nginx-0.1.16-RELEASE import

    *) Bugfix: if the response were transferred by chunks, then on the HEAD
       request the final chunk was issued.

    *) Bugfix: the "Connection: keep-alive" header were issued, even if the
       keepalive_timeout directive forbade the keep-alive use.

    *) Bugfix: the errors in the ngx_http_fastcgi_module caused the
       segmentation faults.

    *) Bugfix: the compressed response encrypted by SSL may not transferred
       complete.

    *) Bugfix: the TCP-specific TCP_NODELAY, TCP_NOPSUH, and TCP_CORK
       options, are not used for the unix domain sockets.

    *) Feature: the rewrite directive supports the arguments rewriting.

    *) Bugfix: the response code 400 was returned for the POST request with
       the "Content-Length: 0" header; the bug had appeared in 0.1.14.
diff --git a/src/http/modules/ngx_http_chunked_filter.c b/src/http/modules/ngx_http_chunked_filter.c
index 5134151..5145ff6 100644
--- a/src/http/modules/ngx_http_chunked_filter.c
+++ b/src/http/modules/ngx_http_chunked_filter.c
@@ -67,7 +67,7 @@
     ngx_buf_t    *b;
     ngx_chain_t   out, tail, *cl, *tl, **ll;
 
-    if (in == NULL || !r->chunked) {
+    if (in == NULL || !r->chunked || r->header_only) {
         return ngx_http_next_body_filter(r, in);
     }
 
diff --git a/src/http/modules/ngx_http_fastcgi_handler.c b/src/http/modules/ngx_http_fastcgi_handler.c
index 41efa0b..9f5016a 100644
--- a/src/http/modules/ngx_http_fastcgi_handler.c
+++ b/src/http/modules/ngx_http_fastcgi_handler.c
@@ -1385,7 +1385,7 @@
                                                ngx_buf_t *buf)
 {
     ngx_int_t                rc;
-    ngx_buf_t               *b;
+    ngx_buf_t               *b, **prev;
     ngx_str_t                line;
     ngx_chain_t             *cl;
     ngx_http_request_t      *r;
@@ -1399,6 +1399,7 @@
     f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
 
     b = NULL;
+    prev = &buf->shadow;
 
     f->pos = buf->pos;
     f->last = buf->last;
@@ -1510,11 +1511,14 @@
         ngx_memzero(b, sizeof(ngx_buf_t));
 
         b->pos = f->pos;
-        b->shadow = buf;
+        b->start = buf->start;
+        b->end = buf->end;
         b->tag = p->tag;
         b->temporary = 1;
         b->recycled = 1;
-        buf->shadow = b;
+
+        *prev = b;
+        prev = &b->shadow;
 
         if (!(cl = ngx_alloc_chain_link(p->pool))) {
             return NGX_ERROR;
@@ -1523,6 +1527,8 @@
         cl->buf = b;
         cl->next = NULL;
 
+        /* STUB */ b->num = buf->num;
+
         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
 
         ngx_chain_add_link(p->in, p->last_in, cl);
@@ -1563,7 +1569,16 @@
     }
 
     if (b) {
+        b->shadow = buf;
         b->last_shadow = 1;
+
+        return NGX_OK;
+    }
+
+    /* there is no data record in the buf, add it to free chain */
+
+    if (ngx_event_pipe_add_free_buf(p, buf) != NGX_OK) {
+        return NGX_ERROR;
     }
 
     return NGX_OK;
diff --git a/src/http/modules/ngx_http_gzip_filter.c b/src/http/modules/ngx_http_gzip_filter.c
index 0cd1d91..cda9ca3 100644
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -471,8 +471,8 @@
 
         /*
          * We preallocate a memory for zlib in one buffer (200K-400K), this
-         * dicreases a number of malloc() and free() calls and also probably
-         * dicreases a number of syscalls (sbrk() and so on).
+         * decreases a number of malloc() and free() calls and also probably
+         * decreases a number of syscalls (sbrk() and so on).
          * Besides we free this memory as soon as the gzipping will complete
          * and do not wait while a whole response will be sent to a client.
          *
diff --git a/src/http/modules/ngx_http_rewrite_handler.c b/src/http/modules/ngx_http_rewrite_handler.c
index 002edb8..636331b 100644
--- a/src/http/modules/ngx_http_rewrite_handler.c
+++ b/src/http/modules/ngx_http_rewrite_handler.c
@@ -9,9 +9,10 @@
 #include <ngx_http.h>
 
 
-#define NGX_HTTP_REWRITE_COPY_MATCH  0
-#define NGX_HTTP_REWRITE_COPY_SHORT  1
-#define NGX_HTTP_REWRITE_COPY_LONG   2
+#define NGX_HTTP_REWRITE_COPY_CAPTURE  0
+#define NGX_HTTP_REWRITE_COPY_SHORT    1
+#define NGX_HTTP_REWRITE_COPY_LONG     2
+#define NGX_HTTP_REWRITE_START_ARGS    3
 
 
 typedef struct {
@@ -119,7 +120,7 @@
     uintptr_t                     data;
     ngx_int_t                     rc;
     ngx_uint_t                    i, m, n;
-    ngx_str_t                     uri;
+    ngx_str_t                     uri, args;
     ngx_http_rewrite_op_t        *op;
     ngx_http_rewrite_rule_t      *rule;
     ngx_http_rewrite_srv_conf_t  *scf;
@@ -176,13 +177,14 @@
         uri.len = rule[i].size;
 
         for (n = 1; n < (ngx_uint_t) rc; n++) {
-           uri.len += captures[2 * n + 1] - captures[2 * n];
+            uri.len += captures[2 * n + 1] - captures[2 * n];
         }
 
         if (!(uri.data = ngx_palloc(r->pool, uri.len))) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
 
+        args.data = NULL;
         p = uri.data;
 
         op = rule[i].ops.elts;
@@ -198,22 +200,34 @@
             } else if (op[n].op == NGX_HTTP_REWRITE_COPY_LONG) {
                 p = ngx_cpymem(p, (void *) op[n].data, op[n].len);
 
-            } else { /* NGX_HTTP_REWRITE_COPY_MATCH */
+            } else if (op[n].op == NGX_HTTP_REWRITE_START_ARGS) {
+                args.data = p;
+
+            } else { /* NGX_HTTP_REWRITE_COPY_CAPTURE */
                 m = 2 * op[n].data;
                 p = ngx_cpymem(p, &r->uri.data[captures[m]],
                                captures[m + 1] - captures[m]);
             }
         }
 
-        uri.len = p - uri.data;
+        if (args.data) {
+            uri.len = args.data - uri.data;
+            args.len = p - args.data;
 
-        if (scf->log) {
-            ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
-                          "rewritten uri: \"%V\"", &uri);
+            r->args = args;
+
+        } else {
+            uri.len = p - uri.data;
+            args.len = 0;
         }
 
         r->uri = uri;
 
+        if (scf->log) {
+            ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+                          "rewritten uri: \"%V\", args: \"%V\"", &uri, &args);
+        }
+
         if (ngx_http_set_exten(r) != NGX_OK) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
@@ -359,7 +373,9 @@
             return NGX_CONF_ERROR;
         }
 
-        for (i = 0; i < value[2].len; /* void */) {
+        i = 0;
+
+        while (i < value[2].len) {
 
             if (!(op = ngx_push_array(&rule->ops))) {
                 return NGX_CONF_ERROR;
@@ -372,7 +388,8 @@
                 && value[2].data[i + 1] >= '1'
                 && value[2].data[i + 1] <= '9')
             {
-                op->op = NGX_HTTP_REWRITE_COPY_MATCH; 
+                op->op = NGX_HTTP_REWRITE_COPY_CAPTURE; 
+                op->len = 0;
                 op->data = value[2].data[++i] - '0';
 
                 if (rule->ncaptures < op->data) {
@@ -381,39 +398,53 @@
 
                 i++;
 
-            } else {
+                continue;
+            }
+
+            if (value[2].data[i] == '?') {
+                op->op = NGX_HTTP_REWRITE_START_ARGS; 
+                op->len = 0;
+                op->data = 0;
+
                 i++;
 
-                while (i < value[2].len && value[2].data[i] != '$') {
-                    i++;
-                }
+                continue;
+            }
 
-                len = &value[2].data[i] - data;
-                rule->size += len;
+            i++;
 
-                if (len) {
+            while (i < value[2].len
+                   && value[2].data[i] != '$'
+                   && value[2].data[i] != '?')
+            {
+                i++;
+            }
 
-                    op->len = len;
+            len = &value[2].data[i] - data;
+            rule->size += len;
 
-                    if (len <= sizeof(uintptr_t)) {
-                        op->op = NGX_HTTP_REWRITE_COPY_SHORT; 
-                        op->data = 0;
+            if (len) {
 
-                        while (len--) {
-                            op->data <<= 8;
-                            op->data |= data[len];
-                        }
+                op->len = len;
 
-                    } else {
-                        op->op = NGX_HTTP_REWRITE_COPY_LONG;
+                if (len <= sizeof(uintptr_t)) {
+                    op->op = NGX_HTTP_REWRITE_COPY_SHORT; 
+                    op->data = 0;
 
-                        if (!(p = ngx_palloc(cf->pool, len))) {
-                            return NGX_CONF_ERROR;
-                        }
-
-                        ngx_memcpy(p, data, len);
-                        op->data = (uintptr_t) p;
+                    while (len--) {
+                        op->data <<= 8;
+                        op->data |= data[len];
                     }
+
+                } else {
+                    op->op = NGX_HTTP_REWRITE_COPY_LONG;
+
+                    if (!(p = ngx_palloc(cf->pool, len))) {
+                        return NGX_CONF_ERROR;
+                    }
+
+                    ngx_memcpy(p, data, len);
+                    op->data = (uintptr_t) p;
                 }
             }
         }
diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c
index 4cc0de1..fa2bcd5 100644
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -76,7 +76,6 @@
     ngx_chain_t                  out;
     ngx_file_info_t              fi;
     ngx_http_cleanup_t          *file_cleanup, *redirect_cleanup;
-    ngx_http_log_ctx_t          *ctx;
     ngx_http_core_loc_conf_t    *clcf;
     ngx_http_static_loc_conf_t  *slcf;
 #if (NGX_HTTP_CACHE)
@@ -476,8 +475,7 @@
 
 #endif
 
-    ctx = log->data;
-    ctx->action = "sending response to client";
+    log->action = "sending response to client";
 
     file_cleanup->data.file.fd = fd;
     file_cleanup->data.file.name = name.data;
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index 3e9383e..ea3a0ca 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -778,17 +778,17 @@
 }
 
 
-u_char *ngx_http_proxy_log_error(void *data, u_char *buf, size_t len)
+u_char *ngx_http_proxy_log_error(ngx_log_t *log, u_char *buf, size_t len)
 {
-    ngx_http_proxy_log_ctx_t *ctx = data;
-
     u_char                          *p;
     ngx_int_t                        escape;
     ngx_str_t                        uri;
     ngx_http_request_t              *r;
     ngx_peer_connection_t           *peer;
+    ngx_http_proxy_log_ctx_t        *ctx;
     ngx_http_proxy_upstream_conf_t  *uc;
 
+    ctx = log->data;
     r = ctx->proxy->request;
     uc = ctx->proxy->lcf->upstream;
     peer = &ctx->proxy->upstream->peer;
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
index 915ca62..4dd97c2 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -251,7 +251,7 @@
 void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev);
 void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p);
 
-u_char *ngx_http_proxy_log_error(void *data, u_char *buf, size_t len);
+u_char *ngx_http_proxy_log_error(ngx_log_t *log, u_char *buf, size_t len);
 void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc);
 void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p);