nginx-0.3.55-RELEASE import

    *) Feature: the "stub" parameter in the "include" SSI command.

    *) Feature: the "block" SSI command.

    *) Feature: the unicode2nginx script was added to contrib.

    *) Bugfix: if a "root" was specified by variable only, then the root
       was relative to a server prefix.

    *) Bugfix: if the request contained "//" or "/./" and escaped symbols
       after them, then the proxied request was sent unescaped.

    *) Bugfix: the $r->headers_in("Cookie") of the ngx_http_perl_module now
       returns all "Cookie" header lines.

    *) Bugfix: a segmentation fault occurred if
       "client_body_in_file_only on" was used and nginx switched to a next
       upstream.

    *) Bugfix: on some condition while reconfiguration character codes
       inside the "charset_map" may be treated invalid; the bug had
       appeared in 0.3.50.
diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c
index b8aa3aa..93c8652 100644
--- a/src/http/modules/ngx_http_access_module.c
+++ b/src/http/modules/ngx_http_access_module.c
@@ -55,7 +55,7 @@
 
 
 
-ngx_http_module_t  ngx_http_access_module_ctx = {
+static ngx_http_module_t  ngx_http_access_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c
index 15231ce..31209f9 100644
--- a/src/http/modules/ngx_http_addition_filter_module.c
+++ b/src/http/modules/ngx_http_addition_filter_module.c
@@ -143,7 +143,7 @@
         ctx->before_body_sent = 1;
 
         if (conf->before_body.len) {
-            if (ngx_http_subrequest(r, &conf->before_body, NULL, 0)
+            if (ngx_http_subrequest(r, &conf->before_body, NULL, NULL, 0)
                 == NGX_ERROR)
             {
                 return NGX_ERROR;
@@ -167,7 +167,7 @@
         return rc;
     }
 
-    if (ngx_http_subrequest(r, &conf->after_body, NULL, 0) == NGX_ERROR) {
+    if (ngx_http_subrequest(r, &conf->after_body, NULL, NULL, 0) == NGX_ERROR) {
         return NGX_ERROR;
     }
 
diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c
index 5dd2876..113527f 100644
--- a/src/http/modules/ngx_http_auth_basic_module.c
+++ b/src/http/modules/ngx_http_auth_basic_module.c
@@ -60,7 +60,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_auth_basic_module_ctx = {
+static ngx_http_module_t  ngx_http_auth_basic_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c
index 5354568..7064f37 100644
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -81,7 +81,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_autoindex_module_ctx = {
+static ngx_http_module_t  ngx_http_autoindex_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c
index e3fdb65..ab6f5ce 100644
--- a/src/http/modules/ngx_http_charset_filter_module.c
+++ b/src/http/modules/ngx_http_charset_filter_module.c
@@ -1325,6 +1325,9 @@
 
     if (ngx_strcasecmp(name->data, "utf-8") == 0) {
         c->utf8 = 1;
+
+    } else {
+        c->utf8 = 0;
     }
 
     return i;
diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c
index 6581e59..4e02194 100644
--- a/src/http/modules/ngx_http_chunked_filter_module.c
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -95,8 +95,11 @@
 
         size += ngx_buf_size(cl->buf);
 
-        if (cl->buf->flush || ngx_buf_in_memory(cl->buf) || cl->buf->in_file) {
-
+        if (cl->buf->flush
+            || cl->buf->sync
+            || ngx_buf_in_memory(cl->buf)
+            || cl->buf->in_file)
+        {
             tl = ngx_alloc_chain_link(r->pool);
             if (tl == NULL) {
                 return NGX_ERROR;
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index 53ef21c..0ea937f 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -57,7 +57,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_dav_module_ctx = {
+static ngx_http_module_t  ngx_http_dav_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_empty_gif_module.c b/src/http/modules/ngx_http_empty_gif_module.c
index b97633a..69b6c89 100644
--- a/src/http/modules/ngx_http_empty_gif_module.c
+++ b/src/http/modules/ngx_http_empty_gif_module.c
@@ -74,7 +74,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_empty_gif_module_ctx = {
+static ngx_http_module_t  ngx_http_empty_gif_module_ctx = {
     NULL,                          /* preconfiguration */
     NULL,                          /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 28f860e..8d5ef95 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -347,7 +347,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_fastcgi_module_ctx = {
+static ngx_http_module_t  ngx_http_fastcgi_module_ctx = {
     ngx_http_fastcgi_add_variables,        /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c
index 4ef2910..b93e6fb 100644
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -72,7 +72,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_index_module_ctx = {
+static ngx_http_module_t  ngx_http_index_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c
index f85a6c8..c81ad2e 100644
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -142,7 +142,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_log_module_ctx = {
+static ngx_http_module_t  ngx_http_log_module_ctx = {
     ngx_http_log_set_formats,              /* preconfiguration */
     ngx_http_log_init,                     /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c
index 4373692..61a9502 100644
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -112,7 +112,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_memcached_module_ctx = {
+static ngx_http_module_t  ngx_http_memcached_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 5999f2e..a6adc3c 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -327,7 +327,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_proxy_module_ctx = {
+static ngx_http_module_t  ngx_http_proxy_module_ctx = {
     ngx_http_proxy_add_variables,          /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c
index 3940ee4..8f128d2 100644
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -61,7 +61,7 @@
 
 
 
-ngx_http_module_t  ngx_http_realip_module_ctx = {
+static ngx_http_module_t  ngx_http_realip_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c
index 88988bd..980de19 100644
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -102,7 +102,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_rewrite_module_ctx = {
+static ngx_http_module_t  ngx_http_rewrite_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 5a65a03..ef870be 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -36,6 +36,13 @@
 } ngx_http_ssi_var_t;
 
 
+typedef struct {
+    ngx_str_t     name;
+    ngx_chain_t  *bufs;
+    ngx_uint_t    count;
+} ngx_http_ssi_block_t;
+
+
 typedef enum {
     ssi_start_state = 0,
     ssi_tag_state,
@@ -83,6 +90,10 @@
     ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
 static ngx_int_t ngx_http_ssi_endif(ngx_http_request_t *r,
     ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_block(ngx_http_request_t *r,
+    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_endblock(ngx_http_request_t *r,
+    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
 
 static ngx_int_t ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v,  uintptr_t gmt);
@@ -189,6 +200,7 @@
 #define  NGX_HTTP_SSI_INCLUDE_VIRTUAL  0
 #define  NGX_HTTP_SSI_INCLUDE_FILE     1
 #define  NGX_HTTP_SSI_INCLUDE_WAIT     2
+#define  NGX_HTTP_SSI_INCLUDE_STUB     3
 
 #define  NGX_HTTP_SSI_ECHO_VAR         0
 #define  NGX_HTTP_SSI_ECHO_DEFAULT     1
@@ -201,11 +213,14 @@
 
 #define  NGX_HTTP_SSI_IF_EXPR          0
 
+#define  NGX_HTTP_SSI_BLOCK_NAME       0
+
 
 static ngx_http_ssi_param_t  ngx_http_ssi_include_params[] = {
     { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0, 0 },
     { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0, 0 },
     { ngx_string("wait"), NGX_HTTP_SSI_INCLUDE_WAIT, 0, 0 },
+    { ngx_string("stub"), NGX_HTTP_SSI_INCLUDE_STUB, 0, 0 },
     { ngx_null_string, 0, 0, 0 }
 };
 
@@ -237,6 +252,12 @@
 };
 
 
+static ngx_http_ssi_param_t  ngx_http_ssi_block_params[] = {
+    { ngx_string("name"), NGX_HTTP_SSI_BLOCK_NAME, 1, 0 },
+    { ngx_null_string, 0, 0, 0 }
+};
+
+
 static ngx_http_ssi_param_t  ngx_http_ssi_no_params[] = {
     { ngx_null_string, 0, 0, 0 }
 };
@@ -244,21 +265,27 @@
 
 static ngx_http_ssi_command_t  ngx_http_ssi_commands[] = {
     { ngx_string("include"), ngx_http_ssi_include,
-                       ngx_http_ssi_include_params, 0, 1 },
-    { ngx_string("echo"), ngx_http_ssi_echo, ngx_http_ssi_echo_params, 0, 0 },
+                       ngx_http_ssi_include_params, 0, 0, 1 },
+    { ngx_string("echo"), ngx_http_ssi_echo,
+                       ngx_http_ssi_echo_params, 0, 0, 0 },
     { ngx_string("config"), ngx_http_ssi_config,
-                       ngx_http_ssi_config_params, 0, 0 },
-    { ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0 },
+                       ngx_http_ssi_config_params, 0, 0, 0 },
+    { ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0, 0 },
 
-    { ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0 },
+    { ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0, 0 },
     { ngx_string("elif"), ngx_http_ssi_if, ngx_http_ssi_if_params,
-                       NGX_HTTP_SSI_COND_IF, 0 },
+                       NGX_HTTP_SSI_COND_IF, 0, 0 },
     { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params,
-                       NGX_HTTP_SSI_COND_IF, 0 },
+                       NGX_HTTP_SSI_COND_IF, 0, 0 },
     { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params,
-                       NGX_HTTP_SSI_COND_ELSE, 0 },
+                       NGX_HTTP_SSI_COND_ELSE, 0, 0 },
 
-    { ngx_null_string, NULL, NULL, 0, 0 }
+    { ngx_string("block"), ngx_http_ssi_block,
+                       ngx_http_ssi_block_params, 0, 0, 0 },
+    { ngx_string("endblock"), ngx_http_ssi_endblock,
+                       ngx_http_ssi_no_params, 0, 1, 0 },
+
+    { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
 
 
@@ -348,13 +375,15 @@
 static ngx_int_t
 ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
 {
+    size_t                     len;
     ngx_int_t                  rc;
     ngx_buf_t                 *b;
     ngx_uint_t                 i, index;
-    ngx_chain_t               *cl;
+    ngx_chain_t               *cl, **ll;
     ngx_table_elt_t           *param;
     ngx_connection_t          *c;
-    ngx_http_ssi_ctx_t        *ctx;
+    ngx_http_ssi_ctx_t        *ctx, *mctx;
+    ngx_http_ssi_block_t      *bl;
     ngx_http_ssi_param_t      *prm;
     ngx_http_ssi_command_t    *cmd;
     ngx_http_ssi_loc_conf_t   *slcf;
@@ -510,6 +539,47 @@
                     ctx->last_out = &cl->next;
 
                 } else {
+                    if (ctx->block
+                        && ctx->saved + (ctx->copy_end - ctx->copy_start))
+                    {
+                        b = ngx_create_temp_buf(r->pool,
+                               ctx->saved + (ctx->copy_end - ctx->copy_start));
+
+                        if (b == NULL) {
+                            return NGX_ERROR;
+                        }
+
+                        if (ctx->saved) {
+                            b->last = ngx_cpymem(b->pos, ngx_http_ssi_string,
+                                                 ctx->saved);
+                        }
+
+                        b->last = ngx_cpymem(b->last, ctx->copy_start,
+                                             ctx->copy_end - ctx->copy_start);
+
+                        cl = ngx_alloc_chain_link(r->pool);
+                        if (cl == NULL) {
+                            return NGX_ERROR;
+                        }
+
+                        cl->buf = b;
+                        cl->next = NULL;
+
+                        b = NULL;
+
+                        mctx = ngx_http_get_module_ctx(r->main,
+                                                   ngx_http_ssi_filter_module);
+                        bl = mctx->blocks->elts;
+                        for (ll = &bl[mctx->blocks->nelts - 1].bufs;
+                             *ll;
+                             ll = &(*ll)->next)
+                        {
+                            /* void */
+                        }
+
+                        *ll = cl;
+                    }
+
                     ctx->saved = 0;
                 }
             }
@@ -559,8 +629,79 @@
                     goto ssi_error;
                 }
 
-                if (!ctx->output && cmd->conditional == 0) {
-                    continue;
+                if (!ctx->output && !cmd->block) {
+
+                    if (ctx->block) {
+
+                        /* reconstruct the SSI command text */
+
+                        len = 5 + ctx->command.len + 4;
+
+                        param = ctx->params.elts;
+                        for (i = 0; i < ctx->params.nelts; i++) {
+                            len += 1 + param[i].key.len + 2
+                                + param[i].value.len + 1;
+                        }
+
+                        b = ngx_create_temp_buf(r->pool, len);
+
+                        if (b == NULL) {
+                            return NGX_ERROR;
+                        }
+
+                        cl = ngx_alloc_chain_link(r->pool);
+                        if (cl == NULL) {
+                            return NGX_ERROR;
+                        }
+
+                        cl->buf = b;
+                        cl->next = NULL;
+
+                        *b->last++ = '<';
+                        *b->last++ = '!';
+                        *b->last++ = '-';
+                        *b->last++ = '-';
+                        *b->last++ = '#';
+
+                        b->last = ngx_cpymem(b->last, ctx->command.data,
+                                             ctx->command.len);
+
+                        for (i = 0; i < ctx->params.nelts; i++) {
+                            *b->last++ = ' ';
+                            b->last = ngx_cpymem(b->last, param[i].key.data,
+                                                 param[i].key.len);
+                            *b->last++ = '=';
+                            *b->last++ = '"';
+                            b->last = ngx_cpymem(b->last, param[i].value.data,
+                                                 param[i].value.len);
+                            *b->last++ = '"';
+                        }
+
+                        *b->last++ = ' ';
+                        *b->last++ = '-';
+                        *b->last++ = '-';
+                        *b->last++ = '>';
+
+                        mctx = ngx_http_get_module_ctx(r->main,
+                                                   ngx_http_ssi_filter_module);
+                        bl = mctx->blocks->elts;
+                        for (ll = &bl[mctx->blocks->nelts - 1].bufs;
+                             *ll;
+                             ll = &(*ll)->next)
+                        {
+                            /* void */
+                        }
+
+                        *ll = cl;
+
+                        b = NULL;
+
+                        continue;
+                    }
+
+                    if (cmd->conditional == 0) {
+                        continue;
+                    }
                 }
 
                 if (ctx->params.nelts > NGX_HTTP_SSI_MAX_PARAMS) {
@@ -1382,8 +1523,12 @@
 
     ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
 
-    var = ctx->variables.elts;
-    for (i = 0; i < ctx->variables.nelts; i++) {
+    if (ctx->variables == NULL) {
+        return NULL;
+    }
+
+    var = ctx->variables->elts;
+    for (i = 0; i < ctx->variables->nelts; i++) {
         if (name->len != var[i].name.len) {
             continue;
         }
@@ -1663,13 +1808,18 @@
 ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
     ngx_str_t **params)
 {
-    ngx_int_t    rc;
-    ngx_str_t   *uri, *file, *wait, args;
-    ngx_uint_t   flags;
+    ngx_int_t              rc;
+    ngx_str_t             *uri, *file, *wait, *stub, args;
+    ngx_buf_t             *b;
+    ngx_uint_t             flags, i;
+    ngx_chain_t           *out, *cl, *tl, **ll;
+    ngx_http_ssi_ctx_t    *mctx;
+    ngx_http_ssi_block_t  *bl;
 
     uri = params[NGX_HTTP_SSI_INCLUDE_VIRTUAL];
     file = params[NGX_HTTP_SSI_INCLUDE_FILE];
     wait = params[NGX_HTTP_SSI_INCLUDE_WAIT];
+    stub = params[NGX_HTTP_SSI_INCLUDE_STUB];
 
     if (uri && file) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
@@ -1687,8 +1837,7 @@
     if (wait) {
         if (uri == NULL) {
             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                          "\"wait\" may not be used with file=\"%V\"",
-                          uri, file);
+                          "\"wait\" may not be used with file=\"%V\"", file);
             return NGX_HTTP_SSI_ERROR;
         }
 
@@ -1699,7 +1848,7 @@
         {
             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                           "invalid value \"%V\" in the \"wait\" parameter",
-                          &wait);
+                          wait);
             return NGX_HTTP_SSI_ERROR;
         }
     }
@@ -1725,7 +1874,68 @@
         return NGX_HTTP_SSI_ERROR;
     }
 
-    rc = ngx_http_subrequest(r, uri, &args, flags);
+    out = NULL;
+
+    if (stub) {
+        mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+
+        if (mctx->blocks) {
+            bl = mctx->blocks->elts;
+            for (i = 0; i < mctx->blocks->nelts; i++) {
+                if (stub->len == bl[i].name.len
+                    && ngx_strncmp(stub->data, bl[i].name.data, stub->len) == 0)
+                {
+                    goto found;
+                }
+            }
+        }
+
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "\"stub\"=\"%V\" for \"include\" not found", stub);
+        return NGX_HTTP_SSI_ERROR;
+
+    found:
+
+        if (bl[i].count++) {
+
+            ll = &out;
+
+            for (tl = bl[i].bufs; tl; tl = tl->next) {
+
+                if (ctx->free) {
+                    cl = ctx->free;
+                    ctx->free = ctx->free->next;
+                    b = cl->buf;
+
+                } else {
+                    b = ngx_alloc_buf(r->pool);
+                    if (b == NULL) {
+                        return NGX_ERROR;
+                    }
+
+                    cl = ngx_alloc_chain_link(r->pool);
+                    if (cl == NULL) {
+                        return NGX_ERROR;
+                    }
+
+                    cl->buf = b;
+                }
+
+                ngx_memcpy(b, tl->buf, sizeof(ngx_buf_t));
+
+                b->pos = b->start;
+
+                *ll = cl;
+                cl->next = NULL;
+                ll = &cl->next;
+            }
+
+        } else {
+            out = bl[i].bufs;
+        }
+    }
+
+    rc = ngx_http_subrequest(r, uri, &args, out, flags);
 
     if (rc == NGX_ERROR) {
         return NGX_HTTP_SSI_ERROR;
@@ -1861,10 +2071,10 @@
 
     mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
 
-    if (mctx->variables.elts == NULL) {
-        if (ngx_array_init(&mctx->variables, r->pool, 4,
-                           sizeof(ngx_http_ssi_var_t)) != NGX_OK)
-        {
+    if (mctx->variables == NULL) {
+        mctx->variables = ngx_array_create(r->pool, 4,
+                                           sizeof(ngx_http_ssi_var_t));
+        if (mctx->variables == NULL) {
             return NGX_HTTP_SSI_ERROR;
         }
     }
@@ -1893,7 +2103,7 @@
         return NGX_OK;
     }
 
-    var = ngx_array_push(&mctx->variables);
+    var = ngx_array_push(mctx->variables);
     if (var == NULL) {
         return NGX_HTTP_SSI_ERROR;
     }
@@ -2136,6 +2346,56 @@
 
 
 static ngx_int_t
+ngx_http_ssi_block(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+    ngx_str_t **params)
+{
+    ngx_http_ssi_ctx_t    *mctx;
+    ngx_http_ssi_block_t  *bl;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "ssi block");
+
+    mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+
+    if (mctx->blocks == NULL) {
+        mctx->blocks = ngx_array_create(r->pool, 4,
+                                        sizeof(ngx_http_ssi_block_t));
+        if (mctx->blocks == NULL) {
+            return NGX_HTTP_SSI_ERROR;
+        }
+    }
+
+    bl = ngx_array_push(mctx->blocks);
+    if (bl == NULL) {
+        return NGX_HTTP_SSI_ERROR;
+    }
+
+    bl->name = *params[NGX_HTTP_SSI_BLOCK_NAME];
+    bl->bufs = NULL;
+    bl->count = 0;
+
+    ctx->output = 0;
+    ctx->block = 1;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_endblock(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+    ngx_str_t **params)
+{
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "ssi endblock");
+
+    ctx->output = 1;
+    ctx->block = 0;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
 ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v,  uintptr_t gmt)
 {
diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h
index 0d9618b..dc3eff0 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.h
+++ b/src/http/modules/ngx_http_ssi_filter_module.h
@@ -56,9 +56,11 @@
 
     size_t                    value_len;
 
-    ngx_array_t               variables;
+    ngx_array_t              *variables;
+    ngx_array_t              *blocks;
 
     unsigned                  conditional:2;
+    unsigned                  block:1;
     unsigned                  output:1;
     unsigned                  output_chosen:1;
     unsigned                  wait:1;
@@ -88,6 +90,7 @@
     ngx_http_ssi_param_t     *params;
 
     unsigned                  conditional:2;
+    unsigned                  block:1;
     unsigned                  flush:1;
 } ngx_http_ssi_command_t;
 
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index a57fbfb..8c78e0f 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -85,7 +85,7 @@
       NULL },
 
     { ngx_string("ssl_verify_client"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
       NGX_HTTP_SRV_CONF_OFFSET,
       offsetof(ngx_http_ssl_srv_conf_t, verify),
diff --git a/src/http/modules/ngx_http_status_module.c b/src/http/modules/ngx_http_status_module.c
index cf4f33f..a2e2dbc 100644
--- a/src/http/modules/ngx_http_status_module.c
+++ b/src/http/modules/ngx_http_status_module.c
@@ -36,7 +36,7 @@
 
 
 
-ngx_http_module_t  ngx_http_status_module_ctx = {
+static ngx_http_module_t  ngx_http_status_module_ctx = {
     NULL,                                  /* pre conf */
 
     NULL,                                  /* create main configuration */
diff --git a/src/http/modules/ngx_http_stub_status_module.c b/src/http/modules/ngx_http_stub_status_module.c
index 7cdb3c1..4fe9c04 100644
--- a/src/http/modules/ngx_http_stub_status_module.c
+++ b/src/http/modules/ngx_http_stub_status_module.c
@@ -26,7 +26,7 @@
 
 
 
-ngx_http_module_t  ngx_http_stub_status_module_ctx = {
+static ngx_http_module_t  ngx_http_stub_status_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c
index bdad35d..648f1ad 100644
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -160,7 +160,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_userid_filter_module_ctx = {
+static ngx_http_module_t  ngx_http_userid_filter_module_ctx = {
     ngx_http_userid_add_variables,         /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index 735cc37..8e287a6 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -199,13 +199,16 @@
     CODE:
 
     dXSTARG;
-    ngx_http_request_t  *r;
-    SV                  *key;
-    u_char              *p;
-    STRLEN               len;
-    ngx_uint_t           i;
-    ngx_list_part_t     *part;
-    ngx_table_elt_t     *header;
+    ngx_http_request_t         *r;
+    SV                         *key;
+    u_char                     *p, *lowcase_key, *cookie;
+    STRLEN                      len;
+    ssize_t                     size;
+    ngx_uint_t                  i, n, hash;
+    ngx_list_part_t            *part;
+    ngx_table_elt_t            *h, **ph;
+    ngx_http_header_t          *hh;
+    ngx_http_core_main_conf_t  *cmcf;
 
     ngx_http_perl_set_request(r);
 
@@ -217,8 +220,85 @@
 
     p = (u_char *) SvPV(key, len);
 
+    /* look up hashed headers */
+
+    lowcase_key = ngx_palloc(r->pool, len);
+    if (lowcase_key == NULL) {
+        XSRETURN_UNDEF;
+    }
+
+    hash = 0;
+    for (i = 0; i < len; i++) {
+        lowcase_key[i] = ngx_tolower(p[i]);
+        hash = ngx_hash(hash, lowcase_key[i]);
+    }
+
+    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+    hh = ngx_hash_find(&cmcf->headers_in_hash, hash, lowcase_key, len);
+
+    if (hh) {
+        if (hh->offset) {
+
+            ph = (ngx_table_elt_t **) ((char *) &r->headers_in + hh->offset);
+
+            if (*ph) {
+                ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len, 0);
+
+                goto done;
+            }
+
+            XSRETURN_UNDEF;
+        }
+
+        /* Cookie */
+
+        n = r->headers_in.cookies.nelts;
+
+        if (n == 0) {
+            XSRETURN_UNDEF;
+        }
+
+        ph = r->headers_in.cookies.elts;
+
+        if (n == 1) {
+            ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len, 0);
+
+            goto done;
+        }
+
+        size = - (ssize_t) (sizeof("; ") - 1);
+
+        for (i = 0; i < n; i++) {
+            size += ph[i]->value.len + sizeof("; ") - 1;
+        }
+
+        cookie = ngx_palloc(r->pool, size);
+        if (cookie == NULL) {
+            XSRETURN_UNDEF;
+        }
+
+        p = cookie;
+
+        for (i = 0; /* void */ ; i++) {
+            p = ngx_copy(p, ph[i]->value.data, ph[i]->value.len);
+
+            if (i == n - 1) {
+                break;
+            }
+
+            *p++ = ';'; *p++ = ' ';
+        }
+
+        ngx_http_perl_set_targ(cookie, size, 0);
+
+        goto done;
+    }
+
+    /* iterate over all headers */
+
     part = &r->headers_in.headers.part;
-    header = part->elts;
+    h = part->elts;
 
     for (i = 0; /* void */ ; i++) {
 
@@ -228,17 +308,17 @@
             }
 
             part = part->next;
-            header = part->elts;
+            h = part->elts;
             i = 0;
         }
 
-        if (len != header[i].key.len
-            || ngx_strcasecmp(p, header[i].key.data) != 0)
+        if (len != h[i].key.len
+            || ngx_strcasecmp(p, h[i].key.data) != 0)
         {
             continue;
         }
 
-        ngx_http_perl_set_targ(header[i].value.data, header[i].value.len, 0);
+        ngx_http_perl_set_targ(h[i].value.data, h[i].value.len, 0);
 
         goto done;
     }
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index bf976e9..b3e1175 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -170,7 +170,7 @@
 };
 
 static ngx_http_ssi_command_t  ngx_http_perl_ssi_command = {
-    ngx_string("perl"), ngx_http_perl_ssi, ngx_http_perl_ssi_params, 0, 1
+    ngx_string("perl"), ngx_http_perl_ssi, ngx_http_perl_ssi_params, 0, 0, 1
 };
 
 #endif
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index 867f8f7..41720f2 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -84,9 +84,6 @@
 
 ngx_int_t ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags);
 
-u_char * ngx_http_log_error_info(ngx_http_request_t *r, u_char *buf,
-    size_t len);
-
 
 ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r,
     ngx_http_client_body_handler_pt post_handler);
diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c
index bba3f5d..87612eb 100644
--- a/src/http/ngx_http_copy_filter_module.c
+++ b/src/http/ngx_http_copy_filter_module.c
@@ -104,6 +104,7 @@
         ctx->output_filter = (ngx_output_chain_filter_pt) ngx_http_next_filter;
         ctx->filter_ctx = r;
 
+        r->request_output = 1;
     }
 
     rc = ngx_output_chain(ctx, in);
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index ee0d3ca..eb4934e 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -426,7 +426,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_core_module_ctx = {
+static ngx_http_module_t  ngx_http_core_module_ctx = {
     ngx_http_core_preconfiguration,        /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
@@ -1071,13 +1071,19 @@
         last = ngx_copy(path->data, clcf->root.data, clcf->root.len);
 
     } else {
-        last = ngx_http_script_run(r, path, clcf->root_lengths->elts, reserved,
-                                   clcf->root_values->elts);
-        if (last == NULL) {
+        if (ngx_http_script_run(r, path, clcf->root_lengths->elts, reserved,
+                               clcf->root_values->elts)
+            == NULL)
+        {
+            return NULL;
+        }
+
+        if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path) == NGX_ERROR) {
             return NULL;
         }
 
         r->root_length = path->len - reserved;
+        last = path->data + r->root_length;
     }
 
     last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1);
@@ -1158,7 +1164,7 @@
 
 ngx_int_t
 ngx_http_subrequest(ngx_http_request_t *r,
-    ngx_str_t *uri, ngx_str_t *args, ngx_uint_t flags)
+    ngx_str_t *uri, ngx_str_t *args, ngx_chain_t *out, ngx_uint_t flags)
 {
     ngx_connection_t              *c;
     ngx_http_request_t            *sr;
@@ -1239,6 +1245,7 @@
         return NGX_ERROR;
     }
 
+    sr->out = out;
     sr->main = r->main;
     sr->parent = r;
     sr->read_event_handler = ngx_http_request_empty_handler;
@@ -2527,8 +2534,10 @@
         lcf->root.len--;
     }
 
-    if (ngx_conf_full_name(cf->cycle, &lcf->root) == NGX_ERROR) {
-        return NGX_CONF_ERROR;
+    if (lcf->root.data[0] != '$') {
+        if (ngx_conf_full_name(cf->cycle, &lcf->root) == NGX_ERROR) {
+            return NGX_CONF_ERROR;
+        }
     }
 
     n = ngx_http_script_variables_count(&lcf->root);
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 661f1b9..5ea8103 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -267,7 +267,7 @@
 ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r);
 
 ngx_int_t ngx_http_subrequest(ngx_http_request_t *r,
-    ngx_str_t *uri, ngx_str_t *args, ngx_uint_t flags);
+    ngx_str_t *uri, ngx_str_t *args, ngx_chain_t *out, ngx_uint_t flags);
 ngx_int_t ngx_http_internal_redirect(ngx_http_request_t *r,
     ngx_str_t *uri, ngx_str_t *args);
 
@@ -283,7 +283,6 @@
 ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *chain);
 
 
-extern ngx_http_module_t  ngx_http_core_module_ctx;
 extern ngx_module_t  ngx_http_core_module;
 
 extern ngx_uint_t ngx_http_max_module;
diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c
index c6ecd3a..ac4543b 100644
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -159,6 +159,8 @@
     ngx_table_elt_t           *header;
     ngx_http_core_loc_conf_t  *clcf;
 
+    r->header_sent = 1;
+
     if (r != r->main) {
         return NGX_OK;
     }
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index 24b7f8c..6017414 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -969,6 +969,8 @@
 #endif
 
         case sw_quoted:
+            r->quoted_uri = 1;
+
             if (ch >= '0' && ch <= '9') {
                 decoded = (u_char) (ch - '0');
                 state = sw_quoted_second;
diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c
index 37d200c..95bbdfa 100644
--- a/src/http/ngx_http_postpone_filter_module.c
+++ b/src/http/ngx_http_postpone_filter_module.c
@@ -127,7 +127,6 @@
         || (r->connection->buffered
             & (NGX_HTTP_LOWLEVEL_BUFFERED|NGX_LOWLEVEL_BUFFERED)))
     {
-
         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                        "http postpone filter out \"%V?%V\"", &r->uri, &r->args);
 
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 0145fe7..e645e81 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -853,7 +853,7 @@
 
             } else {
                 for (i = 0; i < h->key.len; i++) {
-                    h->lowcase_key[i] = ngx_tolower(h->lowcase_key[i]);
+                    h->lowcase_key[i] = ngx_tolower(h->key.data[i]);
                 }
             }
 
@@ -1459,6 +1459,28 @@
                    "http finalize request: %d, \"%V?%V\"",
                    rc, &r->uri, &r->args);
 
+    if (r != r->main
+        && rc != NGX_ERROR
+        && !r->connection->error
+        && !r->request_output
+        && r->out)
+    {
+        if (!r->header_sent) {
+            rc = ngx_http_set_content_type(r);
+
+            if (rc == NGX_OK) {
+                rc = ngx_http_send_header(r);
+
+                if (rc != NGX_ERROR) {
+                    rc = ngx_http_output_filter(r, r->out);
+                }
+            }
+
+        } else {
+            rc = ngx_http_output_filter(r, r->out);
+        }
+    }
+
     if (rc == NGX_ERROR
         || rc == NGX_HTTP_REQUEST_TIME_OUT
         || r->connection->error)
@@ -2435,15 +2457,6 @@
         buf = p;
     }
 
-    return ngx_http_log_error_info(r, buf, len);
-}
-
-
-u_char *
-ngx_http_log_error_info(ngx_http_request_t *r, u_char *buf, size_t len)
-{
-    u_char  *p;
-
     if (r->headers_in.host) {
         p = ngx_snprintf(buf, len, ", host: \"%V\"",
                          &r->headers_in.host->value);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index b2d4184..fa8fd0f 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -437,6 +437,8 @@
     unsigned                          internal:1;
     unsigned                          post_action:1;
     unsigned                          request_complete:1;
+    unsigned                          request_output:1;
+    unsigned                          header_sent:1;
     unsigned                          done:1;
     unsigned                          utf8:1;
 
diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c
index 5cc4d52..460cf39 100644
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -92,6 +92,8 @@
         rb->bufs->buf = b;
         rb->bufs->next = NULL;
 
+        rb->buf = b;
+
         if ((off_t) preread >= r->headers_in.content_length_n) {
 
             /* the whole request body was pre-read */
@@ -124,8 +126,6 @@
 
             /* the whole request body may be placed in r->header_in */
 
-            rb->buf = b;
-
             r->read_event_handler = ngx_http_read_client_request_body_handler;
 
             return ngx_http_do_read_client_request_body(r);
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 5caad00..8ca24e2 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -1394,6 +1394,7 @@
     if (u->cachable) {
         p->temp_file->persistent = 1;
     } else {
+        p->temp_file->log_level = NGX_LOG_WARN;
         p->temp_file->warn = "an upstream response is buffered "
                              "to a temporary file";
     }
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 8aaee45..f151f87 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -523,15 +523,17 @@
 ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
     uintptr_t data)
 {
-    size_t             len;
+    ssize_t            len;
     u_char            *p;
-    ngx_uint_t         i;
+    ngx_uint_t         i, n;
     ngx_array_t       *a;
     ngx_table_elt_t  **h;
 
     a = (ngx_array_t *) ((char *) r + data);
 
-    if (a->nelts == 0) {
+    n = a->nelts;
+
+    if (n == 0) {
         v->not_found = 1;
         return NGX_OK;
     }
@@ -542,16 +544,16 @@
 
     h = a->elts;
 
-    if (a->nelts == 1) {
+    if (n == 1) {
         v->len = (*h)->value.len;
         v->data = (*h)->value.data;
 
         return NGX_OK;
     }
 
-    len = (size_t) - (ssize_t) (sizeof("; ") - 1);
+    len = - (ssize_t) (sizeof("; ") - 1);
 
-    for (i = 0; i < a->nelts; i++) {
+    for (i = 0; i < n; i++) {
         len += h[i]->value.len + sizeof("; ") - 1;
     }
 
@@ -566,7 +568,7 @@
     for (i = 0; /* void */ ; i++) {
         p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
 
-        if (i == a->nelts - 1) {
+        if (i == n - 1) {
             break;
         }
 
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
index 3d991c7..0ff2db3 100644
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -13,7 +13,7 @@
 static ngx_int_t ngx_http_write_filter_init(ngx_cycle_t *cycle);
 
 
-ngx_http_module_t  ngx_http_write_filter_module_ctx = {
+static ngx_http_module_t  ngx_http_write_filter_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
@@ -69,7 +69,7 @@
     for (cl = r->out; cl; cl = cl->next) {
         ll = &cl->next;
 
-        ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
+        ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
                        "write old buf t:%d f:%d %p, pos %p, size: %z "
                        "file: %O, size: %z",
                        cl->buf->temporary, cl->buf->in_file,
@@ -80,7 +80,7 @@
 
 #if 1
         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
-            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+            ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                           "zero size buf in writer "
                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
                           cl->buf->temporary,
@@ -121,7 +121,7 @@
         *ll = cl;
         ll = &cl->next;
 
-        ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
+        ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
                        "write new buf t:%d f:%d %p, pos %p, size: %z "
                        "file: %O, size: %z",
                        cl->buf->temporary, cl->buf->in_file,
@@ -132,7 +132,7 @@
 
 #if 1
         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
-            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+            ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                           "zero size buf in writer "
                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
                           cl->buf->temporary,
@@ -201,7 +201,7 @@
             return NGX_OK;
         }
 
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+        ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                       "the http output chain is empty");
 
         ngx_debug_point();
@@ -214,8 +214,8 @@
 
         if (to_send <= 0) {
             c->write->delayed = 1;
-            ngx_add_timer(r->connection->write,
-                       (ngx_msec_t) (- to_send * 1000 / r->limit_rate + 1));
+            ngx_add_timer(c->write,
+                          (ngx_msec_t) (- to_send * 1000 / r->limit_rate + 1));
 
             c->buffered |= NGX_HTTP_WRITE_BUFFERED;
 
@@ -244,8 +244,7 @@
     if (to_send) {
         sent = c->sent - sent;
         c->write->delayed = 1;
-        ngx_add_timer(r->connection->write,
-                      (ngx_msec_t) (sent * 1000 / r->limit_rate + 1));
+        ngx_add_timer(c->write, (ngx_msec_t) (sent * 1000 / r->limit_rate + 1));
     }
 
     for (cl = r->out; cl && cl != chain; /* void */) {