changeset 642:d3cf6c6b0043 NGINX_1_1_5

nginx 1.1.5 *) Feature: the "uwsgi_buffering" and "scgi_buffering" directives. Thanks to Peter Smit. *) Bugfix: non-cacheable responses might be cached if "proxy_cache_bypass" directive was used. Thanks to John Ferlito. *) Bugfix: in HTTP/1.1 support in the ngx_http_proxy_module. *) Bugfix: cached responses with an empty body were returned incorrectly; the bug had appeared in 0.8.31. *) Bugfix: 201 responses of the ngx_http_dav_module were incorrect; the bug had appeared in 0.8.32. *) Bugfix: in the "return" directive. *) Bugfix: the "ssl_session_cache builtin" directive caused segmentation fault; the bug had appeared in 1.1.1.
author Igor Sysoev <http://sysoev.ru>
date Wed, 05 Oct 2011 00:00:00 +0400
parents 6c19b251b926
children a4bb0b481f6c
files CHANGES CHANGES.ru src/core/nginx.h src/http/modules/ngx_http_empty_gif_module.c src/http/modules/ngx_http_mp4_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_rewrite_module.c src/http/modules/ngx_http_scgi_module.c src/http/modules/ngx_http_ssl_module.c src/http/modules/ngx_http_uwsgi_module.c src/http/modules/perl/nginx.pm src/http/ngx_http.c src/http/ngx_http_core_module.c src/http/ngx_http_file_cache.c src/http/ngx_http_special_response.c src/http/ngx_http_upstream.c src/mail/ngx_mail_ssl_module.c
diffstat 17 files changed, 133 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,27 @@
 
+Changes with nginx 1.1.5                                         05 Oct 2011
+
+    *) Feature: the "uwsgi_buffering" and "scgi_buffering" directives.
+       Thanks to Peter Smit.
+
+    *) Bugfix: non-cacheable responses might be cached if
+       "proxy_cache_bypass" directive was used.
+       Thanks to John Ferlito.
+
+    *) Bugfix: in HTTP/1.1 support in the ngx_http_proxy_module.
+
+    *) Bugfix: cached responses with an empty body were returned
+       incorrectly; the bug had appeared in 0.8.31.
+
+    *) Bugfix: 201 responses of the ngx_http_dav_module were incorrect; the
+       bug had appeared in 0.8.32.
+
+    *) Bugfix: in the "return" directive.
+
+    *) Bugfix: the "ssl_session_cache builtin" directive caused segmentation
+       fault; the bug had appeared in 1.1.1.
+
+
 Changes with nginx 1.1.4                                         20 Sep 2011
 
     *) Feature: the ngx_http_upstream_keepalive module.
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,28 @@
 
+Изменения в nginx 1.1.5                                           05.10.2011
+
+    *) Добавление: директивы uwsgi_buffering и scgi_buffering.
+       Спасибо Peter Smit.
+
+    *) Исправление: при использовании proxy_cache_bypass могли быть
+       закэшированы некэшируемые ответы.
+       Спасибо John Ferlito.
+
+    *) Исправление: в модуле ngx_http_proxy_module при работе с бэкендами по
+       HTTP/1.1.
+
+    *) Исправление: закэшированные ответы с пустым телом возвращались
+       некорректно; ошибка появилась в 0.8.31.
+
+    *) Исправление: ответы с кодом 201 модуля ngx_http_dav_module были
+       некорректны; ошибка появилась в 0.8.32.
+
+    *) Исправление: в директиве return.
+
+    *) Исправление: при использовании директивы "ssl_session_cache builtin"
+       происходил segmentation fault; ошибка появилась в 1.1.1.
+
+
 Изменения в nginx 1.1.4                                           20.09.2011
 
     *) Добавление: модуль ngx_http_upstream_keepalive.
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version      1001004
-#define NGINX_VERSION      "1.1.4"
+#define nginx_version      1001005
+#define NGINX_VERSION      "1.1.5"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/http/modules/ngx_http_empty_gif_module.c
+++ b/src/http/modules/ngx_http_empty_gif_module.c
@@ -111,19 +111,12 @@ static ngx_str_t  ngx_http_gif_type = ng
 static ngx_int_t
 ngx_http_empty_gif_handler(ngx_http_request_t *r)
 {
-    ngx_int_t                 rc;
     ngx_http_complex_value_t  cv;
 
     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
         return NGX_HTTP_NOT_ALLOWED;
     }
 
-    rc = ngx_http_discard_request_body(r);
-
-    if (rc != NGX_OK) {
-        return rc;
-    }
-
     ngx_memzero(&cv, sizeof(ngx_http_complex_value_t));
 
     cv.value.len = sizeof(ngx_empty_gif);
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -187,14 +187,14 @@ typedef struct {
     + (           ((u_char *) (p))[7]) )
 
 #define ngx_mp4_set_64value(p, n)                                             \
-    ((u_char *) (p))[0] = (u_char) ((n) >> 56);                               \
-    ((u_char *) (p))[1] = (u_char) ((n) >> 48);                               \
-    ((u_char *) (p))[2] = (u_char) ((n) >> 40);                               \
-    ((u_char *) (p))[3] = (u_char) ((n) >> 32);                               \
-    ((u_char *) (p))[4] = (u_char) ((n) >> 24);                               \
-    ((u_char *) (p))[5] = (u_char) ((n) >> 16);                               \
-    ((u_char *) (p))[6] = (u_char) ((n) >> 8);                                \
-    ((u_char *) (p))[7] = (u_char) (n)
+    ((u_char *) (p))[0] = (u_char) ((uint64_t) (n) >> 56);                    \
+    ((u_char *) (p))[1] = (u_char) ((uint64_t) (n) >> 48);                    \
+    ((u_char *) (p))[2] = (u_char) ((uint64_t) (n) >> 40);                    \
+    ((u_char *) (p))[3] = (u_char) ((uint64_t) (n) >> 32);                    \
+    ((u_char *) (p))[4] = (u_char) (           (n) >> 24);                    \
+    ((u_char *) (p))[5] = (u_char) (           (n) >> 16);                    \
+    ((u_char *) (p))[6] = (u_char) (           (n) >> 8);                     \
+    ((u_char *) (p))[7] = (u_char)             (n)
 
 #define ngx_mp4_last_trak(mp4)                                                \
     &((ngx_http_mp4_trak_t *) mp4->trak.elts)[mp4->trak.nelts - 1]
@@ -499,9 +499,16 @@ ngx_http_mp4_handler(ngx_http_request_t 
 
         if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) {
 
-            start = ngx_atofp(value.data, value.len, 3);
-
-            if (start != NGX_ERROR) {
+            /*
+             * A Flash player may send start value with a lot of digits
+             * after dot so strtod() is used instead of atofp().  NaNs and
+             * infinities become negative numbers after (int) conversion.
+             */
+
+            ngx_set_errno(0);
+            start = (int) (strtod((char *) value.data, NULL) * 1000);
+
+            if (ngx_errno == 0 && start >= 0) {
                 r->allow_ranges = 0;
 
                 mp4 = ngx_pcalloc(r->pool, sizeof(ngx_http_mp4_file_t));
@@ -1066,7 +1073,7 @@ ngx_http_mp4_update_mdat_atom(ngx_http_m
 
     atom_header = mp4->mdat_atom_header;
 
-    if (atom_data_size > 0xffffffff) {
+    if ((uint64_t) atom_data_size > 0xffffffff) {
         atom_size = 1;
         atom_header_size = sizeof(ngx_mp4_atom_header64_t);
         ngx_mp4_set_64value(atom_header + sizeof(ngx_mp4_atom_header_t),
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1559,7 +1559,7 @@ ngx_http_proxy_copy_filter(ngx_event_pip
         r = p->input_ctx;
         p->upstream_done = 1;
 
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+        ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
                       "upstream sent too many data");
     }
 
@@ -1647,6 +1647,8 @@ ngx_http_proxy_parse_chunked(ngx_http_re
                     state = sw_trailer;
                     break;
                 case ';':
+                case ' ':
+                case '\t':
                     state = sw_last_chunk_extension;
                     break;
                 default:
@@ -1664,6 +1666,8 @@ ngx_http_proxy_parse_chunked(ngx_http_re
                 state = sw_chunk_data;
                 break;
             case ';':
+            case ' ':
+            case '\t':
                 state = sw_chunk_extension;
                 break;
             default:
@@ -1813,9 +1817,6 @@ done:
 
 invalid:
 
-    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                  "upstream sent invalid chunked response");
-
     return NGX_ERROR;
 }
 
@@ -1929,7 +1930,7 @@ ngx_http_proxy_chunked_filter(ngx_event_
 
         /* invalid response */
 
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                       "upstream sent invalid chunked response");
 
         return NGX_ERROR;
@@ -2085,7 +2086,7 @@ ngx_http_proxy_non_buffered_chunked_filt
 
         /* invalid response */
 
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                       "upstream sent invalid chunked response");
 
         return NGX_ERROR;
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -167,8 +167,8 @@ ngx_http_rewrite_handler(ngx_http_reques
         code(e);
     }
 
-    if (e->status == NGX_DECLINED) {
-        return NGX_DECLINED;
+    if (e->status < NGX_HTTP_BAD_REQUEST) {
+        return e->status;
     }
 
     if (r->err_status == 0) {
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -96,6 +96,13 @@ static ngx_command_t ngx_http_scgi_comma
       offsetof(ngx_http_scgi_loc_conf_t, upstream.store_access),
       NULL },
 
+    { ngx_string("scgi_buffering"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_scgi_loc_conf_t, upstream.buffering),
+      NULL },
+
     { ngx_string("scgi_ignore_client_abort"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -412,7 +419,7 @@ ngx_http_scgi_handler(ngx_http_request_t
     u->abort_request = ngx_http_scgi_abort_request;
     u->finalize_request = ngx_http_scgi_finalize_request;
 
-    u->buffering = 1;
+    u->buffering = scf->upstream.buffering;
 
     u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
     if (u->pipe == NULL) {
@@ -1038,6 +1045,8 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t
     /* "scgi_cyclic_temp_file" is disabled */
     conf->upstream.cyclic_temp_file = 0;
 
+    conf->upstream.change_buffering = 1;
+
     ngx_str_set(&conf->upstream.module, "scgi");
 
     return conf;
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -616,6 +616,8 @@ ngx_http_ssl_session_cache(ngx_conf_t *c
                 return NGX_CONF_ERROR;
             }
 
+            sscf->shm_zone->init = ngx_ssl_session_cache_init;
+
             continue;
         }
 
@@ -626,8 +628,6 @@ ngx_http_ssl_session_cache(ngx_conf_t *c
         sscf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
     }
 
-    sscf->shm_zone->init = ngx_ssl_session_cache_init;
-
     return NGX_CONF_OK;
 
 invalid:
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -123,6 +123,13 @@ static ngx_command_t ngx_http_uwsgi_comm
       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.store_access),
       NULL },
 
+    { ngx_string("uwsgi_buffering"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_uwsgi_loc_conf_t, upstream.buffering),
+      NULL },
+
     { ngx_string("uwsgi_ignore_client_abort"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -445,7 +452,7 @@ ngx_http_uwsgi_handler(ngx_http_request_
     u->abort_request = ngx_http_uwsgi_abort_request;
     u->finalize_request = ngx_http_uwsgi_finalize_request;
 
-    u->buffering = 1;
+    u->buffering = uwcf->upstream.buffering;
 
     u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
     if (u->pipe == NULL) {
@@ -1091,6 +1098,8 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_
     /* "uwsgi_cyclic_temp_file" is disabled */
     conf->upstream.cyclic_temp_file = 0;
 
+    conf->upstream.change_buffering = 1;
+
     ngx_str_set(&conf->upstream.module, "uwsgi");
 
     return conf;
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -48,7 +48,7 @@ our @EXPORT = qw(
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '1.1.4';
+our $VERSION = '1.1.5';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1281,7 +1281,7 @@ ngx_http_add_addresses(ngx_conf_t *cf, n
 
             if (addr[i].opt.set) {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                        "a duplicate listen options for %s", addr[i].opt.addr);
+                        "duplicate listen options for %s", addr[i].opt.addr);
                 return NGX_ERROR;
             }
 
@@ -1747,10 +1747,12 @@ ngx_http_add_listening(ngx_conf_t *cf, n
 
 #if (NGX_WIN32)
     {
-    ngx_iocp_conf_t  *iocpcf;
-
-    iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
-    if (iocpcf->acceptex_read) {
+    ngx_iocp_conf_t  *iocpcf = NULL;
+
+    if (ngx_get_conf(cf->cycle->conf_ctx, ngx_events_module)) {
+        iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
+    }
+    if (iocpcf && iocpcf->acceptex_read) {
         ls->post_accept_buffer_size = cscf->client_header_buffer_size;
     }
     }
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1784,13 +1784,12 @@ ngx_http_send_response(ngx_http_request_
     ngx_buf_t    *b;
     ngx_chain_t   out;
 
+    if (ngx_http_discard_request_body(r) != NGX_OK) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
     r->headers_out.status = status;
 
-    if (status == NGX_HTTP_NO_CONTENT) {
-        r->header_only = 1;
-        return ngx_http_send_header(r);
-    }
-
     if (ngx_http_complex_value(r, cv, &val) != NGX_OK) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -853,6 +853,10 @@ ngx_http_cache_send(ngx_http_request_t *
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http file cache send: %s", c->file.name.data);
 
+    if (r != r->main && c->length - c->body_start == 0) {
+        return ngx_http_send_header(r);
+    }
+
     /* we need to allocate all before the header would be sent */
 
     b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
@@ -865,8 +869,6 @@ ngx_http_cache_send(ngx_http_request_t *
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    r->header_only = (c->length - c->body_start) == 0;
-
     rc = ngx_http_send_header(r);
 
     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
@@ -876,7 +878,7 @@ ngx_http_cache_send(ngx_http_request_t *
     b->file_pos = c->body_start;
     b->file_last = c->length;
 
-    b->in_file = 1;
+    b->in_file = (c->length - c->body_start) ? 1: 0;
     b->last_buf = (r == r->main) ? 1: 0;
     b->last_in_chain = 1;
 
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -421,7 +421,6 @@ ngx_http_special_response_handler(ngx_ht
     if (error == NGX_HTTP_CREATED) {
         /* 201 */
         err = 0;
-        r->header_only = 1;
 
     } else if (error == NGX_HTTP_NO_CONTENT) {
         /* 204 */
@@ -636,7 +635,7 @@ ngx_http_send_special_response(ngx_http_
         r->headers_out.content_type_lowcase = NULL;
 
     } else {
-        r->headers_out.content_length_n = -1;
+        r->headers_out.content_length_n = 0;
     }
 
     if (r->headers_out.content_length) {
@@ -654,7 +653,7 @@ ngx_http_send_special_response(ngx_http_
     }
 
     if (ngx_http_error_pages[err].len == 0) {
-        return NGX_OK;
+        return ngx_http_send_special(r, NGX_HTTP_LAST);
     }
 
     b = ngx_calloc_buf(r->pool);
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -683,6 +683,8 @@ ngx_http_upstream_cache(ngx_http_request
             return NGX_DECLINED;
         }
 
+        u->cacheable = 1;
+
         switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
 
         case NGX_ERROR:
@@ -696,8 +698,6 @@ ngx_http_upstream_cache(ngx_http_request
             break;
         }
 
-        u->cacheable = 1;
-
         c = r->cache;
 
         c->min_uses = u->conf->cache_min_uses;
@@ -2181,8 +2181,6 @@ ngx_http_upstream_send_response(ngx_http
                 ngx_http_upstream_finalize_request(r, u, 0);
                 return;
             }
-
-            u->cacheable = 1;
         }
 
         break;
@@ -2927,6 +2925,7 @@ ngx_http_upstream_next(ngx_http_request_
         }
 
         ngx_close_connection(u->peer.connection);
+        u->peer.connection = NULL;
     }
 
 #if 0
@@ -3071,7 +3070,12 @@ ngx_http_upstream_finalize_request(ngx_h
 
     r->connection->log->action = "sending to client";
 
-    if (rc == 0) {
+    if (rc == 0
+#if (NGX_HTTP_CACHE)
+        && !r->cached
+#endif
+       )
+    {
         rc = ngx_http_send_special(r, NGX_HTTP_LAST);
     }
 
@@ -4329,6 +4333,10 @@ ngx_http_upstream_add(ngx_conf_t *cf, ng
             continue;
         }
 
+        if (flags & NGX_HTTP_UPSTREAM_CREATE) {
+            uscfp[i]->flags = flags;
+        }
+
         return uscfp[i];
     }
 
--- a/src/mail/ngx_mail_ssl_module.c
+++ b/src/mail/ngx_mail_ssl_module.c
@@ -464,6 +464,8 @@ ngx_mail_ssl_session_cache(ngx_conf_t *c
                 return NGX_CONF_ERROR;
             }
 
+            scf->shm_zone->init = ngx_ssl_session_cache_init;
+
             continue;
         }
 
@@ -474,8 +476,6 @@ ngx_mail_ssl_session_cache(ngx_conf_t *c
         scf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
     }
 
-    scf->shm_zone->init = ngx_ssl_session_cache_init;
-
     return NGX_CONF_OK;
 
 invalid: