changeset 584:016632f0fb18 NGINX_0_8_44

nginx 0.8.44 *) Change: now nginx does not cache by default backend responses, if they have a "Set-Cookie" header line. *) Feature: the "listen" directive supports the "setfib" parameter. Thanks to Andrew Filonov. *) Bugfix: the "sub_filter" directive might change character case on partial match. *) Bugfix: compatibility with HP/UX. *) Bugfix: compatibility with AIX xcl_r compiler. *) Bugfix: nginx treated a large SSLv2 packets as plain requests. Thanks to Miroslaw Jaworski.
author Igor Sysoev <http://sysoev.ru>
date Mon, 05 Jul 2010 00:00:00 +0400
parents 39e50617266a
children 565a8b8fdad5
files CHANGES CHANGES.ru auto/cc/conf auto/os/features src/core/nginx.h src/core/ngx_connection.c src/core/ngx_connection.h src/core/ngx_log.h src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_scgi_module.c src/http/modules/ngx_http_sub_filter_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_core_module.h src/http/ngx_http_request.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h src/os/unix/ngx_errno.h
diffstat 21 files changed, 234 insertions(+), 199 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,10 +1,29 @@
 
+Changes with nginx 0.8.44                                        05 Jul 2010
+
+    *) Change: now nginx does not cache by default backend responses, if 
+       they have a "Set-Cookie" header line.
+
+    *) Feature: the "listen" directive supports the "setfib" parameter. 
+       Thanks to Andrew Filonov.
+
+    *) Bugfix: the "sub_filter" directive might change character case on 
+       partial match.
+
+    *) Bugfix: compatibility with HP/UX.
+
+    *) Bugfix: compatibility with AIX xcl_r compiler.
+
+    *) Bugfix: nginx treated a large SSLv2 packets as plain requests.
+       Thanks to Miroslaw Jaworski.
+
+
 Changes with nginx 0.8.43                                        30 Jun 2010
 
     *) Feature: large geo ranges base loading speed-up.
 
-    *) Bugfix: an error_page redirection to "location /zero { return 204; 
-       }" without changing status code kept the error body; the bug had 
+    *) Bugfix: an error_page redirection to "location /zero {return 204;}" 
+       without changing status code kept the error body; the bug had 
        appeared in 0.8.42.
 
     *) Bugfix: nginx might close IPv6 listen socket during 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,11 +1,31 @@
 
+Изменения в nginx 0.8.44                                          05.07.2010
+
+    *) Изменение: теперь nginx по умолчанию не кэширует ответы бэкендов, в 
+       заголовке которых есть строка "Set-Cookie".
+
+    *) Добавление: директива listen поддерживает параметр setfib.
+       Спасибо Андрею Филонову.
+
+    *) Исправление: директива sub_filter могла изменять регистр букв при 
+       частичном совпадении.
+
+    *) Исправление: совместимость с HP/UX.
+
+    *) Исправление: совместимость с компилятором AIX xcl_r.
+
+    *) Исправление: nginx считал большие пакеты SSLv2 как обычные текстовые 
+       запросы.
+       Спасибо Miroslaw Jaworski.
+
+
 Изменения в nginx 0.8.43                                          30.06.2010
 
     *) Добавление: ускорение загрузки больших баз geo-диапазонов.
 
-    *) Исправление: перенаправление ошибки в "location /zero { return 204; 
-       }" без изменения кода ответа оставляло тело ошибки; ошибка появилась 
-       в 0.8.42.
+    *) Исправление: перенаправление ошибки в "location /zero {return 204;}" 
+       без изменения кода ответа оставляло тело ошибки; ошибка появилась в 
+       0.8.42.
 
     *) Исправление: nginx мог закрывать IPv6 listen сокет во время 
        переконфигурации.
--- a/auto/cc/conf
+++ b/auto/cc/conf
@@ -143,19 +143,6 @@ if [ "$NGX_PLATFORM" != win32 ]; then
     . auto/feature
 
 
-    ngx_feature="gcc variadic macros"
-    ngx_feature_name="NGX_HAVE_GCC_VARIADIC_MACROS"
-    ngx_feature_run=yes
-    ngx_feature_incs="#include <stdio.h>
-#define var(dummy, args...)  sprintf(args)"
-    ngx_feature_path=
-    ngx_feature_libs=
-    ngx_feature_test="char  buf[30]; buf[0] = '0';
-                      var(0, buf, \"%d\", 1);
-                      if (buf[0] != '1') return 1"
-    . auto/feature
-
-
     if [ "$NGX_CC_NAME" = "ccc" ]; then
         echo "checking for C99 variadic macros ... disabled"
     else
@@ -173,6 +160,19 @@ if [ "$NGX_PLATFORM" != win32 ]; then
      fi
 
 
+    ngx_feature="gcc variadic macros"
+    ngx_feature_name="NGX_HAVE_GCC_VARIADIC_MACROS"
+    ngx_feature_run=yes
+    ngx_feature_incs="#include <stdio.h>
+#define var(dummy, args...)  sprintf(args)"
+    ngx_feature_path=
+    ngx_feature_libs=
+    ngx_feature_test="char  buf[30]; buf[0] = '0';
+                      var(0, buf, \"%d\", 1);
+                      if (buf[0] != '1') return 1"
+    . auto/feature
+
+
 #    ngx_feature="inline"
 #    ngx_feature_name=
 #    ngx_feature_run=no
--- a/auto/os/features
+++ b/auto/os/features
@@ -295,6 +295,15 @@ if [ $ngx_found != yes ]; then
     fi
 fi
 
+ngx_feature="SO_SETFIB"
+ngx_feature_name="NGX_HAVE_SETFIB"
+ngx_feature_run=no
+ngx_feature_incs="#include <sys/socket.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="setsockopt(0, SOL_SOCKET, SO_SETFIB, NULL, 4)"
+. auto/feature
+
 
 if [ $NGX_FILE_AIO = YES ]; then
 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         8043
-#define NGINX_VERSION      "0.8.43"
+#define nginx_version         8044
+#define NGINX_VERSION      "0.8.44"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -74,6 +74,10 @@ ngx_create_listening(ngx_conf_t *cf, voi
     ls->rcvbuf = -1;
     ls->sndbuf = -1;
 
+#if (NGX_HAVE_SETFIB)
+    ls->setfib = -1;
+#endif
+
     return ls;
 }
 
@@ -179,6 +183,25 @@ ngx_set_inherited_sockets(ngx_cycle_t *c
             ls[i].sndbuf = -1;
         }
 
+#if 0
+        /* SO_SETFIB is currently a set only option */
+
+#if (NGX_HAVE_SETFIB)
+
+        if (getsockopt(ls[i].setfib, SOL_SOCKET, SO_SETFIB,
+                       (void *) &ls[i].setfib, &olen)
+            == -1)
+        {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                          "getsockopt(SO_SETFIB) %V failed, ignored",
+                          &ls[i].addr_text);
+
+            ls[i].setfib = -1;
+        }
+
+#endif
+#endif
+
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
 
         ngx_memzero(&af, sizeof(struct accept_filter_arg));
@@ -473,6 +496,19 @@ ngx_configure_listening_sockets(ngx_cycl
             }
         }
 
+#if (NGX_HAVE_SETFIB)
+        if (ls[i].setfib != -1) {
+            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
+                           (const void *) &ls[i].setfib, sizeof(int))
+                == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                              "setsockopt(SO_SETFIB, %d) %V failed, ignored",
+                              ls[i].setfib, &ls[i].addr_text);
+            }
+        }
+#endif
+
 #if 0
         if (1) {
             int tcp_nodelay = 1;
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -69,6 +69,9 @@ struct ngx_listening_s {
     char               *accept_filter;
 #endif
 #endif
+#if (NGX_HAVE_SETFIB)
+    int                 setfib;
+#endif
 
 };
 
--- a/src/core/ngx_log.h
+++ b/src/core/ngx_log.h
@@ -68,7 +68,23 @@ struct ngx_log_s {
 
 /*********************************/
 
-#if (NGX_HAVE_GCC_VARIADIC_MACROS)
+#if (NGX_HAVE_C99_VARIADIC_MACROS)
+
+#define NGX_HAVE_VARIADIC_MACROS  1
+
+#define ngx_log_error(level, log, ...)                                        \
+    if ((log)->log_level >= level) ngx_log_error_core(level, log, __VA_ARGS__)
+
+void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
+    const char *fmt, ...);
+
+#define ngx_log_debug(level, log, ...)                                        \
+    if ((log)->log_level & level)                                             \
+        ngx_log_error_core(NGX_LOG_DEBUG, log, __VA_ARGS__)
+
+/*********************************/
+
+#elif (NGX_HAVE_GCC_VARIADIC_MACROS)
 
 #define NGX_HAVE_VARIADIC_MACROS  1
 
@@ -84,22 +100,6 @@ void ngx_log_error_core(ngx_uint_t level
 
 /*********************************/
 
-#elif (NGX_HAVE_C99_VARIADIC_MACROS)
-
-#define NGX_HAVE_VARIADIC_MACROS  1
-
-#define ngx_log_error(level, log, ...)                                        \
-    if ((log)->log_level >= level) ngx_log_error_core(level, log, __VA_ARGS__)
-
-void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
-    const char *fmt, ...);
-
-#define ngx_log_debug(level, log, ...)                                        \
-    if ((log)->log_level & level)                                             \
-        ngx_log_error_core(NGX_LOG_DEBUG, log, __VA_ARGS__)
-
-/*********************************/
-
 #else /* NO VARIADIC MACROS */
 
 #define NGX_HAVE_VARIADIC_MACROS  0
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -183,15 +183,6 @@ static ngx_conf_bitmask_t  ngx_http_fast
 };
 
 
-static ngx_conf_bitmask_t  ngx_http_fastcgi_ignore_headers_masks[] = {
-    { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
-    { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
-    { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
-    { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
-    { ngx_null_string, 0 }
-};
-
-
 ngx_module_t  ngx_http_fastcgi_module;
 
 
@@ -430,7 +421,7 @@ static ngx_command_t  ngx_http_fastcgi_c
       ngx_conf_set_bitmask_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_headers),
-      &ngx_http_fastcgi_ignore_headers_masks },
+      &ngx_http_upstream_ignore_headers_masks },
 
     { ngx_string("fastcgi_catch_stderr"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
@@ -524,19 +515,6 @@ static ngx_str_t  ngx_http_fastcgi_hide_
 
 #if (NGX_HTTP_CACHE)
 
-static ngx_str_t  ngx_http_fastcgi_hide_cache_headers[] = {
-    ngx_string("Status"),
-    ngx_string("X-Accel-Expires"),
-    ngx_string("X-Accel-Redirect"),
-    ngx_string("X-Accel-Limit-Rate"),
-    ngx_string("X-Accel-Buffering"),
-    ngx_string("X-Accel-Charset"),
-    ngx_string("Set-Cookie"),
-    ngx_string("P3P"),
-    ngx_null_string
-};
-
-
 static ngx_keyval_t  ngx_http_fastcgi_cache_headers[] = {
     { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
     { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
@@ -2034,7 +2012,6 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
     u_char                       *p;
     size_t                        size;
     uintptr_t                    *code;
-    ngx_str_t                    *hide;
     ngx_uint_t                    i;
     ngx_array_t                   headers_names;
     ngx_keyval_t                 *src;
@@ -2260,18 +2237,8 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
     hash.name = "fastcgi_hide_headers_hash";
 
-#if (NGX_HTTP_CACHE)
-
-    hide = conf->upstream.cache ? ngx_http_fastcgi_hide_cache_headers:
-                                  ngx_http_fastcgi_hide_headers;
-#else
-
-    hide = ngx_http_fastcgi_hide_headers;
-
-#endif
-
     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
-                                            &prev->upstream, hide, &hash)
+             &prev->upstream, ngx_http_fastcgi_hide_headers, &hash)
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -157,15 +157,6 @@ static ngx_conf_bitmask_t  ngx_http_prox
 };
 
 
-static ngx_conf_bitmask_t  ngx_http_proxy_ignore_headers_masks[] = {
-    { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
-    { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
-    { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
-    { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
-    { ngx_null_string, 0 }
-};
-
-
 ngx_module_t  ngx_http_proxy_module;
 
 
@@ -432,7 +423,7 @@ static ngx_command_t  ngx_http_proxy_com
       ngx_conf_set_bitmask_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_headers),
-      &ngx_http_proxy_ignore_headers_masks },
+      &ngx_http_upstream_ignore_headers_masks },
 
 #if (NGX_HTTP_SSL)
 
@@ -521,21 +512,6 @@ static ngx_keyval_t  ngx_http_proxy_cach
     { ngx_null_string, ngx_null_string }
 };
 
-
-static ngx_str_t  ngx_http_proxy_hide_cache_headers[] = {
-    ngx_string("Date"),
-    ngx_string("Server"),
-    ngx_string("X-Pad"),
-    ngx_string("X-Accel-Expires"),
-    ngx_string("X-Accel-Redirect"),
-    ngx_string("X-Accel-Limit-Rate"),
-    ngx_string("X-Accel-Buffering"),
-    ngx_string("X-Accel-Charset"),
-    ngx_string("Set-Cookie"),
-    ngx_string("P3P"),
-    ngx_null_string
-};
-
 #endif
 
 
@@ -1734,7 +1710,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
     ngx_http_proxy_loc_conf_t *conf = child;
 
     size_t                      size;
-    ngx_str_t                  *h;
     ngx_keyval_t               *s;
     ngx_hash_init_t             hash;
     ngx_http_proxy_redirect_t  *pr;
@@ -2018,18 +1993,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
     hash.bucket_size = conf->headers_hash_bucket_size;
     hash.name = "proxy_headers_hash";
 
-#if (NGX_HTTP_CACHE)
-
-    h = conf->upstream.cache ? ngx_http_proxy_hide_cache_headers:
-                               ngx_http_proxy_hide_headers;
-#else
-
-    h = ngx_http_proxy_hide_headers;
-
-#endif
-
     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
-                                            &prev->upstream, h, &hash)
+            &prev->upstream, ngx_http_proxy_hide_headers, &hash)
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -70,15 +70,6 @@ static ngx_conf_bitmask_t ngx_http_scgi_
 };
 
 
-static ngx_conf_bitmask_t ngx_http_scgi_ignore_headers_masks[] = {
-    { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
-    { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
-    { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
-    { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
-    { ngx_null_string, 0 }
-};
-
-
 ngx_module_t  ngx_http_scgi_module;
 
 
@@ -296,7 +287,7 @@ static ngx_command_t ngx_http_scgi_comma
       ngx_conf_set_bitmask_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_scgi_loc_conf_t, upstream.ignore_headers),
-      &ngx_http_scgi_ignore_headers_masks },
+      &ngx_http_upstream_ignore_headers_masks },
 
       ngx_null_command
 };
@@ -346,19 +337,6 @@ static ngx_str_t ngx_http_scgi_hide_head
 
 #if (NGX_HTTP_CACHE)
 
-static ngx_str_t  ngx_http_scgi_hide_cache_headers[] = {
-    ngx_string("Status"),
-    ngx_string("X-Accel-Expires"),
-    ngx_string("X-Accel-Redirect"),
-    ngx_string("X-Accel-Limit-Rate"),
-    ngx_string("X-Accel-Buffering"),
-    ngx_string("X-Accel-Charset"),
-    ngx_string("Set-Cookie"),
-    ngx_string("P3P"),
-    ngx_null_string
-};
-
-
 static ngx_keyval_t  ngx_http_scgi_cache_headers[] = {
     { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
     { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
@@ -1061,7 +1039,6 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t 
     u_char                       *p;
     size_t                        size;
     uintptr_t                    *code;
-    ngx_str_t                    *hide;
     ngx_uint_t                    i;
     ngx_array_t                   headers_names;
     ngx_keyval_t                 *src;
@@ -1280,18 +1257,8 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t 
     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
     hash.name = "scgi_hide_headers_hash";
 
-#if (NGX_HTTP_CACHE)
-
-    hide = conf->upstream.cache ? ngx_http_scgi_hide_cache_headers:
-                                  ngx_http_scgi_hide_headers;
-#else
-
-    hide = ngx_http_scgi_hide_headers;
-
-#endif
-
     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
-                                            &prev->upstream, hide, &hash)
+            &prev->upstream, ngx_http_scgi_hide_headers, &hash)
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
--- a/src/http/modules/ngx_http_sub_filter_module.c
+++ b/src/http/modules/ngx_http_sub_filter_module.c
@@ -29,6 +29,8 @@ typedef enum {
 
 typedef struct {
     ngx_str_t                  match;
+    ngx_str_t                  saved;
+    ngx_str_t                  looked;
 
     ngx_uint_t                 once;   /* unsigned  once:1 */
 
@@ -47,8 +49,6 @@ typedef struct {
     ngx_str_t                  sub;
 
     ngx_uint_t                 state;
-    size_t                     saved;
-    size_t                     looked;
 } ngx_http_sub_ctx_t;
 
 
@@ -147,6 +147,16 @@ ngx_http_sub_header_filter(ngx_http_requ
         return NGX_ERROR;
     }
 
+    ctx->saved.data = ngx_pnalloc(r->pool, slcf->match.len);
+    if (ctx->saved.data == NULL) {
+        return NGX_ERROR;
+    }
+
+    ctx->looked.data = ngx_pnalloc(r->pool, slcf->match.len);
+    if (ctx->looked.data == NULL) {
+        return NGX_ERROR;
+    }
+
     ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module);
 
     ctx->match = slcf->match;
@@ -226,13 +236,13 @@ ngx_http_sub_body_filter(ngx_http_reques
         while (ctx->pos < ctx->buf->last) {
 
             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "saved: %d state: %d", ctx->saved, ctx->state);
+                           "saved: \"%V\" state: %d", &ctx->saved, ctx->state);
 
             rc = ngx_http_sub_parse(r, ctx);
 
             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "parse: %d, looked: %d %p-%p",
-                           rc, ctx->looked, ctx->copy_start, ctx->copy_end);
+                           "parse: %d, looked: \"%V\" %p-%p",
+                           rc, &ctx->looked, ctx->copy_start, ctx->copy_end);
 
             if (rc == NGX_ERROR) {
                 return rc;
@@ -241,9 +251,9 @@ ngx_http_sub_body_filter(ngx_http_reques
             if (ctx->copy_start != ctx->copy_end) {
 
                 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                               "saved: %d", ctx->saved);
+                               "saved: \"%V\"", &ctx->saved);
 
-                if (ctx->saved) {
+                if (ctx->saved.len) {
 
                     if (ctx->free) {
                         cl = ctx->free;
@@ -265,14 +275,19 @@ ngx_http_sub_body_filter(ngx_http_reques
                         cl->buf = b;
                     }
 
+                    b->pos = ngx_pnalloc(r->pool, ctx->saved.len);
+                    if (b->pos == NULL) {
+                        return NGX_ERROR;
+                    }
+
+                    ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len);
+                    b->last = b->pos + ctx->saved.len;
                     b->memory = 1;
-                    b->pos = ctx->match.data;
-                    b->last = ctx->match.data + ctx->saved;
 
                     *ctx->last_out = cl;
                     ctx->last_out = &cl->next;
 
-                    ctx->saved = 0;
+                    ctx->saved.len = 0;
                 }
 
                 if (ctx->free) {
@@ -405,7 +420,8 @@ ngx_http_sub_body_filter(ngx_http_reques
 
         ctx->buf = NULL;
 
-        ctx->saved = ctx->looked;
+        ctx->saved.len = ctx->looked.len;
+        ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->looked.len);
     }
 
     if (ctx->out == NULL && ctx->busy == NULL) {
@@ -496,7 +512,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
         ctx->copy_start = ctx->pos;
         ctx->copy_end = ctx->buf->last;
         ctx->pos = ctx->buf->last;
-        ctx->looked = 0;
+        ctx->looked.len = 0;
 
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once");
 
@@ -504,7 +520,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
     }
 
     state = ctx->state;
-    looked = ctx->looked;
+    looked = ctx->looked.len;
     last = ctx->buf->last;
     copy_end = ctx->copy_end;
 
@@ -522,6 +538,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
             for ( ;; ) {
                 if (ch == match) {
                     copy_end = p;
+                    ctx->looked.data[0] = *p;
                     looked = 1;
                     state = sub_match_state;
 
@@ -538,7 +555,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
 
             ctx->state = state;
             ctx->pos = p;
-            ctx->looked = looked;
+            ctx->looked.len = looked;
             ctx->copy_end = p;
 
             if (ctx->copy_start == NULL) {
@@ -555,16 +572,17 @@ ngx_http_sub_parse(ngx_http_request_t *r
         /* state == sub_match_state */
 
         if (ch == ctx->match.data[looked]) {
+            ctx->looked.data[looked] = *p;
             looked++;
 
             if (looked == ctx->match.len) {
                 if ((size_t) (p - ctx->pos) < looked) {
-                    ctx->saved = 0;
+                    ctx->saved.len = 0;
                 }
 
                 ctx->state = sub_start_state;
                 ctx->pos = p + 1;
-                ctx->looked = 0;
+                ctx->looked.len = 0;
                 ctx->copy_end = copy_end;
 
                 if (ctx->copy_start == NULL && copy_end) {
@@ -576,6 +594,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
 
         } else if (ch == ctx->match.data[0]) {
             copy_end = p;
+            ctx->looked.data[0] = *p;
             looked = 1;
 
         } else {
@@ -587,7 +606,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
 
     ctx->state = state;
     ctx->pos = p;
-    ctx->looked = looked;
+    ctx->looked.len = looked;
 
     ctx->copy_end = (state == sub_start_state) ? p : copy_end;
 
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -83,15 +83,6 @@ static ngx_conf_bitmask_t ngx_http_uwsgi
 };
 
 
-static ngx_conf_bitmask_t ngx_http_uwsgi_ignore_headers_masks[] = {
-    { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
-    { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
-    { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
-    { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
-    { ngx_null_string, 0 }
-};
-
-
 ngx_module_t  ngx_http_uwsgi_module;
 
 
@@ -330,7 +321,7 @@ static ngx_command_t ngx_http_uwsgi_comm
       ngx_conf_set_bitmask_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers),
-      &ngx_http_uwsgi_ignore_headers_masks },
+      &ngx_http_upstream_ignore_headers_masks },
 
       ngx_null_command
 };
@@ -379,18 +370,6 @@ static ngx_str_t ngx_http_uwsgi_hide_hea
 
 #if (NGX_HTTP_CACHE)
 
-static ngx_str_t  ngx_http_uwsgi_hide_cache_headers[] = {
-    ngx_string("X-Accel-Expires"),
-    ngx_string("X-Accel-Redirect"),
-    ngx_string("X-Accel-Limit-Rate"),
-    ngx_string("X-Accel-Buffering"),
-    ngx_string("X-Accel-Charset"),
-    ngx_string("Set-Cookie"),
-    ngx_string("P3P"),
-    ngx_null_string
-};
-
-
 static ngx_keyval_t  ngx_http_uwsgi_cache_headers[] = {
     { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
     { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
@@ -1113,7 +1092,6 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t
     u_char                       *p;
     size_t                        size;
     uintptr_t                    *code;
-    ngx_str_t                    *hide;
     ngx_uint_t                    i;
     ngx_array_t                   headers_names;
     ngx_keyval_t                 *src;
@@ -1334,18 +1312,8 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t
     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
     hash.name = "uwsgi_hide_headers_hash";
 
-#if (NGX_HTTP_CACHE)
-
-    hide = conf->upstream.cache ? ngx_http_uwsgi_hide_cache_headers:
-                                  ngx_http_uwsgi_hide_headers;
-#else
-
-    hide = ngx_http_uwsgi_hide_headers;
-
-#endif
-
     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
-                                            &prev->upstream, hide, &hash)
+            &prev->upstream, ngx_http_uwsgi_hide_headers, &hash)
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
--- 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 = '0.8.43';
+our $VERSION = '0.8.44';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1720,6 +1720,10 @@ ngx_http_add_listening(ngx_conf_t *cf, n
     ls->ipv6only = addr->opt.ipv6only;
 #endif
 
+#if (NGX_HAVE_SETFIB)
+    ls->setfib = addr->opt.setfib;
+#endif
+
     return ls;
 }
 
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -2992,6 +2992,9 @@ ngx_http_core_merge_srv_conf(ngx_conf_t 
         lsopt.backlog = NGX_LISTEN_BACKLOG;
         lsopt.rcvbuf = -1;
         lsopt.sndbuf = -1;
+#if (NGX_HAVE_SETFIB)
+        lsopt.setfib = -1;
+#endif
         lsopt.wildcard = 1;
 
         (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.addr,
@@ -3410,6 +3413,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx
     lsopt.backlog = NGX_LISTEN_BACKLOG;
     lsopt.rcvbuf = -1;
     lsopt.sndbuf = -1;
+#if (NGX_HAVE_SETFIB)
+    lsopt.setfib = -1;
+#endif
     lsopt.wildcard = u.wildcard;
 
     (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.addr,
@@ -3430,6 +3436,19 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx
             continue;
         }
 
+#if (NGX_HAVE_SETFIB)
+        if (ngx_strncmp(value[n].data, "setfib=", 7) == 0) {
+            lsopt.setfib = ngx_atoi(value[n].data + 7, value[n].len - 7);
+
+            if (lsopt.setfib == NGX_ERROR || lsopt.setfib == 0) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "invalid setfib \"%V\"", &value[n]);
+                return NGX_CONF_ERROR;
+            }
+
+            continue;
+        }
+#endif
         if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
             lsopt.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
             lsopt.set = 1;
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -71,6 +71,9 @@ typedef struct {
     int                        backlog;
     int                        rcvbuf;
     int                        sndbuf;
+#if (NGX_HAVE_SETFIB)
+    int                        setfib;
+#endif
 
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
     char                      *accept_filter;
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -555,7 +555,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
     }
 
     if (n == 1) {
-        if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
+        if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
                            "https ssl handshake: 0x%02Xd", buf[0]);
 
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -72,6 +72,8 @@ static void ngx_http_upstream_finalize_r
 
 static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
+    ngx_table_elt_t *h, ngx_uint_t offset);
 static ngx_int_t
     ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset);
@@ -189,7 +191,7 @@ ngx_http_upstream_header_t  ngx_http_ups
                  ngx_http_upstream_rewrite_refresh, 0, 0 },
 
     { ngx_string("Set-Cookie"),
-                 ngx_http_upstream_ignore_header_line, 0,
+                 ngx_http_upstream_process_set_cookie, 0,
                  ngx_http_upstream_copy_header_line, 0, 1 },
 
     { ngx_string("Content-Disposition"),
@@ -355,6 +357,16 @@ ngx_conf_bitmask_t  ngx_http_upstream_ca
 };
 
 
+ngx_conf_bitmask_t  ngx_http_upstream_ignore_headers_masks[] = {
+    { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
+    { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
+    { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
+    { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
+    { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE },
+    { ngx_null_string, 0 }
+};
+
+
 ngx_int_t
 ngx_http_upstream_create(ngx_http_request_t *r)
 {
@@ -2985,6 +2997,24 @@ ngx_http_upstream_ignore_header_line(ngx
 
 
 static ngx_int_t
+ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
+    ngx_uint_t offset)
+{
+#if (NGX_HTTP_CACHE)
+    ngx_http_upstream_t  *u;
+
+    u = r->upstream;
+
+    if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE)) {
+        u->cacheable = 0;
+    }
+#endif
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
 ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset)
 {
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -43,6 +43,7 @@
 #define NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES     0x00000004
 #define NGX_HTTP_UPSTREAM_IGN_EXPIRES        0x00000008
 #define NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL  0x00000010
+#define NGX_HTTP_UPSTREAM_IGN_SET_COOKIE     0x00000020
 
 
 typedef struct {
@@ -337,6 +338,7 @@ ngx_int_t ngx_http_upstream_hide_headers
 
 extern ngx_module_t        ngx_http_upstream_module;
 extern ngx_conf_bitmask_t  ngx_http_upstream_cache_method_mask[];
+extern ngx_conf_bitmask_t  ngx_http_upstream_ignore_headers_masks[];
 
 
 #endif /* _NGX_HTTP_UPSTREAM_H_INCLUDED_ */
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -30,7 +30,6 @@ typedef int               ngx_err_t;
 #define NGX_EINVAL        EINVAL
 #define NGX_ENOSPC        ENOSPC
 #define NGX_EPIPE         EPIPE
-#define NGX_EAGAIN        EAGAIN
 #define NGX_EINPROGRESS   EINPROGRESS
 #define NGX_EADDRINUSE    EADDRINUSE
 #define NGX_ECONNABORTED  ECONNABORTED
@@ -48,6 +47,11 @@ typedef int               ngx_err_t;
 #define NGX_EILSEQ        EILSEQ
 #define NGX_ENOMOREFILES  0
 
+#if (__hpux__)
+#define NGX_EAGAIN        EWOULDBLOCK
+#else
+#define NGX_EAGAIN        EAGAIN
+#endif
 
 
 #define ngx_errno                  errno