nginx-0.1.11-RELEASE import

    *) Feature: the worker_priority directive.

    *) Change: both tcp_nopush and tcp_nodelay directives affect the
       transferred response.

    *) Bugfix: nginx did not call initgroups().
       Thanks to Andrew Sitnikov and Andrei Nigmatulin.

    *) Change: now the ngx_http_autoindex_module shows the file size in the
       bytes.

    *) Bugfix: the ngx_http_autoindex_module returned the 500 error if the
       broken symlink was in a directory.

    *) Bugfix: the files bigger than 4G could not be transferred using
       sendfile.

    *) Bugfix: if the backend was resolved to several backends and there
       was an error while the response waiting then process may got caught
       in an endless loop.

    *) Bugfix: the worker process may exit with the "unknown cycle" message
       when the /dev/poll method was used.

    *) Bugfix: "close() channel failed" errors.

    *) Bugfix: the autodetection of the "nobody" and "nogroup" groups.

    *) Bugfix: the send_lowat directive did not work on Linux.

    *) Bugfix: the segmentation fault occurred if there was no events
       section in configuration.

    *) Bugfix: nginx could not be built on OpenBSD.

    *) Bugfix: the double slashes in "://" in the URI were converted to
       ":/".
diff --git a/src/http/modules/ngx_http_autoindex_handler.c b/src/http/modules/ngx_http_autoindex_handler.c
index f5ec970..ac2438e 100644
--- a/src/http/modules/ngx_http_autoindex_handler.c
+++ b/src/http/modules/ngx_http_autoindex_handler.c
@@ -105,11 +105,10 @@
 
 static ngx_int_t ngx_http_autoindex_handler(ngx_http_request_t *r)
 {
-    u_char                         *last, scale;
+    u_char                         *last;
     size_t                          len;
-    off_t                           length;
     ngx_tm_t                        tm;
-    ngx_int_t                       rc, size;
+    ngx_int_t                       rc;
     ngx_uint_t                      i, level;
     ngx_err_t                       err;
     ngx_buf_t                      *b;
@@ -307,7 +306,7 @@
                + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof(">") - 2
                + sizeof("</a>") - 1
                + sizeof(" 28-Sep-1970 12:00 ") - 1
-               + sizeof("1023G") - 1
+               + 19
                + 2;
     }
 
@@ -383,44 +382,11 @@
                               tm.ngx_tm_min);
 
         if (entry[i].dir) {
-            b->last = ngx_cpymem(b->last, "   -", sizeof("   -") - 1);
+            b->last = ngx_cpymem(b->last,  "                  -",
+                                 sizeof("                  -") - 1);
 
         } else {
-            length = entry[i].size;
-
-            if (length > 1024 * 1024 * 1024 - 1) {
-                size = (ngx_int_t) (length / (1024 * 1024 * 1024));
-                if ((length % (1024 * 1024 * 1024))
-                                                > (1024 * 1024 * 1024 / 2 - 1))
-                {
-                    size++;
-                }
-                scale = 'G';
-
-            } else if (length > 1024 * 1024 - 1) {
-                size = (ngx_int_t) (length / (1024 * 1024));
-                if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) {
-                    size++;
-                }
-                scale = 'M';
-
-            } else if (length > 9999) {
-                size = (ngx_int_t) (length / 1024);
-                if (length % 1024 > 511) {
-                    size++;
-                }
-                scale = 'K';
-
-            } else {
-                size = (ngx_int_t) length;
-                scale = ' ';
-            }
-
-            b->last = ngx_sprintf(b->last, "%4i", size);
-
-            if (scale != ' ') {
-                *b->last++ = scale;
-            }
+            b->last = ngx_sprintf(b->last, "%19O", entry[i].size);
         }
 
         *b->last++ = CR;
diff --git a/src/http/modules/ngx_http_chunked_filter.c b/src/http/modules/ngx_http_chunked_filter.c
index 929a7ed..5134151 100644
--- a/src/http/modules/ngx_http_chunked_filter.c
+++ b/src/http/modules/ngx_http_chunked_filter.c
@@ -63,7 +63,7 @@
                                               ngx_chain_t *in)
 {
     u_char       *chunk;
-    size_t        size;
+    off_t         size;
     ngx_buf_t    *b;
     ngx_chain_t   out, tail, *cl, *tl, **ll;
 
@@ -106,13 +106,14 @@
             return NGX_ERROR;
         }
 
-        if (!(chunk = ngx_palloc(r->pool, sizeof("00000000" CRLF) - 1))) {
+        chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1);
+        if (chunk == NULL) {
             return NGX_ERROR;
         }
 
         b->temporary = 1;
         b->pos = chunk;
-        b->last = ngx_sprintf(chunk, "%xz" CRLF, size);
+        b->last = ngx_sprintf(chunk, "%xO" CRLF, size);
 
         out.buf = b;
     }
diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c
index 3386953..74ccf0a 100644
--- a/src/http/modules/ngx_http_index_handler.c
+++ b/src/http/modules/ngx_http_index_handler.c
@@ -448,8 +448,7 @@
     ngx_http_index_loc_conf_t  *prev = parent;
     ngx_http_index_loc_conf_t  *conf = child;
 
-    ngx_uint_t  i;
-    ngx_str_t  *index, *prev_index;
+    ngx_str_t  *index;
 
     if (conf->max_index_len == 0) {
         if (prev->max_index_len != 0) {
@@ -465,6 +464,8 @@
         return NGX_CONF_OK;
     }
 
+#if 0
+
     if (prev->max_index_len != 0) {
 
         prev_index = prev->indices.elts;
@@ -476,6 +477,8 @@
         }
     }
 
+#endif
+
     if (conf->max_index_len < prev->max_index_len) {
         conf->max_index_len = prev->max_index_len;
     }
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index 425a1a6..651dfa6 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -275,12 +275,9 @@
 
 
 static ngx_http_log_op_name_t ngx_http_proxy_log_fmt_ops[] = {
-    { ngx_string("proxy"), /* STUB */ 100,
-                           ngx_http_proxy_log_proxy_state },
-    { ngx_string("proxy_cache_state"), sizeof("BYPASS") - 1,
-                                       ngx_http_proxy_log_cache_state },
-    { ngx_string("proxy_reason"), sizeof("BPS") - 1,
-                                  ngx_http_proxy_log_reason },
+    { ngx_string("proxy"), 0, ngx_http_proxy_log_proxy_state },
+    { ngx_string("proxy_cache_state"), 0, ngx_http_proxy_log_cache_state },
+    { ngx_string("proxy_reason"), 0, ngx_http_proxy_log_reason },
     { ngx_null_string, 0, NULL }
 };
 
@@ -792,111 +789,180 @@
 static u_char *ngx_http_proxy_log_proxy_state(ngx_http_request_t *r,
                                               u_char *buf, uintptr_t data)
 {
-    ngx_http_proxy_ctx_t  *p;
+    ngx_uint_t               i;
+    ngx_http_proxy_ctx_t    *p;
+    ngx_http_proxy_state_t  *state;
 
     p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
 
     if (p == NULL) {
+        if (buf == NULL) {
+            return (u_char *) 1;
+        }
+
         *buf = '-';
         return buf + 1;
     }
 
-    if (p->state->cache_state == 0) {
-        *buf++ = '-';
 
-    } else {
-        buf = ngx_cpymem(buf, cache_states[p->state->cache_state - 1].data,
-                         cache_states[p->state->cache_state - 1].len);
+    if (buf == NULL) {
+        /* find the request line length */
+        return (u_char *) (uintptr_t) (p->states.nelts * /* STUB */ 100);
     }
 
-    *buf++ = '/';
 
-    if (p->state->expired == 0) {
-        *buf++ = '-';
+    i = 0;
+    state = p->states.elts;
 
-    } else {
-        buf = ngx_sprintf(buf, "%T", p->state->expired);
+    for ( ;; ) {
+        if (state[i].cache_state == 0) {
+            *buf++ = '-';
+
+        } else {
+            buf = ngx_cpymem(buf, cache_states[state[i].cache_state - 1].data,
+                             cache_states[state[i].cache_state - 1].len);
+        }
+
+        *buf++ = '/';
+
+        if (state[i].expired == 0) {
+            *buf++ = '-';
+
+        } else {
+            buf = ngx_sprintf(buf, "%T", state[i].expired);
+        }
+
+        *buf++ = '/';
+
+        if (state[i].bl_time == 0) {
+            *buf++ = '-';
+
+        } else {
+            buf = ngx_sprintf(buf, "%T", state[i].bl_time);
+        }
+
+        *buf++ = '/';
+
+        *buf++ = '*';
+
+        *buf++ = ' ';
+
+        if (state[i].status == 0) {
+            *buf++ = '-';
+
+        } else {
+            buf = ngx_sprintf(buf, "%ui", state[i].status);
+        }
+
+        *buf++ = '/';
+
+        if (state[i].reason == 0) {
+            *buf++ = '-';
+
+        } else {
+            buf = ngx_cpymem(buf, cache_reasons[state[i].reason - 1].data,
+                             cache_reasons[state[i].reason - 1].len);
+        }
+
+        *buf++ = '/';
+
+        if (state[i].reason < NGX_HTTP_PROXY_CACHE_XAE) {
+            *buf++ = '-';
+
+        } else {
+            buf = ngx_sprintf(buf, "%T", state[i].expires);
+        }
+
+        *buf++ = ' ';
+        *buf++ = '*';
+
+        if (++i == p->states.nelts) {
+            return buf;
+        }
+
+        *buf++ = ',';
+        *buf++ = ' ';
     }
-
-    *buf++ = '/';
-
-    if (p->state->bl_time == 0) {
-        *buf++ = '-';
-
-    } else {
-        buf = ngx_sprintf(buf, "%T", p->state->bl_time);
-    }
-
-    *buf++ = '/';
-
-    *buf++ = '*';
-
-    *buf++ = ' ';
-
-    if (p->state->status == 0) {
-        *buf++ = '-';
-
-    } else {
-        buf = ngx_sprintf(buf, "%ui", p->state->status);
-    }
-
-    *buf++ = '/';
-
-    if (p->state->reason == 0) {
-        *buf++ = '-';
-
-    } else {
-        buf = ngx_cpymem(buf, cache_reasons[p->state->reason - 1].data,
-                         cache_reasons[p->state->reason - 1].len);
-    }
-
-    *buf++ = '/';
-
-    if (p->state->reason < NGX_HTTP_PROXY_CACHE_XAE) {
-        *buf++ = '-';
-
-    } else {
-        buf = ngx_sprintf(buf, "%T", p->state->expires);
-    }
-
-    *buf++ = ' ';
-    *buf++ = '*';
-
-    return buf;
 }
 
 
 static u_char *ngx_http_proxy_log_cache_state(ngx_http_request_t *r,
                                               u_char *buf, uintptr_t data)
 {
-    ngx_http_proxy_ctx_t  *p;
+    ngx_uint_t               i;
+    ngx_http_proxy_ctx_t    *p;
+    ngx_http_proxy_state_t  *state;
 
     p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
 
     if (p == NULL || p->state->cache_state == 0) {
+        if (buf == NULL) {
+            return (u_char *) 1;
+        }
+
         *buf = '-';
         return buf + 1;
     }
 
-    return ngx_cpymem(buf, cache_states[p->state->cache_state - 1].data,
-                      cache_states[p->state->cache_state - 1].len);
+    if (buf == NULL) {
+        /* find the request line length */
+        return (u_char *) (p->states.nelts * sizeof("BYPASS") - 1);
+    }
+
+    i = 0;
+    state = p->states.elts;
+
+    for ( ;; ) {
+        buf = ngx_cpymem(buf, cache_states[state[i].cache_state - 1].data,
+                         cache_states[state[i].cache_state - 1].len);
+
+        if (++i == p->states.nelts) {
+            return buf;
+        }
+
+        *buf++ = ',';
+        *buf++ = ' ';
+    }
 }
 
 
 static u_char *ngx_http_proxy_log_reason(ngx_http_request_t *r, u_char *buf,
                                          uintptr_t data)
 {
-    ngx_http_proxy_ctx_t  *p;
+    ngx_uint_t               i;
+    ngx_http_proxy_ctx_t    *p;
+    ngx_http_proxy_state_t  *state;
 
     p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
 
     if (p == NULL || p->state->reason == 0) {
+        if (buf == NULL) {
+            return (u_char *) 1;
+        }
+
         *buf = '-';
         return buf + 1;
     }
 
-    return ngx_cpymem(buf, cache_reasons[p->state->reason - 1].data,
-                      cache_reasons[p->state->reason - 1].len);
+    if (buf == NULL) {
+        /* find the request line length */
+        return (u_char *) (p->states.nelts * sizeof("BPS") - 1);
+    }
+
+    i = 0;
+    state = p->states.elts;
+
+    for ( ;; ) {
+        buf = ngx_cpymem(buf, cache_reasons[state[i].reason - 1].data,
+                         cache_reasons[state[i].reason - 1].len);
+
+        if (++i == p->states.nelts) {
+            return buf;
+        }
+
+        *buf++ = ',';
+        *buf++ = ' ';
+    }
 }
 
 
@@ -1387,9 +1453,8 @@
 
 static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
 {
-    ssize_t *np = data;
-
 #if (NGX_FREEBSD)
+    ssize_t *np = data;
 
     if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -1401,6 +1466,7 @@
     }
 
 #elif !(NGX_HAVE_SO_SNDLOWAT)
+    ssize_t *np = data;
 
     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                        "\"proxy_send_lowat\" is not supported, ignored");
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
index 23d40c4..47d2b17 100644
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -528,6 +528,7 @@
 {
     ngx_chain_t             *cl;
     ngx_output_chain_ctx_t  *output;
+    ngx_http_proxy_state_e   state;
 
     /* reinit the request chain */
 
@@ -560,11 +561,17 @@
 
     /* add one more state */
 
+    state = p->state->cache_state;
+
     if (!(p->state = ngx_push_array(&p->states))) {
         ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
     }
 
+    ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t));
+
+    p->state->cache_state = state; 
+
     p->status = 0;
     p->status_count = 0;
 }
@@ -719,9 +726,9 @@
     writer->out = NULL;
     writer->last = &writer->out;
     writer->connection = c;
-    writer->limit = OFF_T_MAX_VALUE;
+    writer->limit = 0;
 
-    if (p->upstream->peer.tries > 1 && p->request_sent) {
+    if (p->request_sent) {
         ngx_http_proxy_reinit_upstream(p);
     }
 
@@ -803,13 +810,13 @@
                           p->request_sent ? NULL:
                                             p->request->request_body->bufs);
 
+    p->request_sent = 1;
+
     if (rc == NGX_ERROR) {
         ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
         return;
     }
 
-    p->request_sent = 1;
-
     if (c->write->timer_set) {
         ngx_del_timer(c->write);
     }
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
index aa66902..c882b30 100644
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -97,6 +97,11 @@
 } ngx_http_cache_t;
 
 
+typedef struct {
+    ngx_path_t                path;
+    ngx_str_t                 key;
+} ngx_http_cache_ctx_t;
+
 
 #define NGX_HTTP_CACHE_STALE     1
 #define NGX_HTTP_CACHE_AGED      2
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index c4cb8b9..e3ccd8f 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1815,9 +1815,8 @@
 
 static char *ngx_http_lowat_check(ngx_conf_t *cf, void *post, void *data)
 {
-    ssize_t *np = data;
-
 #if (NGX_FREEBSD)
+    ssize_t *np = data;
 
     if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -1829,6 +1828,7 @@
     }
 
 #elif !(NGX_HAVE_SO_SNDLOWAT)
+    ssize_t *np = data;
 
     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                        "\"send_lowat\" is not supported, ignored");
diff --git a/src/http/ngx_http_header_filter.c b/src/http/ngx_http_header_filter.c
index 3fa1108..31fa826 100644
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -252,9 +252,7 @@
          * Konqueror keeps the connection alive for about N seconds.
          */
 
-        if (clcf->keepalive_header
-            && (r->headers_in.gecko || r->headers_in.konqueror))
-        {
+        if (clcf->keepalive_header) {
             len += sizeof("Keep-Alive: timeout=") - 1 + TIME_T_LEN + 2;
         }
 
@@ -384,9 +382,7 @@
         b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF,
                              sizeof("Connection: keep-alive" CRLF) - 1);
 
-        if (clcf->keepalive_header
-            && (r->headers_in.gecko || r->headers_in.konqueror))
-        {
+        if (clcf->keepalive_header) {
             b->last = ngx_sprintf(b->last, "Keep-Alive: timeout=%T" CRLF,
                                   clcf->keepalive_header);
         }
diff --git a/src/http/ngx_http_log_handler.c b/src/http/ngx_http_log_handler.c
index 581a1ce..fd37344 100644
--- a/src/http/ngx_http_log_handler.c
+++ b/src/http/ngx_http_log_handler.c
@@ -166,7 +166,10 @@
         len++;
 #endif
 
-        ngx_test_null(line, ngx_palloc(r->pool, len), NGX_ERROR);
+        if (!(line = ngx_palloc(r->pool, len))) {
+            return NGX_ERROR;
+        }
+
         p = line;
 
         for (i = 0; i < log[l].ops->nelts; i++) {
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index 96ed49c..77db813 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -665,6 +665,8 @@
     u_char  c, ch, decoded, *p, *u;
     enum {
         sw_usual = 0,
+        sw_colon,
+        sw_colon_slash,
         sw_slash,
         sw_dot,
         sw_dot_dot,
@@ -730,8 +732,14 @@
             case '?':
                 r->args_start = p;
                 break;
+            case ':':
+                state = sw_colon;
+                *u++ = ch;
+                break;
             case '.':
                 r->uri_ext = u + 1;
+                *u++ = ch;
+                break;
             default:
                 *u++ = ch;
                 break;
@@ -739,6 +747,61 @@
             ch = *p++;
             break;
 
+        case sw_colon:
+            switch(ch) {
+#if (NGX_WIN32)
+            case '\\':
+                state = sw_colon_slash;
+                *u++ = '/';
+                break;
+#endif
+            case '/':
+                state = sw_colon_slash;
+                *u++ = ch;
+                break;
+            case ':':
+                *u++ = ch;
+                break;
+            case '%':
+                quoted_state = state;
+                state = sw_quoted;
+                break;
+            default:
+                state = sw_usual;
+                *u++ = ch;
+                break;
+            }
+            ch = *p++;
+            break;
+
+        case sw_colon_slash:
+            switch(ch) {
+#if (NGX_WIN32)
+            case '\\':
+                state = sw_slash;
+                *u++ = '/';
+                break;
+#endif
+            case '/':
+                state = sw_slash;
+                *u++ = ch;
+                break;
+            case '.':
+                state = sw_dot;
+                *u++ = ch;
+                break;
+            case '%':
+                quoted_state = state;
+                state = sw_quoted;
+                break;
+            default:
+                state = sw_usual;
+                *u++ = ch;
+                break;
+            }
+            ch = *p++;
+            break;
+
         case sw_slash:
             switch(ch) {
 #if (NGX_WIN32)
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index b6013fc..fe3d516 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1190,8 +1190,9 @@
 
 #if 0
             /* MSIE ignores the SSL "close notify" alert */
-
-            ngx_ssl_set_nosendshut(r->connection->ssl);
+            if (c->ssl) {
+                r->connection->ssl->no_send_shut = 1;
+            }
 #endif
         }
 
@@ -1269,7 +1270,7 @@
     }
 
     if (r->connection->read->pending_eof) {
-#if (NGX_KQUEUE)
+#if (NGX_HAVE_KQUEUE)
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log,
                        r->connection->read->kq_errno,
                        "kevent() reported about an closed connection");
@@ -1702,24 +1703,26 @@
         }
 
         c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
+        tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
 
     } else {
-        if (clcf->tcp_nodelay && !c->tcp_nodelay) {
-            tcp_nodelay = 1;
+        tcp_nodelay = 1;
+    }
 
-            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
+    if (tcp_nodelay && clcf->tcp_nodelay && !c->tcp_nodelay) {
 
-            if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
-                               (const void *) &tcp_nodelay, sizeof(int)) == -1)
-            {
-                ngx_connection_error(c, ngx_socket_errno,
-                                     "setsockopt(TCP_NODELAY) failed");
-                ngx_http_close_connection(c);
-                return;
-            }
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
 
-            c->tcp_nodelay = 1;
+        if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
+                           (const void *) &tcp_nodelay, sizeof(int)) == -1)
+        {
+            ngx_connection_error(c, ngx_socket_errno,
+                                 "setsockopt(TCP_NODELAY) failed");
+            ngx_http_close_connection(c);
+            return;
         }
+
+        c->tcp_nodelay = 1;
     }
 
 #if 0
@@ -1761,6 +1764,11 @@
             ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
                           "kevent() reported that client %V closed "
                           "keepalive connection", ctx->client);
+#if (NGX_HTTP_SSL)
+            if (c->ssl) {
+                c->ssl->no_send_shut = 1;
+            }
+#endif
             ngx_http_close_connection(c);
             return;
         }
diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c
index 67f6862..50e8bc2 100644
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -152,8 +152,7 @@
 
     sent = c->sent;
 
-    chain = c->send_chain(c, ctx->out,
-                          clcf->limit_rate ? clcf->limit_rate: OFF_T_MAX_VALUE);
+    chain = c->send_chain(c, ctx->out, clcf->limit_rate);
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
                    "http write filter %p", chain);