# HG changeset patch # User Igor Sysoev # Date 1235941200 -10800 # Node ID a8424ffa495cf3a21769c567df89bef2a9c0c3fd # Parent 9ef0e36f3cd554b070d6ca33633b0919eaa5f395 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. diff --git a/CHANGES b/CHANGES --- 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. diff --git a/CHANGES.ru b/CHANGES.ru --- 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 *) Добавление: логгирование ошибок аутентификации. diff --git a/src/core/nginx.c b/src/core/nginx.c --- 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; } diff --git a/src/core/nginx.h b/src/core/nginx.h --- 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" diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c --- 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; } diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- 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; diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c --- 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; } diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- 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; } diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h --- 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); diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c --- 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; } diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- 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; } diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c --- 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 diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- 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; } diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c --- 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; } diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c --- 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; } diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c --- 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"); diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c --- 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, diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c --- 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; } diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c --- 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; } diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c --- 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; } diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c --- 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; } diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c --- 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; } diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c --- 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; } } diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c --- 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); diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- 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); diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c --- 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; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- 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; } } diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- 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; diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c --- 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, diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- 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); diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- 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; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- 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); diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- 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); }