diff src/http/ngx_http_upstream.c @ 76:da9a3b14312d NGINX_0_1_38

nginx 0.1.38 *) Feature: the "limit_rate" directive is supported in in proxy and FastCGI mode. *) Feature: the "X-Accel-Limit-Rate" response header line is supported in proxy and FastCGI mode. *) Feature: the "break" directive. *) Feature: the "log_not_found" directive. *) Bugfix: the response status code was not changed when request was redirected by the ""X-Accel-Redirect" header line. *) Bugfix: the variables set by the "set" directive could not be used in SSI. *) Bugfix: the segmentation fault may occurred if the SSI page has more than one remote subrequest. *) Bugfix: nginx treated the backend response as invalid if the status line in the header was transferred in two packets; bug appeared in 0.1.29. *) Feature: the "ssi_types" directive. *) Feature: the "autoindex_exact_size" directive. *) Bugfix: the ngx_http_autoindex_module did not support the long file names in UTF-8. *) Feature: the IMAP/POP3 proxy.
author Igor Sysoev <http://sysoev.ru>
date Fri, 08 Jul 2005 00:00:00 +0400
parents 77969b24f355
children 9db7e0b5b27f
line wrap: on
line diff
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -39,6 +39,8 @@ static ngx_int_t
     ngx_table_elt_t *h, ngx_uint_t offset);
 static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r,
+    ngx_table_elt_t *h, ngx_uint_t offset);
 static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset);
 static ngx_int_t
@@ -143,6 +145,10 @@ ngx_http_upstream_header_t  ngx_http_ups
                  offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect),
                  ngx_http_upstream_ignore_header_line, 0, 0 },
 
+    { ngx_string("X-Accel-Limit-Rate"),
+                 ngx_http_upstream_process_limit_rate, 0,
+                 ngx_http_upstream_ignore_header_line, 0, 0 },
+
 #if (NGX_HTTP_GZIP)
     { ngx_string("Content-Encoding"),
                  ngx_http_upstream_process_header_line,
@@ -299,12 +305,19 @@ ngx_http_upstream_check_broken_connectio
     ngx_connection_t     *c;
     ngx_http_upstream_t  *u;
 
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0,
-                   "http upstream check client, write event:%d", ev->write);
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0,
+                   "http upstream check client, write event:%d, \"%V\"",
+                   ev->write, &r->uri);
 
     c = r->connection;
     u = r->upstream;
 
+    if (c->closed) {
+        ngx_http_upstream_finalize_request(r, u,
+                                           NGX_HTTP_CLIENT_CLOSED_REQUEST);
+        return;
+    }
+
     if (u->peer.connection == NULL) {
         return;
     }
@@ -318,6 +331,7 @@ ngx_http_upstream_check_broken_connectio
         }
 
         ev->eof = 1;
+        c->closed = 1;
 
         if (ev->kq_errno) {
             ev->error = 1;
@@ -325,9 +339,8 @@ ngx_http_upstream_check_broken_connectio
 
         if (!u->cachable && u->peer.connection) {
             ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
-                          "kevent() reported that client closed "
-                          "prematurely connection, "
-                          "so upstream connection is closed too");
+                          "kevent() reported that client closed prematurely "
+                          "connection, so upstream connection is closed too");
             ngx_http_upstream_finalize_request(r, u,
                                                NGX_HTTP_CLIENT_CLOSED_REQUEST);
             return;
@@ -374,6 +387,7 @@ ngx_http_upstream_check_broken_connectio
     }
 
     ev->eof = 1;
+    c->closed = 1;
 
     if (n == -1) {
         if (err == NGX_EAGAIN) {
@@ -924,6 +938,8 @@ ngx_http_upstream_process_header(ngx_eve
             }
         }
 
+        r->headers_out.status_line.len = 0;
+
         ngx_http_internal_redirect(r,
                               &r->upstream->headers_in.x_accel_redirect->value,
                               NULL);
@@ -1155,9 +1171,33 @@ ngx_http_upstream_process_body(ngx_event
 
     if (ev->timedout) {
         if (ev->write) {
-            p->downstream_error = 1;
-            ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT,
-                          "client timed out");
+            if (ev->delayed) {
+
+                ev->timedout = 0;
+                ev->delayed = 0;
+
+                if (!ev->ready) {
+                    ngx_add_timer(ev, p->send_timeout);
+
+                    if (ngx_handle_write_event(ev, p->send_lowat) == NGX_ERROR)
+                    {
+                        ngx_http_upstream_finalize_request(r, u, 0);
+                        return;
+                    }
+
+                    return;
+                }
+
+                if (ngx_event_pipe(p, ev->write) == NGX_ABORT) {
+                    ngx_http_upstream_finalize_request(r, u, 0);
+                    return;
+                }
+
+            } else {
+                p->downstream_error = 1;
+                ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT,
+                              "client timed out");
+            }
 
         } else {
             p->upstream_error = 1; 
@@ -1166,6 +1206,17 @@ ngx_http_upstream_process_body(ngx_event
         }
 
     } else {
+        if (ev->write && ev->delayed) {
+            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                           "http downstream delayed");
+
+            if (ngx_handle_write_event(ev, p->send_lowat) == NGX_ERROR) {
+                return;
+            }
+
+            return;
+        }
+
         if (ngx_event_pipe(p, ev->write) == NGX_ABORT) {
             ngx_http_upstream_finalize_request(r, u, 0);
             return;
@@ -1281,6 +1332,7 @@ ngx_http_upstream_next(ngx_http_request_
     }
 
     if (r->connection->write->eof) {
+        r->connection->closed = 1;
         ngx_http_upstream_finalize_request(r, u,
                                            NGX_HTTP_CLIENT_CLOSED_REQUEST);
         return;
@@ -1432,6 +1484,24 @@ ngx_http_upstream_ignore_header_line(ngx
 
 
 static ngx_int_t
+ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h,
+    ngx_uint_t offset)
+{   
+    ngx_int_t  n;
+
+    r->upstream->headers_in.x_accel_limit_rate = h;
+
+    n = ngx_atoi(h->value.data, h->value.len);
+
+    if (n != NGX_ERROR) {
+        r->limit_rate = (size_t) n;
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
 ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
     ngx_uint_t offset)
 {