changeset 463:a8424ffa495c NGINX_0_7_39

nginx 0.7.39 *) Bugfix: large response with SSI might hang, if gzipping was enabled; the bug had appeared in 0.7.28. Thanks to Artem Bokhan. *) Bugfix: a segmentation fault might occur in worker process, if short static variants are used in a "try_files" directive.
author Igor Sysoev <http://sysoev.ru>
date Mon, 02 Mar 2009 00:00:00 +0300
parents 9ef0e36f3cd5
children ead634c4b006
files CHANGES CHANGES.ru src/core/nginx.c src/core/nginx.h src/core/ngx_conf_file.c src/core/ngx_cycle.c src/core/ngx_file.c src/core/ngx_inet.c src/core/ngx_inet.h src/core/ngx_log.c src/event/ngx_event.c src/event/ngx_event_connect.c src/event/ngx_event_openssl.c src/http/modules/ngx_http_access_module.c src/http/modules/ngx_http_charset_filter_module.c src/http/modules/ngx_http_geo_module.c src/http/modules/ngx_http_gzip_filter_module.c src/http/modules/ngx_http_log_module.c src/http/modules/ngx_http_map_module.c src/http/modules/ngx_http_range_filter_module.c src/http/modules/ngx_http_realip_module.c src/http/modules/ngx_http_ssi_filter_module.c src/http/modules/ngx_http_sub_filter_module.c src/http/modules/ngx_http_userid_filter_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_header_filter_module.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/http/ngx_http_upstream.c src/http/ngx_http_variables.c
diffstat 33 files changed, 349 insertions(+), 237 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,14 @@
 
+Changes with nginx 0.7.39                                        02 Mar 2009
+
+    *) Bugfix: large response with SSI might hang, if gzipping was enabled; 
+       the bug had appeared in 0.7.28.
+       Thanks to Artem Bokhan.
+
+    *) Bugfix: a segmentation fault might occur in worker process, if short 
+       static variants are used in a "try_files" directive.
+
+
 Changes with nginx 0.7.38                                        23 Feb 2009
 
     *) Feature: authentication failures logging.
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,15 @@
 
+Изменения в nginx 0.7.39                                          02.03.2009
+
+    *) Исправление: при включённом сжатии большие ответы с использованием 
+       SSI могли зависать; ошибка появилась в 0.7.28.
+       Спасибо Артёму Бохану.
+
+    *) Исправление: при использовании коротких статических вариантов в 
+       директиве try_files в рабочем процессе мог произойти segmentation 
+       fault.
+
+
 Изменения в nginx 0.7.38                                          23.02.2009
 
     *) Добавление: логгирование ошибок аутентификации.
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -388,7 +388,7 @@ ngx_add_inherited_sockets(ngx_cycle_t *c
 
     if (ngx_array_init(&cycle->listening, cycle->pool, 10,
                        sizeof(ngx_listening_t))
-        == NGX_ERROR)
+        != NGX_OK)
     {
         return NGX_ERROR;
     }
@@ -838,7 +838,7 @@ ngx_core_module_init_conf(ngx_cycle_t *c
         ccf->pid.data = (u_char *) NGX_PID_PATH;
     }
 
-    if (ngx_conf_full_name(cycle, &ccf->pid, 0) == NGX_ERROR) {
+    if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) {
         return NGX_CONF_ERROR;
     }
 
@@ -858,7 +858,7 @@ ngx_core_module_init_conf(ngx_cycle_t *c
         ccf->lock_file.data = (u_char *) NGX_LOCK_PATH;
     }
 
-    if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) == NGX_ERROR) {
+    if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) {
         return NGX_CONF_ERROR;
     }
 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VERSION      "0.7.38"
+#define NGINX_VERSION      "0.7.39"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -741,7 +741,7 @@ ngx_conf_include(ngx_conf_t *cf, ngx_com
 
     ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
 
-    if (ngx_conf_full_name(cf->cycle, &file, 1) == NGX_ERROR) {
+    if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
         return NGX_CONF_ERROR;
     }
 
@@ -854,7 +854,7 @@ ngx_conf_open_file(ngx_cycle_t *cycle, n
     if (name) {
         full = *name;
 
-        if (ngx_conf_full_name(cycle, &full, 0) == NGX_ERROR) {
+        if (ngx_conf_full_name(cycle, &full, 0) != NGX_OK) {
             return NULL;
         }
 
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -136,7 +136,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
     }
 
     if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
-        == NGX_ERROR)
+        != NGX_OK)
     {
         ngx_destroy_pool(pool);
         return NULL;
@@ -155,7 +155,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
     }
 
     if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))
-        == NGX_ERROR)
+        != NGX_OK)
     {
         ngx_destroy_pool(pool);
         return NULL;
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -259,7 +259,7 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, n
         path->name.len--;
     }
 
-    if (ngx_conf_full_name(cf->cycle, &path->name, 0) == NGX_ERROR) {
+    if (ngx_conf_full_name(cf->cycle, &path->name, 0) != NGX_OK) {
         return NULL;
     }
 
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -226,26 +226,25 @@ ngx_inet6_ntop(u_char *p, u_char *text, 
 /* AF_INET only */
 
 ngx_int_t
-ngx_ptocidr(ngx_str_t *text, void *cidr)
+ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
 {
-    u_char           *addr, *mask, *last;
-    ngx_int_t         shift;
-    ngx_inet_cidr_t  *in_cidr;
+    u_char     *addr, *mask, *last;
+    ngx_int_t   shift;
 
-    in_cidr = cidr;
     addr = text->data;
     last = addr + text->len;
 
     mask = ngx_strlchr(addr, last, '/');
 
-    in_cidr->addr = ngx_inet_addr(addr, (mask ? mask : last) - addr);
+    cidr->u.in.addr = ngx_inet_addr(addr, (mask ? mask : last) - addr);
 
-    if (in_cidr->addr == INADDR_NONE) {
+    if (cidr->u.in.addr == INADDR_NONE) {
         return NGX_ERROR;
     }
 
     if (mask == NULL) {
-        in_cidr->mask = 0xffffffff;
+        cidr->family = AF_INET;
+        cidr->u.in.mask = 0xffffffff;
         return NGX_OK;
     }
 
@@ -256,26 +255,28 @@ ngx_ptocidr(ngx_str_t *text, void *cidr)
         return NGX_ERROR;
     }
 
+    cidr->family = AF_INET;
+
     if (shift == 0) {
 
         /* the x86 compilers use the shl instruction that shifts by modulo 32 */
 
-        in_cidr->mask = 0;
+        cidr->u.in.mask = 0;
 
-        if (in_cidr->addr == 0) {
+        if (cidr->u.in.addr == 0) {
             return NGX_OK;
         }
 
         return NGX_DONE;
     }
 
-    in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
+    cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
 
-    if (in_cidr->addr == (in_cidr->addr & in_cidr->mask)) {
+    if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
         return NGX_OK;
     }
 
-    in_cidr->addr &= in_cidr->mask;
+    cidr->u.in.addr &= cidr->u.in.mask;
 
     return NGX_DONE;
 }
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -35,50 +35,71 @@
 
 
 typedef struct {
-    in_addr_t         addr;
-    in_addr_t         mask;
-} ngx_inet_cidr_t;
+    in_addr_t                 addr;
+    in_addr_t                 mask;
+} ngx_in_cidr_t;
+
+
+#if (NGX_HAVE_INET6)
+
+typedef struct {
+    struct in6_addr           addr;
+    struct in6_addr           mask;
+} ngx_in6_cidr_t;
+
+#endif
+
+
+typedef struct {
+    ngx_uint_t                family;
+    union {
+        ngx_in_cidr_t         in;
+#if (NGX_HAVE_INET6)
+        ngx_in6_cidr_t        in6;
+#endif
+    } u;
+} ngx_cidr_t;
 
 
 typedef union {
-    in_addr_t         in_addr;
+    in_addr_t                 in_addr;
 } ngx_url_addr_t;
 
 
 typedef struct {
-    struct sockaddr  *sockaddr;
-    socklen_t         socklen;
-    ngx_str_t         name;
+    struct sockaddr          *sockaddr;
+    socklen_t                 socklen;
+    ngx_str_t                 name;
 } ngx_peer_addr_t;
 
 
 typedef struct {
-    ngx_str_t         url;
-    ngx_str_t         host;
-    ngx_str_t         port_text;
-    ngx_str_t         uri;
+    ngx_str_t                 url;
+    ngx_str_t                 host;
+    ngx_str_t                 port_text;
+    ngx_str_t                 uri;
 
-    in_port_t         port;
-    in_port_t         default_port;
-    int               family;
+    in_port_t                 port;
+    in_port_t                 default_port;
+    int                       family;
 
-    unsigned          listen:1;
-    unsigned          uri_part:1;
-    unsigned          no_resolve:1;
-    unsigned          one_addr:1;
+    unsigned                  listen:1;
+    unsigned                  uri_part:1;
+    unsigned                  no_resolve:1;
+    unsigned                  one_addr:1;
 
-    unsigned          no_port:1;
-    unsigned          wildcard:1;
+    unsigned                  no_port:1;
+    unsigned                  wildcard:1;
 
-    ngx_url_addr_t    addr;
+    ngx_url_addr_t            addr;
 
-    socklen_t         socklen;
-    u_char            sockaddr[NGX_SOCKADDRLEN];
+    socklen_t                 socklen;
+    u_char                    sockaddr[NGX_SOCKADDRLEN];
 
-    ngx_peer_addr_t  *addrs;
-    ngx_uint_t        naddrs;
+    ngx_peer_addr_t          *addrs;
+    ngx_uint_t                naddrs;
 
-    char             *err;
+    char                     *err;
 } ngx_url_t;
 
 
@@ -86,7 +107,7 @@ in_addr_t ngx_inet_addr(u_char *text, si
 size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len,
     ngx_uint_t port);
 size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);
-ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr);
+ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr);
 ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u);
 ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u);
 
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -329,7 +329,7 @@ ngx_set_error_log(ngx_conf_t *cf, ngx_co
         cf->cycle->new_log->file->name = value[1];
 
         if (ngx_conf_full_name(cf->cycle, &cf->cycle->new_log->file->name, 0)
-            == NGX_ERROR)
+            != NGX_OK)
         {
             return NGX_CONF_ERROR;
         }
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -1040,18 +1040,16 @@ ngx_event_debug_connection(ngx_conf_t *c
     ngx_str_t          *value;
     ngx_event_debug_t  *dc;
     struct hostent     *h;
-    ngx_inet_cidr_t     in_cidr;
+    ngx_cidr_t          cidr;
 
     value = cf->args->elts;
 
-    /* AF_INET only */
-
     dc = ngx_array_push(&ecf->debug_connection);
     if (dc == NULL) {
         return NGX_CONF_ERROR;
     }
 
-    rc = ngx_ptocidr(&value[1], &in_cidr);
+    rc = ngx_ptocidr(&value[1], &cidr);
 
     if (rc == NGX_DONE) {
         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
@@ -1060,8 +1058,18 @@ ngx_event_debug_connection(ngx_conf_t *c
     }
 
     if (rc == NGX_OK) {
-        dc->mask = in_cidr.mask;
-        dc->addr = in_cidr.addr;
+
+        /* AF_INET only */
+
+        if (cidr.family != AF_INET) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "\"debug_connection\" supports IPv4 only");
+            return NGX_CONF_ERROR;
+        }
+
+        dc->mask = cidr.u.in.mask;
+        dc->addr = cidr.u.in.addr;
+
         return NGX_CONF_OK;
     }
 
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -155,6 +155,7 @@ ngx_event_connect_peer(ngx_peer_connecti
                  */
                 || err == NGX_EAGAIN
 #endif
+                || err == NGX_ECONNRESET
                 || err == NGX_ENETDOWN
                 || err == NGX_ENETUNREACH
                 || err == NGX_EHOSTDOWN
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -189,7 +189,7 @@ ngx_int_t
 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
     ngx_str_t *key)
 {
-    if (ngx_conf_full_name(cf->cycle, cert, 1) == NGX_ERROR) {
+    if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -202,7 +202,7 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_
         return NGX_ERROR;
     }
 
-    if (ngx_conf_full_name(cf->cycle, key, 1) == NGX_ERROR) {
+    if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -233,7 +233,7 @@ ngx_ssl_client_certificate(ngx_conf_t *c
         return NGX_OK;
     }
 
-    if (ngx_conf_full_name(cf->cycle, cert, 1) == NGX_ERROR) {
+    if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -391,7 +391,7 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_
         return NGX_OK;
     }
 
-    if (ngx_conf_full_name(cf->cycle, file, 1) == NGX_ERROR) {
+    if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
         return NGX_ERROR;
     }
 
--- a/src/http/modules/ngx_http_access_module.c
+++ b/src/http/modules/ngx_http_access_module.c
@@ -141,7 +141,7 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx
 
     ngx_int_t                rc;
     ngx_str_t               *value;
-    ngx_inet_cidr_t          in_cidr;
+    ngx_cidr_t               cidr;
     ngx_http_access_rule_t  *rule;
 
     if (alcf->rules == NULL) {
@@ -168,7 +168,7 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx
         return NGX_CONF_OK;
     }
 
-    rc = ngx_ptocidr(&value[1], &in_cidr);
+    rc = ngx_ptocidr(&value[1], &cidr);
 
     if (rc == NGX_ERROR) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
@@ -176,13 +176,19 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx
         return NGX_CONF_ERROR;
     }
 
+    if (cidr.family != AF_INET) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "\"allow\" supports IPv4 only");
+        return NGX_CONF_ERROR;
+    }
+
     if (rc == NGX_DONE) {
         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                            "low address bits of %V are meaningless", &value[1]);
     }
 
-    rule->mask = in_cidr.mask;
-    rule->addr = in_cidr.addr;
+    rule->mask = cidr.u.in.mask;
+    rule->addr = cidr.u.in.addr;
 
     return NGX_CONF_OK;
 }
--- a/src/http/modules/ngx_http_charset_filter_module.c
+++ b/src/http/modules/ngx_http_charset_filter_module.c
@@ -1421,19 +1421,21 @@ ngx_http_charset_create_main_conf(ngx_co
     }
 
     if (ngx_array_init(&mcf->charsets, cf->pool, 2, sizeof(ngx_http_charset_t))
-        == NGX_ERROR)
+        != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
 
     if (ngx_array_init(&mcf->tables, cf->pool, 1,
-                       sizeof(ngx_http_charset_tables_t)) == NGX_ERROR)
+                       sizeof(ngx_http_charset_tables_t))
+        != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
 
     if (ngx_array_init(&mcf->recodes, cf->pool, 2,
-                       sizeof(ngx_http_charset_recode_t)) == NGX_ERROR)
+                       sizeof(ngx_http_charset_recode_t))
+        != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -778,7 +778,7 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
     ngx_int_t                        rc, del;
     ngx_str_t                       *net;
     ngx_uint_t                       i;
-    ngx_inet_cidr_t                  cidrin;
+    ngx_cidr_t                       cidr;
     ngx_http_variable_value_t       *val, *old;
 
     if (ctx->tree == NULL) {
@@ -789,8 +789,8 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
     }
 
     if (ngx_strcmp(value[0].data, "default") == 0) {
-        cidrin.addr = 0;
-        cidrin.mask = 0;
+        cidr.u.in.addr = 0;
+        cidr.u.in.mask = 0;
         net = &value[0];
 
     } else {
@@ -804,11 +804,11 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
         }
 
         if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
-            cidrin.addr = 0xffffffff;
-            cidrin.mask = 0xffffffff;
+            cidr.u.in.addr = 0xffffffff;
+            cidr.u.in.mask = 0xffffffff;
 
         } else {
-            rc = ngx_ptocidr(net, &cidrin);
+            rc = ngx_ptocidr(net, &cidr);
 
             if (rc == NGX_ERROR) {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -816,18 +816,25 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
                 return NGX_CONF_ERROR;
             }
 
+            if (cidr.family != AF_INET) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "\"geo\" supports IPv4 only");
+                return NGX_CONF_ERROR;
+            }
+
             if (rc == NGX_DONE) {
                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                                    "low address bits of %V are meaningless",
                                    net);
             }
 
-            cidrin.addr = ntohl(cidrin.addr);
-            cidrin.mask = ntohl(cidrin.mask);
+            cidr.u.in.addr = ntohl(cidr.u.in.addr);
+            cidr.u.in.mask = ntohl(cidr.u.in.mask);
         }
 
         if (del) {
-            if (ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask)
+            if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
+                                       cidr.u.in.mask)
                 != NGX_OK)
             {
                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
@@ -845,7 +852,7 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
     }
 
     for (i = 2; i; i--) {
-        rc = ngx_radix32tree_insert(ctx->tree, cidrin.addr, cidrin.mask,
+        rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, cidr.u.in.mask,
                                     (uintptr_t) val);
         if (rc == NGX_OK) {
             return NGX_CONF_OK;
@@ -858,13 +865,13 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
         /* rc == NGX_BUSY */
 
         old  = (ngx_http_variable_value_t *)
-                   ngx_radix32tree_find(ctx->tree, cidrin.addr & cidrin.mask);
+              ngx_radix32tree_find(ctx->tree, cidr.u.in.addr & cidr.u.in.mask);
 
         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
                 net, val, old);
 
-        rc = ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask);
+        rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, cidr.u.in.mask);
 
         if (rc == NGX_ERROR) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -19,6 +19,7 @@ typedef struct {
 
     ngx_bufs_t           bufs;
 
+    size_t               postpone_gzipping;
     ngx_int_t            level;
     size_t               wbits;
     size_t               memlevel;
@@ -84,7 +85,7 @@ struct gztrailer {
 
 static void ngx_http_gzip_filter_memory(ngx_http_request_t *r,
     ngx_http_gzip_ctx_t *ctx);
-static ngx_int_t ngx_http_gzip_filter_copy_recycled(ngx_http_gzip_ctx_t *ctx,
+static ngx_int_t ngx_http_gzip_filter_buffer(ngx_http_gzip_ctx_t *ctx,
     ngx_chain_t *in);
 static ngx_int_t ngx_http_gzip_filter_deflate_start(ngx_http_request_t *r,
     ngx_http_gzip_ctx_t *ctx);
@@ -170,6 +171,13 @@ static ngx_command_t  ngx_http_gzip_filt
       offsetof(ngx_http_gzip_conf_t, memlevel),
       &ngx_http_gzip_hash_p },
 
+    { ngx_string("postpone_gzipping"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gzip_conf_t, postpone_gzipping),
+      NULL },
+
     { ngx_string("gzip_no_buffer"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -257,7 +265,7 @@ ngx_http_gzip_header_filter(ngx_http_req
     ngx_http_set_ctx(r, ctx, ngx_http_gzip_filter_module);
 
     ctx->request = r;
-    ctx->buffering = 1;
+    ctx->buffering = (conf->postpone_gzipping != 0);
 
     ngx_http_gzip_filter_memory(r, ctx);
 
@@ -301,8 +309,17 @@ ngx_http_gzip_body_filter(ngx_http_reque
 
     if (ctx->buffering) {
 
+        /*
+         * With default memory settings zlib starts to output gzipped data
+         * only after it has got about 90K, so it makes sense to allocate
+         * zlib memory (200-400K) only after we have enough data to compress.
+         * Although we copy buffers, nevertheless for not big responses
+         * this allows to allocate zlib memory, to compress and to output
+         * the response in one step using hot CPU cache.
+         */
+
         if (in) {
-            switch (ngx_http_gzip_filter_copy_recycled(ctx, in)) {
+            switch (ngx_http_gzip_filter_buffer(ctx, in)) {
 
             case NGX_OK:
                 return NGX_OK;
@@ -327,7 +344,7 @@ ngx_http_gzip_body_filter(ngx_http_reque
     }
 
     if (in) {
-        if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) {
+        if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
             goto failed;
         }
     }
@@ -482,12 +499,13 @@ ngx_http_gzip_filter_memory(ngx_http_req
 
 
 static ngx_int_t
-ngx_http_gzip_filter_copy_recycled(ngx_http_gzip_ctx_t *ctx, ngx_chain_t *in)
+ngx_http_gzip_filter_buffer(ngx_http_gzip_ctx_t *ctx, ngx_chain_t *in)
 {
-    size_t               size, buffered;
-    ngx_buf_t           *b, *buf;
-    ngx_chain_t         *cl, **ll;
-    ngx_http_request_t  *r;
+    size_t                 size, buffered;
+    ngx_buf_t             *b, *buf;
+    ngx_chain_t           *cl, **ll;
+    ngx_http_request_t    *r;
+    ngx_http_gzip_conf_t  *conf;
 
     r = ctx->request;
 
@@ -501,6 +519,8 @@ ngx_http_gzip_filter_copy_recycled(ngx_h
         ll = &cl->next;
     }
 
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
+
     while (in) {
         cl = ngx_alloc_chain_link(r->pool);
         if (cl == NULL) {
@@ -512,25 +532,11 @@ ngx_http_gzip_filter_copy_recycled(ngx_h
         size = b->last - b->pos;
         buffered += size;
 
-        if (b->flush || b->last_buf) {
-            ctx->buffering = 0;
-
-        } else if (buffered > ctx->allocated / 2) {
-
-            /*
-             * With default memory settings zlib starts to output gzipped data
-             * only after it has got about 90K, so it makes sense to allocate
-             * zlib memory (200-400K) only after we have enough data
-             * to compress.  Although we copy recycled buffers, nevertheless
-             * for responses up to 120K this allows to allocate zlib memory,
-             * to compress and to output the response in one step
-             * using hot CPU cache.
-             */
-
+        if (b->flush || b->last_buf || buffered > conf->postpone_gzipping) {
             ctx->buffering = 0;
         }
 
-        if (ctx->buffering && size && b->recycled) {
+        if (ctx->buffering && size) {
 
             buf = ngx_create_temp_buf(r->pool, size);
             if (buf == NULL) {
@@ -1077,9 +1083,10 @@ ngx_http_gzip_create_conf(ngx_conf_t *cf
     conf->enable = NGX_CONF_UNSET;
     conf->no_buffer = NGX_CONF_UNSET;
 
+    conf->postpone_gzipping = NGX_CONF_UNSET_SIZE;
     conf->level = NGX_CONF_UNSET;
-    conf->wbits = (size_t) NGX_CONF_UNSET;
-    conf->memlevel = (size_t) NGX_CONF_UNSET;
+    conf->wbits = NGX_CONF_UNSET_SIZE;
+    conf->memlevel = NGX_CONF_UNSET_SIZE;
     conf->min_length = NGX_CONF_UNSET;
 
     return conf;
@@ -1093,16 +1100,18 @@ ngx_http_gzip_merge_conf(ngx_conf_t *cf,
     ngx_http_gzip_conf_t *conf = child;
 
     ngx_conf_merge_value(conf->enable, prev->enable, 0);
+    ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0);
 
     ngx_conf_merge_bufs_value(conf->bufs, prev->bufs,
                               (128 * 1024) / ngx_pagesize, ngx_pagesize);
 
+    ngx_conf_merge_size_value(conf->postpone_gzipping, prev->postpone_gzipping,
+                              0);
     ngx_conf_merge_value(conf->level, prev->level, 1);
     ngx_conf_merge_size_value(conf->wbits, prev->wbits, MAX_WBITS);
     ngx_conf_merge_size_value(conf->memlevel, prev->memlevel,
                               MAX_MEM_LEVEL - 1);
     ngx_conf_merge_value(conf->min_length, prev->min_length, 20);
-    ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0);
 
     if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
                              prev->types_keys, &prev->types,
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -863,7 +863,7 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx
         }
 
     } else {
-        if (ngx_conf_full_name(cf->cycle, &value[1], 0) == NGX_ERROR) {
+        if (ngx_conf_full_name(cf->cycle, &value[1], 0) != NGX_OK) {
             return NGX_CONF_ERROR;
         }
 
--- a/src/http/modules/ngx_http_map_module.c
+++ b/src/http/modules/ngx_http_map_module.c
@@ -374,7 +374,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command
     if (ngx_strcmp(value[0].data, "include") == 0) {
         file = value[1];
 
-        if (ngx_conf_full_name(cf->cycle, &file, 1) == NGX_ERROR){
+        if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK){
             return NGX_CONF_ERROR;
         }
 
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -187,7 +187,7 @@ ngx_http_range_header_filter(ngx_http_re
     }
 
     if (ngx_array_init(&ctx->ranges, r->pool, 1, sizeof(ngx_http_range_t))
-        == NGX_ERROR)
+        != NGX_OK)
     {
         return NGX_ERROR;
     }
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -282,7 +282,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx
 
     ngx_int_t                rc;
     ngx_str_t               *value;
-    ngx_inet_cidr_t          in_cidr;
+    ngx_cidr_t               cidr;
     ngx_http_realip_from_t  *from;
 
     if (rlcf->from == NULL) {
@@ -300,7 +300,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx
 
     value = cf->args->elts;
 
-    rc = ngx_ptocidr(&value[1], &in_cidr);
+    rc = ngx_ptocidr(&value[1], &cidr);
 
     if (rc == NGX_ERROR) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
@@ -308,13 +308,19 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx
         return NGX_CONF_ERROR;
     }
 
+    if (cidr.family != AF_INET) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "\"realip_from\" supports IPv4 only");
+        return NGX_CONF_ERROR;
+    }
+
     if (rc == NGX_DONE) {
         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                            "low address bits of %V are meaningless", &value[1]);
     }
 
-    from->mask = in_cidr.mask;
-    from->addr = in_cidr.addr;
+    from->mask = cidr.u.in.mask;
+    from->addr = cidr.u.in.addr;
 
     return NGX_CONF_OK;
 }
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -397,7 +397,7 @@ ngx_http_ssi_body_filter(ngx_http_reques
     /* add the incoming chain to the chain ctx->in */
 
     if (in) {
-        if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) {
+        if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
             return NGX_ERROR;
         }
     }
@@ -2060,7 +2060,7 @@ ngx_http_ssi_stub_output(ngx_http_reques
     out = data;
 
     if (!r->header_sent) {
-        if (ngx_http_set_content_type(r) == NGX_ERROR) {
+        if (ngx_http_set_content_type(r) != NGX_OK) {
             return NGX_ERROR;
         }
 
--- a/src/http/modules/ngx_http_sub_filter_module.c
+++ b/src/http/modules/ngx_http_sub_filter_module.c
@@ -204,7 +204,7 @@ ngx_http_sub_body_filter(ngx_http_reques
     /* add the incoming chain to the chain ctx->in */
 
     if (in) {
-        if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) {
+        if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
             return NGX_ERROR;
         }
     }
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -360,10 +360,16 @@ static ngx_int_t
 ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
     ngx_http_userid_conf_t *conf)
 {
-    u_char           *cookie, *p;
-    size_t            len;
-    ngx_str_t         src, dst;
-    ngx_table_elt_t  *set_cookie, *p3p;
+    u_char               *cookie, *p;
+    size_t                len;
+    ngx_str_t             src, dst;
+    ngx_table_elt_t      *set_cookie, *p3p;
+    ngx_connection_t     *c;
+    struct sockaddr_in   *sin;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6  *sin6;
+#endif
+
     /*
      * TODO: in the threaded mode the sequencers should be in TLS and their
      * ranges should be divided between threads
@@ -388,7 +394,28 @@ ngx_http_userid_set_uid(ngx_http_request
                     return NGX_ERROR;
                 }
 
-                ctx->uid_set[0] = htonl(r->in_addr);
+                c = r->connection;
+
+                switch (c->local_sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+                case AF_INET6:
+                    sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
+
+                    p = (u_char *) &ctx->uid_set[0];
+
+                    *p++ = sin6->sin6_addr.s6_addr[12];
+                    *p++ = sin6->sin6_addr.s6_addr[13];
+                    *p++ = sin6->sin6_addr.s6_addr[14];
+                    *p = sin6->sin6_addr.s6_addr[15];
+
+                    break;
+#endif
+                default: /* AF_INET */
+                    sin = (struct sockaddr_in *) c->local_sockaddr;
+                    ctx->uid_set[0] = sin->sin_addr.s_addr;
+                    break;
+                }
 
             } else {
                 ctx->uid_set[0] = htonl(conf->service);
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '0.7.38';
+our $VERSION = '0.7.39';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1603,7 +1603,7 @@ ngx_http_cmp_dns_wildcards(const void *o
 static ngx_int_t
 ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
 {
-    ngx_uint_t                 i, a, last, bind_wildcard;
+    ngx_uint_t                 i, last, bind_wildcard;
     ngx_listening_t           *ls;
     ngx_http_port_t           *hport;
     ngx_http_conf_addr_t      *addr;
@@ -1626,16 +1626,16 @@ ngx_http_init_listening(ngx_conf_t *cf, 
         bind_wildcard = 0;
     }
 
-    a = 0;
-
-    while (a < last) {
-
-        if (bind_wildcard && !addr[a].bind) {
-            a++;
+    i = 0;
+
+    while (i < last) {
+
+        if (bind_wildcard && !addr[i].bind) {
+            i++;
             continue;
         }
 
-        ls = ngx_http_add_listening(cf, &addr[a]);
+        ls = ngx_http_add_listening(cf, &addr[i]);
         if (ls == NULL) {
             return NGX_ERROR;
         }
@@ -1647,23 +1647,12 @@ ngx_http_init_listening(ngx_conf_t *cf, 
 
         ls->servers = hport;
 
-        hport->port = ntohs(port->port);
-
-        for (i = ls->addr_text.len - 1; i; i--) {
-
-            if (ls->addr_text.data[i] == ':') {
-                hport->port_text.len = ls->addr_text.len - i;
-                hport->port_text.data = &ls->addr_text.data[i];
-                break;
-            }
-        }
-
-        if (a == last - 1) {
+        if (i == last - 1) {
             hport->naddrs = last;
 
         } else {
             hport->naddrs = 1;
-            a = 0;
+            i = 0;
         }
 
         switch (ls->sockaddr->sa_family) {
@@ -1823,7 +1812,7 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_h
             return NGX_ERROR;
         }
 
-        addrs[i].conf.virtual_names = vn;
+        addrs[i].conf.core_srv_conf->virtual_names = vn;
 
         vn->names.hash = addr[i].hash;
         vn->names.wc_head = addr[i].wc_head;
@@ -1880,7 +1869,7 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_
             return NGX_ERROR;
         }
 
-        addrs6[i].conf.virtual_names = vn;
+        addrs6[i].conf.core_srv_conf->virtual_names = vn;
 
         vn->names.hash = addr[i].hash;
         vn->names.wc_head = addr[i].wc_head;
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1086,12 +1086,8 @@ ngx_http_core_try_files_phase(ngx_http_r
             len = tf->name.len;
         }
 
-        reserve = len - r->uri.len;
-
         /* 16 bytes are preallocation */
-        reserve = reserve < 16 ? 16 : reserve + 16;
-
-        reserve += alias;
+        reserve = ngx_abs((ssize_t) (len - r->uri.len)) + alias + 16;
 
         if (reserve > allocated) {
 
@@ -1555,7 +1551,7 @@ ngx_http_set_content_type(ngx_http_reque
 
                 exten = ngx_pnalloc(r->pool, r->exten.len);
                 if (exten == NULL) {
-                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                    return NGX_ERROR;
                 }
 
                 hash = ngx_hash_strlow(exten, r->exten.data, r->exten.len);
@@ -1684,8 +1680,7 @@ ngx_http_map_uri_to_path(ngx_http_reques
             return NULL;
         }
 
-        if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path, 0)== NGX_ERROR)
-        {
+        if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path, 0) != NGX_OK) {
             return NULL;
         }
 
@@ -1776,7 +1771,6 @@ ngx_http_server_addr(ngx_http_request_t 
 {
     socklen_t            len;
     ngx_connection_t    *c;
-    struct sockaddr_in  *sin;
     u_char               sa[NGX_SOCKADDRLEN];
 
     c = r->connection;
@@ -1799,9 +1793,6 @@ ngx_http_server_addr(ngx_http_request_t 
         ngx_memcpy(c->local_sockaddr, &sa, len);
     }
 
-    sin = (struct sockaddr_in *) c->local_sockaddr;
-    r->in_addr = sin->sin_addr.s_addr;
-
     if (s == NULL) {
         return NGX_OK;
     }
@@ -2010,7 +2001,7 @@ ngx_http_subrequest(ngx_http_request_t *
 
     if (ngx_list_init(&sr->headers_out.headers, r->pool, 20,
                       sizeof(ngx_table_elt_t))
-        == NGX_ERROR)
+        != NGX_OK)
     {
         return NGX_ERROR;
     }
@@ -2065,10 +2056,6 @@ ngx_http_subrequest(ngx_http_request_t *
         c->data = sr;
     }
 
-    sr->in_addr = r->in_addr;
-    sr->port = r->port;
-    sr->port_text = r->port_text;
-
     sr->variables = r->variables;
 
     sr->log_handler = r->log_handler;
@@ -2602,7 +2589,7 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_c
     if (ngx_strcmp(value[0].data, "include") == 0) {
         file = value[1];
 
-        if (ngx_conf_full_name(cf->cycle, &file, 1) == NGX_ERROR){
+        if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
             return NGX_CONF_ERROR;
         }
 
@@ -2736,14 +2723,14 @@ ngx_http_core_create_srv_conf(ngx_conf_t
 
     if (ngx_array_init(&cscf->listen, cf->temp_pool, 4,
                        sizeof(ngx_http_listen_t))
-        == NGX_ERROR)
+        != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
 
     if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
                        sizeof(ngx_http_server_name_t))
-        == NGX_ERROR)
+        != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
@@ -2962,7 +2949,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
             conf->root.len = sizeof("html") - 1;
             conf->root.data = (u_char *) "html";
 
-            if (ngx_conf_full_name(cf->cycle, &conf->root, 0) == NGX_ERROR) {
+            if (ngx_conf_full_name(cf->cycle, &conf->root, 0) != NGX_OK) {
                 return NGX_CONF_ERROR;
             }
         }
@@ -3534,7 +3521,7 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_c
     }
 
     if (lcf->root.data[0] != '$') {
-        if (ngx_conf_full_name(cf->cycle, &lcf->root, 0) == NGX_ERROR) {
+        if (ngx_conf_full_name(cf->cycle, &lcf->root, 0) != NGX_OK) {
             return NGX_CONF_ERROR;
         }
     }
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -150,6 +150,8 @@ typedef struct {
     /* server ctx */
     ngx_http_conf_ctx_t        *ctx;
 
+    ngx_http_virtual_names_t   *virtual_names;
+
     ngx_str_t                   server_name;
 
     size_t                      connection_pool_size;
@@ -175,8 +177,6 @@ typedef struct {
     /* the default server configuration for this address:port */
     ngx_http_core_srv_conf_t  *core_srv_conf;
 
-    ngx_http_virtual_names_t  *virtual_names;
-
 #if (NGX_HTTP_SSL)
     ngx_uint_t                 ssl;   /* unsigned  ssl:1; */
 #endif
@@ -200,9 +200,6 @@ typedef struct {
 
 
 typedef struct {
-    in_port_t                  port;
-    ngx_str_t                  port_text;
-
     /* ngx_http_in_addr_t or ngx_http_in6_addr_t */
     void                      *addrs;
     ngx_uint_t                 naddrs;
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -155,12 +155,16 @@ ngx_http_header_filter(ngx_http_request_
     size_t                     len;
     ngx_str_t                  host;
     ngx_buf_t                 *b;
-    ngx_uint_t                 status, i;
+    ngx_uint_t                 status, i, port;
     ngx_chain_t                out;
     ngx_list_part_t           *part;
     ngx_table_elt_t           *header;
     ngx_http_core_loc_conf_t  *clcf;
     ngx_http_core_srv_conf_t  *cscf;
+    struct sockaddr_in        *sin;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6       *sin6;
+#endif
     u_char                     addr[NGX_SOCKADDR_STRLEN];
 
     r->header_sent = 1;
@@ -297,31 +301,42 @@ ngx_http_header_filter(ngx_http_request_
             }
         }
 
-#if (NGX_HTTP_SSL)
-        if (r->connection->ssl) {
-            len += sizeof("Location: https://") - 1
-                   + host.len
-                   + r->headers_out.location->value.len + 2;
+        switch (r->connection->local_sockaddr->sa_family) {
 
-            if (clcf->port_in_redirect && r->port != 443) {
-                len += r->port_text->len;
-            }
+#if (NGX_HAVE_INET6)
+        case AF_INET6:
+            sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr;
+            port = ntohs(sin6->sin6_port);
+            break;
+#endif
+        default: /* AF_INET */
+            sin = (struct sockaddr_in *) r->connection->local_sockaddr;
+            port = ntohs(sin->sin_port);
+            break;
+        }
 
-        } else
+        len += sizeof("Location: https://") - 1
+               + host.len
+               + r->headers_out.location->value.len + 2;
+
+        if (clcf->port_in_redirect) {
+
+#if (NGX_HTTP_SSL)
+	    if (r->connection->ssl)
+		port = (port == 443) ? 0 : port;
+	    else
 #endif
-        {
-            len += sizeof("Location: http://") - 1
-                   + host.len
-                   + r->headers_out.location->value.len + 2;
+		port = (port == 80) ? 0 : port;
+	}
 
-            if (clcf->port_in_redirect && r->port != 80) {
-                len += r->port_text->len;
-            }
+        if (port) {
+            len += sizeof(":65535") - 1;
         }
 
     } else {
         host.len = 0;
         host.data = NULL;
+        port = 0;
     }
 
     if (r->chunked) {
@@ -473,21 +488,8 @@ ngx_http_header_filter(ngx_http_request_
         *b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/';
         b->last = ngx_copy(b->last, host.data, host.len);
 
-        if (clcf->port_in_redirect) {
-#if (NGX_HTTP_SSL)
-            if (r->connection->ssl) {
-                if (r->port != 443) {
-                    b->last = ngx_copy(b->last, r->port_text->data,
-                                       r->port_text->len);
-                }
-            } else
-#endif
-            {
-                if (r->port != 80) {
-                    b->last = ngx_copy(b->last, r->port_text->data,
-                                       r->port_text->len);
-                }
-            }
+        if (port) {
+            b->last = ngx_sprintf(b->last, ":%ui", port);
         }
 
         b->last = ngx_copy(b->last, r->headers_out.location->value.data,
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -300,9 +300,6 @@ ngx_http_init_request(ngx_event_t *rev)
 
     port = c->listening->servers;
 
-    r->port = port->port;
-    r->port_text = &port->port_text;
-
     r->connection = c;
 
     if (port->naddrs > 1) {
@@ -373,13 +370,10 @@ ngx_http_init_request(ngx_event_t *rev)
         default: /* AF_INET */
             addr = port->addrs;
             addr_conf = &addr[0].conf;
-            r->in_addr = addr[0].addr;
             break;
         }
     }
 
-    r->virtual_names = addr_conf->virtual_names;
-
     /* the default server configuration for the address:port */
     cscf = addr_conf->core_srv_conf;
 
@@ -410,7 +404,7 @@ ngx_http_init_request(ngx_event_t *rev)
             }
 
             if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
-                == NGX_ERROR)
+                != NGX_OK)
             {
                 ngx_http_close_connection(c);
                 return;
@@ -453,7 +447,7 @@ ngx_http_init_request(ngx_event_t *rev)
 
     if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
                       sizeof(ngx_table_elt_t))
-        == NGX_ERROR)
+        != NGX_OK)
     {
         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
@@ -813,7 +807,7 @@ ngx_http_process_request_line(ngx_event_
 
             if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
                               sizeof(ngx_table_elt_t))
-                == NGX_ERROR)
+                != NGX_OK)
             {
                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return;
@@ -822,7 +816,7 @@ ngx_http_process_request_line(ngx_event_
 
             if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
                                sizeof(ngx_table_elt_t *))
-                == NGX_ERROR)
+                != NGX_OK)
             {
                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return;
@@ -1618,11 +1612,15 @@ ngx_http_find_virtual_server(ngx_http_re
 {
     u_char                    *server;
     ngx_uint_t                 hash;
+    ngx_http_virtual_names_t  *vn;
     ngx_http_core_loc_conf_t  *clcf;
     ngx_http_core_srv_conf_t  *cscf;
     u_char                     buf[32];
 
-    if (r->virtual_names == NULL) {
+    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
+    vn = cscf->virtual_names;
+
+    if (vn == NULL) {
         return NGX_DECLINED;
     }
 
@@ -1638,7 +1636,7 @@ ngx_http_find_virtual_server(ngx_http_re
 
     hash = ngx_hash_strlow(server, host, len);
 
-    cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, server, len);
+    cscf = ngx_hash_find_combined(&vn->names, hash, server, len);
 
     if (cscf) {
         goto found;
@@ -1646,7 +1644,7 @@ ngx_http_find_virtual_server(ngx_http_re
 
 #if (NGX_PCRE)
 
-    if (r->virtual_names->nregex) {
+    if (vn->nregex) {
         ngx_int_t                n;
         ngx_uint_t               i;
         ngx_str_t                name;
@@ -1655,9 +1653,9 @@ ngx_http_find_virtual_server(ngx_http_re
         name.len = len;
         name.data = server;
 
-        sn = r->virtual_names->regex;
-
-        for (i = 0; i < r->virtual_names->nregex; i++) {
+        sn = vn->regex;
+
+        for (i = 0; i < vn->nregex; i++) {
 
             n = ngx_regex_exec(sn[i].regex, &name, NULL, 0);
 
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -384,11 +384,6 @@ struct ngx_http_request_s {
     ngx_http_post_subrequest_t       *post_subrequest;
     ngx_http_posted_request_t        *posted_requests;
 
-    uint32_t                          in_addr;
-    ngx_uint_t                        port;
-    ngx_str_t                        *port_text;    /* ":80" */
-    ngx_http_virtual_names_t         *virtual_names;
-
     ngx_int_t                         phase_handler;
     ngx_http_handler_pt               content_handler;
     ngx_uint_t                        access_code;
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -860,7 +860,7 @@ ngx_http_upstream_ssl_init_connection(ng
 
     if (ngx_ssl_create_connection(u->conf->ssl, c,
                                   NGX_SSL_BUFFER|NGX_SSL_CLIENT)
-        == NGX_ERROR)
+        != NGX_OK)
     {
         ngx_http_upstream_finalize_request(r, u,
                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -332,7 +332,8 @@ ngx_http_get_variable_index(ngx_conf_t *
 
     if (v == NULL) {
         if (ngx_array_init(&cmcf->variables, cf->pool, 4,
-                           sizeof(ngx_http_variable_t)) == NGX_ERROR)
+                           sizeof(ngx_http_variable_t))
+            != NGX_OK)
         {
             return NGX_ERROR;
         }
@@ -956,11 +957,44 @@ static ngx_int_t
 ngx_http_variable_server_port(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
-    v->len = r->port_text->len - 1;
+    ngx_uint_t            port;
+    struct sockaddr_in   *sin;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6  *sin6;
+#endif
+
+    v->len = 0;
     v->valid = 1;
     v->no_cacheable = 0;
     v->not_found = 0;
-    v->data = r->port_text->data + 1;
+
+    if (ngx_http_server_addr(r, NULL) != NGX_OK) {
+        return NGX_ERROR;
+    }
+
+    v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
+    if (v->data == NULL) {
+        return NGX_ERROR;
+    }
+
+    switch (r->connection->local_sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr;
+        port = ntohs(sin6->sin6_port);
+        break;
+#endif
+
+    default: /* AF_INET */
+        sin = (struct sockaddr_in *) r->connection->local_sockaddr;
+        port = ntohs(sin->sin_port);
+        break;
+    }
+
+    if (port > 0 && port < 65536) {
+        v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
+    }
 
     return NGX_OK;
 }
@@ -1039,9 +1073,7 @@ ngx_http_variable_document_root(ngx_http
             return NGX_ERROR;
         }
 
-        if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0)
-            == NGX_ERROR)
-        {
+        if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
             return NGX_ERROR;
         }
 
@@ -1080,9 +1112,7 @@ ngx_http_variable_realpath_root(ngx_http
 
         path.data[path.len - 1] = '\0';
 
-        if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0)
-            == NGX_ERROR)
-        {
+        if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
             return NGX_ERROR;
         }
     }
@@ -1286,6 +1316,8 @@ static ngx_int_t
 ngx_http_variable_sent_location(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
+    ngx_str_t  name;
+
     if (r->headers_out.location) {
         v->len = r->headers_out.location->value.len;
         v->valid = 1;
@@ -1296,7 +1328,10 @@ ngx_http_variable_sent_location(ngx_http
         return NGX_OK;
     }
 
-    return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
+    name.len = sizeof("sent_http_location") - 1;
+    name.data = (u_char *) "sent_http_location";
+
+    return ngx_http_variable_unknown_header(v, &name,
                                             &r->headers_out.headers.part,
                                             sizeof("sent_http_") - 1);
 }