summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornginx <nginx@nginx.org>2013-03-05 14:54:11 +0000
committerJon Kolb <jon@b0g.us>2013-03-05 14:54:11 +0000
commit72050c25110c60a640ed602b5a99dc3513adf8c2 (patch)
tree03cd2bf0cc618bf496095e1bcd8713592b4b4344
parenta36b88c56061d08f8fbe96a51489bf3381792aca (diff)
downloadnginx-72050c25110c60a640ed602b5a99dc3513adf8c2.tar.gz
Changes with nginx 1.3.14 05 Mar 2013v1.3.14
*) Feature: $connections_active, $connections_reading, and $connections_writing variables in the ngx_http_stub_status_module. *) Feature: support of WebSocket connections in the ngx_http_uwsgi_module and ngx_http_scgi_module. *) Bugfix: in virtual servers handling with SNI. *) Bugfix: new sessions were not always stored if the "ssl_session_cache shared" directive was used and there was no free space in shared memory. Thanks to Piotr Sikora. *) Bugfix: multiple X-Forwarded-For headers were handled incorrectly. Thanks to Neal Poole for sponsoring this work. *) Bugfix: in the ngx_http_mp4_module. Thanks to Gernot Vormayr.
-rw-r--r--CHANGES22
-rw-r--r--CHANGES.ru23
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/event/ngx_event_openssl.c24
-rw-r--r--src/http/modules/ngx_http_geo_module.c11
-rw-r--r--src/http/modules/ngx_http_geoip_module.c22
-rw-r--r--src/http/modules/ngx_http_mp4_module.c7
-rw-r--r--src/http/modules/ngx_http_proxy_module.c30
-rw-r--r--src/http/modules/ngx_http_realip_module.c25
-rw-r--r--src/http/modules/ngx_http_scgi_module.c10
-rw-r--r--src/http/modules/ngx_http_ssl_module.c1
-rw-r--r--src/http/modules/ngx_http_stub_status_module.c81
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c10
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http.h2
-rw-r--r--src/http/ngx_http_core_module.c68
-rw-r--r--src/http/ngx_http_core_module.h31
-rw-r--r--src/http/ngx_http_file_cache.c2
-rw-r--r--src/http/ngx_http_request.c788
-rw-r--r--src/http/ngx_http_request.h39
-rw-r--r--src/http/ngx_http_variables.c39
21 files changed, 813 insertions, 428 deletions
diff --git a/CHANGES b/CHANGES
index eb5377e74..2569ccc8a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,26 @@
+Changes with nginx 1.3.14 05 Mar 2013
+
+ *) Feature: $connections_active, $connections_reading, and
+ $connections_writing variables in the ngx_http_stub_status_module.
+
+ *) Feature: support of WebSocket connections in the
+ ngx_http_uwsgi_module and ngx_http_scgi_module.
+
+ *) Bugfix: in virtual servers handling with SNI.
+
+ *) Bugfix: new sessions were not always stored if the "ssl_session_cache
+ shared" directive was used and there was no free space in shared
+ memory.
+ Thanks to Piotr Sikora.
+
+ *) Bugfix: multiple X-Forwarded-For headers were handled incorrectly.
+ Thanks to Neal Poole for sponsoring this work.
+
+ *) Bugfix: in the ngx_http_mp4_module.
+ Thanks to Gernot Vormayr.
+
+
Changes with nginx 1.3.13 19 Feb 2013
*) Change: a compiler with name "cc" is now used by default.
diff --git a/CHANGES.ru b/CHANGES.ru
index 1d1a3a025..bdf457834 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,27 @@
+Изменения в nginx 1.3.14 05.03.2013
+
+ *) Добавление: переменные $connections_active, $connections_reading и
+ $connections_writing в модуле ngx_http_stub_status_module.
+
+ *) Добавление: поддержка WebSocket-соединений в модулях
+ ngx_http_uwsgi_module и ngx_http_scgi_module.
+
+ *) Исправление: в обработке виртуальных серверов при использовании SNI.
+
+ *) Исправление: при использовании директивы "ssl_session_cache shared"
+ новые сессии могли не сохраняться, если заканчивалось место в
+ разделяемой памяти.
+ Спасибо Piotr Sikora.
+
+ *) Исправление: несколько заголовков X-Forwarded-For обрабатывались
+ неправильно.
+ Спасибо Neal Poole за спонсирование разработки.
+
+ *) Исправление: в модуле ngx_http_mp4_module.
+ Спасибо Gernot Vormayr.
+
+
Изменения в nginx 1.3.13 19.02.2013
*) Изменение: теперь для сборки по умолчанию используется компилятор с
diff --git a/src/core/nginx.h b/src/core/nginx.h
index f522433e2..f0f3808f1 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1003013
-#define NGINX_VERSION "1.3.13"
+#define nginx_version 1003014
+#define NGINX_VERSION "1.3.14"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index b8f1cae91..62ce12c14 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -1842,8 +1842,18 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
}
sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
+
if (sess_id == NULL) {
- goto failed;
+
+ /* drop the oldest non-expired session and try once more */
+
+ ngx_ssl_expire_sessions(cache, shpool, 0);
+
+ sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
+
+ if (sess_id == NULL) {
+ goto failed;
+ }
}
#if (NGX_PTR_SIZE == 8)
@@ -1853,8 +1863,18 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
#else
id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
+
if (id == NULL) {
- goto failed;
+
+ /* drop the oldest non-expired session and try once more */
+
+ ngx_ssl_expire_sessions(cache, shpool, 0);
+
+ id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
+
+ if (id == NULL) {
+ goto failed;
+ }
}
#endif
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index a927ab798..725baa211 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -314,18 +314,17 @@ static ngx_int_t
ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
ngx_addr_t *addr)
{
- ngx_table_elt_t *xfwd;
+ ngx_array_t *xfwd;
if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) {
return NGX_ERROR;
}
- xfwd = r->headers_in.x_forwarded_for;
+ xfwd = &r->headers_in.x_forwarded_for;
- if (xfwd != NULL && ctx->proxies != NULL) {
- (void) ngx_http_get_forwarded_addr(r, addr, xfwd->value.data,
- xfwd->value.len, ctx->proxies,
- ctx->proxy_recursive);
+ if (xfwd->nelts > 0 && ctx->proxies != NULL) {
+ (void) ngx_http_get_forwarded_addr(r, addr, xfwd, NULL,
+ ctx->proxies, ctx->proxy_recursive);
}
return NGX_OK;
diff --git a/src/http/modules/ngx_http_geoip_module.c b/src/http/modules/ngx_http_geoip_module.c
index 364106519..576fc5f3c 100644
--- a/src/http/modules/ngx_http_geoip_module.c
+++ b/src/http/modules/ngx_http_geoip_module.c
@@ -240,19 +240,18 @@ static u_long
ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
{
ngx_addr_t addr;
- ngx_table_elt_t *xfwd;
+ ngx_array_t *xfwd;
struct sockaddr_in *sin;
addr.sockaddr = r->connection->sockaddr;
addr.socklen = r->connection->socklen;
/* addr.name = r->connection->addr_text; */
- xfwd = r->headers_in.x_forwarded_for;
+ xfwd = &r->headers_in.x_forwarded_for;
- if (xfwd != NULL && gcf->proxies != NULL) {
- (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
- xfwd->value.len, gcf->proxies,
- gcf->proxy_recursive);
+ if (xfwd->nelts > 0 && gcf->proxies != NULL) {
+ (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
+ gcf->proxies, gcf->proxy_recursive);
}
#if (NGX_HAVE_INET6)
@@ -293,7 +292,7 @@ static geoipv6_t
ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
{
ngx_addr_t addr;
- ngx_table_elt_t *xfwd;
+ ngx_array_t *xfwd;
in_addr_t addr4;
struct in6_addr addr6;
struct sockaddr_in *sin;
@@ -303,12 +302,11 @@ ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
addr.socklen = r->connection->socklen;
/* addr.name = r->connection->addr_text; */
- xfwd = r->headers_in.x_forwarded_for;
+ xfwd = &r->headers_in.x_forwarded_for;
- if (xfwd != NULL && gcf->proxies != NULL) {
- (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
- xfwd->value.len, gcf->proxies,
- gcf->proxy_recursive);
+ if (xfwd->nelts > 0 && gcf->proxies != NULL) {
+ (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
+ gcf->proxies, gcf->proxy_recursive);
}
switch (addr.sockaddr->sa_family) {
diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c
index b864858ea..20ef51af2 100644
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -754,6 +754,13 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
*prev = &mp4->mdat_atom;
+ if (start_offset > mp4->mdat_data.buf->file_last) {
+ ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
+ "start time is out mp4 mdat atom in \"%s\"",
+ mp4->file.name.data);
+ return NGX_ERROR;
+ }
+
adjustment = mp4->ftyp_size + mp4->moov_size
+ ngx_http_mp4_update_mdat_atom(mp4, start_offset)
- start_offset;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index a623adc34..eadc8c480 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -2014,32 +2014,44 @@ static ngx_int_t
ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
- u_char *p;
+ size_t len;
+ u_char *p;
+ ngx_uint_t i, n;
+ ngx_table_elt_t **h;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
- if (r->headers_in.x_forwarded_for == NULL) {
+ n = r->headers_in.x_forwarded_for.nelts;
+ h = r->headers_in.x_forwarded_for.elts;
+
+ len = 0;
+
+ for (i = 0; i < n; i++) {
+ len += h[i]->value.len + sizeof(", ") - 1;
+ }
+
+ if (len == 0) {
v->len = r->connection->addr_text.len;
v->data = r->connection->addr_text.data;
return NGX_OK;
}
- v->len = r->headers_in.x_forwarded_for->value.len
- + sizeof(", ") - 1 + r->connection->addr_text.len;
+ len += r->connection->addr_text.len;
- p = ngx_pnalloc(r->pool, v->len);
+ p = ngx_pnalloc(r->pool, len);
if (p == NULL) {
return NGX_ERROR;
}
+ v->len = len;
v->data = p;
- p = ngx_copy(p, r->headers_in.x_forwarded_for->value.data,
- r->headers_in.x_forwarded_for->value.len);
-
- *p++ = ','; *p++ = ' ';
+ for (i = 0; i < n; i++) {
+ p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
+ *p++ = ','; *p++ = ' ';
+ }
ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c
index 4531ea51c..ed9c5f9e8 100644
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -107,10 +107,12 @@ ngx_module_t ngx_http_realip_module = {
static ngx_int_t
ngx_http_realip_handler(ngx_http_request_t *r)
{
- u_char *ip, *p;
+ u_char *p;
size_t len;
+ ngx_str_t *value;
ngx_uint_t i, hash;
ngx_addr_t addr;
+ ngx_array_t *xfwd;
ngx_list_part_t *part;
ngx_table_elt_t *header;
ngx_connection_t *c;
@@ -137,19 +139,20 @@ ngx_http_realip_handler(ngx_http_request_t *r)
return NGX_DECLINED;
}
- len = r->headers_in.x_real_ip->value.len;
- ip = r->headers_in.x_real_ip->value.data;
+ value = &r->headers_in.x_real_ip->value;
+ xfwd = NULL;
break;
case NGX_HTTP_REALIP_XFWD:
- if (r->headers_in.x_forwarded_for == NULL) {
+ xfwd = &r->headers_in.x_forwarded_for;
+
+ if (xfwd->elts == NULL) {
return NGX_DECLINED;
}
- len = r->headers_in.x_forwarded_for->value.len;
- ip = r->headers_in.x_forwarded_for->value.data;
+ value = NULL;
break;
@@ -178,8 +181,8 @@ ngx_http_realip_handler(ngx_http_request_t *r)
&& len == header[i].key.len
&& ngx_strncmp(p, header[i].lowcase_key, len) == 0)
{
- len = header[i].value.len;
- ip = header[i].value.data;
+ value = &header[i].value;
+ xfwd = NULL;
goto found;
}
@@ -192,15 +195,13 @@ found:
c = r->connection;
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "realip: \"%s\"", ip);
-
addr.sockaddr = c->sockaddr;
addr.socklen = c->socklen;
/* addr.name = c->addr_text; */
- if (ngx_http_get_forwarded_addr(r, &addr, ip, len, rlcf->from,
+ if (ngx_http_get_forwarded_addr(r, &addr, xfwd, value, rlcf->from,
rlcf->recursive)
- == NGX_OK)
+ != NGX_DECLINED)
{
return ngx_http_realip_set_addr(r, &addr);
}
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index c87b44b53..49cc96d24 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -984,7 +984,7 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
u = r->upstream;
if (u->headers_in.status_n) {
- return NGX_OK;
+ goto done;
}
if (u->headers_in.status) {
@@ -1015,6 +1015,14 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
u->state->status = u->headers_in.status_n;
}
+ done:
+
+ if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS
+ && r->headers_in.upgrade)
+ {
+ u->upgrade = 1;
+ }
+
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index 62882838d..2fc4ad47c 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -661,7 +661,6 @@ ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
if (value[i].data[j] == ':') {
- value[i].data[j] = '\0';
break;
}
diff --git a/src/http/modules/ngx_http_stub_status_module.c b/src/http/modules/ngx_http_stub_status_module.c
index 96abe928a..e2ac94928 100644
--- a/src/http/modules/ngx_http_stub_status_module.c
+++ b/src/http/modules/ngx_http_stub_status_module.c
@@ -10,6 +10,10 @@
#include <ngx_http.h>
+static ngx_int_t ngx_http_stub_status_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_stub_status_add_variables(ngx_conf_t *cf);
+
static char *ngx_http_set_status(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -28,7 +32,7 @@ static ngx_command_t ngx_http_status_commands[] = {
static ngx_http_module_t ngx_http_stub_status_module_ctx = {
- NULL, /* preconfiguration */
+ ngx_http_stub_status_add_variables, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
@@ -58,6 +62,21 @@ ngx_module_t ngx_http_stub_status_module = {
};
+static ngx_http_variable_t ngx_http_stub_status_vars[] = {
+
+ { ngx_string("connections_active"), NULL, ngx_http_stub_status_variable,
+ 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
+ { ngx_string("connections_reading"), NULL, ngx_http_stub_status_variable,
+ 1, NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
+ { ngx_string("connections_writing"), NULL, ngx_http_stub_status_variable,
+ 2, NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
+ { ngx_null_string, NULL, NULL, 0, 0, 0 }
+};
+
+
static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r)
{
size_t size;
@@ -133,6 +152,66 @@ static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r)
}
+static ngx_int_t
+ngx_http_stub_status_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ u_char *p;
+ ngx_atomic_int_t value;
+
+ p = ngx_pnalloc(r->pool, NGX_ATOMIC_T_LEN);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ switch (data) {
+ case 0:
+ value = *ngx_stat_active;
+ break;
+
+ case 1:
+ value = *ngx_stat_reading;
+ break;
+
+ case 2:
+ value = *ngx_stat_writing;
+ break;
+
+ /* suppress warning */
+ default:
+ value = 0;
+ break;
+ }
+
+ v->len = ngx_sprintf(p, "%uA", value) - p;
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->data = p;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_stub_status_add_variables(ngx_conf_t *cf)
+{
+ ngx_http_variable_t *var, *v;
+
+ for (v = ngx_http_stub_status_vars; v->name.len; v++) {
+ var = ngx_http_add_variable(cf, &v->name, v->flags);
+ if (var == NULL) {
+ return NGX_ERROR;
+ }
+
+ var->get_handler = v->get_handler;
+ var->data = v->data;
+ }
+
+ return NGX_OK;
+}
+
+
static char *ngx_http_set_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index c683df0be..623ee4957 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -1018,7 +1018,7 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r)
u = r->upstream;
if (u->headers_in.status_n) {
- return NGX_OK;
+ goto done;
}
if (u->headers_in.status) {
@@ -1049,6 +1049,14 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r)
u->state->status = u->headers_in.status_n;
}
+ done:
+
+ if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS
+ && r->headers_in.upgrade)
+ {
+ u->upgrade = 1;
+ }
+
return NGX_OK;
}
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 353cadb9d..4adb2de9f 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -50,7 +50,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '1.3.13';
+our $VERSION = '1.3.14';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index f974081ea..bf70c16a8 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -27,11 +27,11 @@ typedef u_char *(*ngx_http_log_handler_pt)(ngx_http_request_t *r,
#include <ngx_http_variables.h>
+#include <ngx_http_config.h>
#include <ngx_http_request.h>
#include <ngx_http_script.h>
#include <ngx_http_upstream.h>
#include <ngx_http_upstream_round_robin.h>
-#include <ngx_http_config.h>
#include <ngx_http_busy_lock.h>
#include <ngx_http_core_module.h>
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 27f082ee7..c4914997b 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -76,6 +76,9 @@ static ngx_uint_t ngx_http_gzip_quantity(u_char *p, u_char *last);
static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#endif
+static ngx_int_t ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r,
+ ngx_addr_t *addr, u_char *xff, size_t xfflen, ngx_array_t *proxies,
+ int recursive);
#if (NGX_HAVE_OPENAT)
static char *ngx_http_disable_symlinks(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -1458,11 +1461,7 @@ ngx_http_update_location_config(ngx_http_request_t *r)
}
if (r == r->main) {
- r->connection->log->file = clcf->error_log->file;
-
- if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
- r->connection->log->log_level = clcf->error_log->log_level;
- }
+ ngx_http_set_connection_log(r->connection, clcf->error_log);
}
if ((ngx_io.flags & NGX_IO_SENDFILE) && clcf->sendfile) {
@@ -2747,10 +2746,58 @@ ngx_http_set_disable_symlinks(ngx_http_request_t *r,
ngx_int_t
ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
+ ngx_array_t *headers, ngx_str_t *value, ngx_array_t *proxies,
+ int recursive)
+{
+ ngx_int_t rc;
+ ngx_uint_t i, found;
+ ngx_table_elt_t **h;
+
+ if (headers == NULL) {
+ return ngx_http_get_forwarded_addr_internal(r, addr, value->data,
+ value->len, proxies,
+ recursive);
+ }
+
+ i = headers->nelts;
+ h = headers->elts;
+
+ rc = NGX_DECLINED;
+
+ found = 0;
+
+ while (i-- > 0) {
+ rc = ngx_http_get_forwarded_addr_internal(r, addr, h[i]->value.data,
+ h[i]->value.len, proxies,
+ recursive);
+
+ if (!recursive) {
+ break;
+ }
+
+ if (rc == NGX_DECLINED && found) {
+ rc = NGX_DONE;
+ break;
+ }
+
+ if (rc != NGX_OK) {
+ break;
+ }
+
+ found = 1;
+ }
+
+ return rc;
+}
+
+
+static ngx_int_t
+ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr,
u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive)
{
u_char *p;
in_addr_t inaddr;
+ ngx_int_t rc;
ngx_addr_t paddr;
ngx_cidr_t *cidr;
ngx_uint_t family, i;
@@ -2842,8 +2889,15 @@ ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
*addr = paddr;
if (recursive && p > xff) {
- (void) ngx_http_get_forwarded_addr(r, addr, xff, p - 1 - xff,
- proxies, 1);
+ rc = ngx_http_get_forwarded_addr_internal(r, addr, xff, p - 1 - xff,
+ proxies, 1);
+
+ if (rc == NGX_DECLINED) {
+ return NGX_DONE;
+ }
+
+ /* rc == NGX_OK || rc == NGX_DONE */
+ return rc;
}
return NGX_OK;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index ff1c2dfa0..921ebbcaa 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -209,6 +209,23 @@ typedef struct {
typedef struct {
+#if (NGX_PCRE)
+ ngx_http_regex_t *regex;
+#endif
+ ngx_http_core_srv_conf_t *server; /* virtual name server conf */
+ ngx_str_t name;
+} ngx_http_server_name_t;
+
+
+typedef struct {
+ ngx_hash_combined_t names;
+
+ ngx_uint_t nregex;
+ ngx_http_server_name_t *regex;
+} ngx_http_virtual_names_t;
+
+
+struct ngx_http_addr_conf_s {
/* the default server configuration for this address:port */
ngx_http_core_srv_conf_t *default_server;
@@ -217,7 +234,7 @@ typedef struct {
#if (NGX_HTTP_SSL)
ngx_uint_t ssl; /* unsigned ssl:1; */
#endif
-} ngx_http_addr_conf_t;
+};
typedef struct {
@@ -268,15 +285,6 @@ typedef struct {
} ngx_http_conf_addr_t;
-struct ngx_http_server_name_s {
-#if (NGX_PCRE)
- ngx_http_regex_t *regex;
-#endif
- ngx_http_core_srv_conf_t *server; /* virtual name server conf */
- ngx_str_t name;
-};
-
-
typedef struct {
ngx_int_t status;
ngx_int_t overwrite;
@@ -516,7 +524,8 @@ ngx_int_t ngx_http_set_disable_symlinks(ngx_http_request_t *r,
ngx_http_core_loc_conf_t *clcf, ngx_str_t *path, ngx_open_file_info_t *of);
ngx_int_t ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
- u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive);
+ ngx_array_t *headers, ngx_str_t *value, ngx_array_t *proxies,
+ int recursive);
extern ngx_module_t ngx_http_core_module;
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
index bd6cebadd..6d94c5034 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -1674,8 +1674,6 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
p = (u_char *) ngx_strchr(name.data, ':');
if (p) {
- *p = '\0';
-
name.len = p - name.data;
p++;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 763e7bf11..54e1c262e 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -21,21 +21,24 @@ static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_process_multi_header_lines(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_process_host(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
-static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r,
- ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
static void ngx_http_process_request(ngx_http_request_t *r);
-static ssize_t ngx_http_validate_host(ngx_http_request_t *r, u_char **host,
- size_t len, ngx_uint_t alloc);
-static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r,
- u_char *host, size_t len);
+static ngx_int_t ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool,
+ ngx_uint_t alloc);
+static ngx_int_t ngx_http_set_virtual_server(ngx_http_request_t *r,
+ ngx_str_t *host);
+static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c,
+ ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
+ ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp);
static void ngx_http_request_handler(ngx_event_t *ev);
static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc);
@@ -153,7 +156,7 @@ ngx_http_header_t ngx_http_headers_in[] = {
#if (NGX_HTTP_X_FORWARDED_FOR)
{ ngx_string("X-Forwarded-For"),
offsetof(ngx_http_headers_in_t, x_forwarded_for),
- ngx_http_process_header_line },
+ ngx_http_process_multi_header_lines },
#endif
#if (NGX_HTTP_REALIP)
@@ -185,7 +188,8 @@ ngx_http_header_t ngx_http_headers_in[] = {
ngx_http_process_header_line },
#endif
- { ngx_string("Cookie"), 0, ngx_http_process_cookie },
+ { ngx_string("Cookie"), offsetof(ngx_http_headers_in_t, cookies),
+ ngx_http_process_multi_header_lines },
{ ngx_null_string, 0, NULL }
};
@@ -194,137 +198,30 @@ ngx_http_header_t ngx_http_headers_in[] = {
void
ngx_http_init_connection(ngx_connection_t *c)
{
- ngx_event_t *rev;
- ngx_http_log_ctx_t *ctx;
-
- ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
- if (ctx == NULL) {
- ngx_http_close_connection(c);
- return;
- }
-
- ctx->connection = c;
- ctx->request = NULL;
- ctx->current_request = NULL;
-
- c->log->connection = c->number;
- c->log->handler = ngx_http_log_error;
- c->log->data = ctx;
- c->log->action = "reading client request line";
-
- c->log_error = NGX_ERROR_INFO;
-
- rev = c->read;
- rev->handler = ngx_http_init_request;
- c->write->handler = ngx_http_empty_handler;
-
-#if (NGX_STAT_STUB)
- (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
-#endif
-
- if (rev->ready) {
- /* the deferred accept(), rtsig, aio, iocp */
-
- if (ngx_use_accept_mutex) {
- ngx_post_event(rev, &ngx_posted_events);
- return;
- }
-
- ngx_http_init_request(rev);
- return;
- }
-
- ngx_add_timer(rev, c->listening->post_accept_timeout);
-
- if (ngx_handle_read_event(rev, 0) != NGX_OK) {
-#if (NGX_STAT_STUB)
- (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
-#endif
- ngx_http_close_connection(c);
- return;
- }
-}
-
-
-static void
-ngx_http_init_request(ngx_event_t *rev)
-{
- ngx_time_t *tp;
- ngx_uint_t i;
- ngx_connection_t *c;
- ngx_http_request_t *r;
- struct sockaddr_in *sin;
- ngx_http_port_t *port;
- ngx_http_in_addr_t *addr;
- ngx_http_log_ctx_t *ctx;
- ngx_http_addr_conf_t *addr_conf;
- ngx_http_connection_t *hc;
- ngx_http_core_srv_conf_t *cscf;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_core_main_conf_t *cmcf;
+ ngx_uint_t i;
+ ngx_event_t *rev;
+ struct sockaddr_in *sin;
+ ngx_http_port_t *port;
+ ngx_http_in_addr_t *addr;
+ ngx_http_log_ctx_t *ctx;
+ ngx_http_connection_t *hc;
#if (NGX_HAVE_INET6)
- struct sockaddr_in6 *sin6;
- ngx_http_in6_addr_t *addr6;
+ struct sockaddr_in6 *sin6;
+ ngx_http_in6_addr_t *addr6;
#endif
-#if (NGX_STAT_STUB)
- (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
-#endif
-
- c = rev->data;
-
- if (rev->timedout) {
- ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
-
+ hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
+ if (hc == NULL) {
ngx_http_close_connection(c);
return;
}
- c->requests++;
-
- hc = c->data;
-
- if (hc == NULL) {
- hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
- if (hc == NULL) {
- ngx_http_close_connection(c);
- return;
- }
- }
-
- r = hc->request;
-
- if (r) {
- ngx_memzero(r, sizeof(ngx_http_request_t));
-
- r->pipeline = hc->pipeline;
-
- if (hc->nbusy) {
- r->header_in = hc->busy[0];
- }
-
- } else {
- r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
- if (r == NULL) {
- ngx_http_close_connection(c);
- return;
- }
-
- hc->request = r;
- }
-
- c->data = r;
- r->http_connection = hc;
-
- c->sent = 0;
- r->signature = NGX_HTTP_MODULE;
+ c->data = hc;
/* find the server configuration for the address:port */
port = c->listening->servers;
- r->connection = c;
-
if (port->naddrs > 1) {
/*
@@ -354,7 +251,7 @@ ngx_http_init_request(ngx_event_t *rev)
}
}
- addr_conf = &addr6[i].conf;
+ hc->addr_conf = &addr6[i].conf;
break;
#endif
@@ -372,7 +269,7 @@ ngx_http_init_request(ngx_event_t *rev)
}
}
- addr_conf = &addr[i].conf;
+ hc->addr_conf = &addr[i].conf;
break;
}
@@ -384,90 +281,161 @@ ngx_http_init_request(ngx_event_t *rev)
#if (NGX_HAVE_INET6)
case AF_INET6:
addr6 = port->addrs;
- addr_conf = &addr6[0].conf;
+ hc->addr_conf = &addr6[0].conf;
break;
#endif
default: /* AF_INET */
addr = port->addrs;
- addr_conf = &addr[0].conf;
+ hc->addr_conf = &addr[0].conf;
break;
}
}
- r->virtual_names = addr_conf->virtual_names;
-
/* the default server configuration for the address:port */
- cscf = addr_conf->default_server;
+ hc->conf_ctx = hc->addr_conf->default_server->ctx;
- r->main_conf = cscf->ctx->main_conf;
- r->srv_conf = cscf->ctx->srv_conf;
- r->loc_conf = cscf->ctx->loc_conf;
+ ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
+ if (ctx == NULL) {
+ ngx_http_close_connection(c);
+ return;
+ }
- rev->handler = ngx_http_process_request_line;
- r->read_event_handler = ngx_http_block_reading;
+ ctx->connection = c;
+ ctx->request = NULL;
+ ctx->current_request = NULL;
-#if (NGX_HTTP_SSL)
+ c->log->connection = c->number;
+ c->log->handler = ngx_http_log_error;
+ c->log->data = ctx;
+ c->log->action = "reading client request line";
+ c->log_error = NGX_ERROR_INFO;
+
+ rev = c->read;
+ rev->handler = ngx_http_init_request;
+ c->write->handler = ngx_http_empty_handler;
+
+#if (NGX_HTTP_SSL)
{
ngx_http_ssl_srv_conf_t *sscf;
- sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
- if (sscf->enable || addr_conf->ssl) {
+ sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
- if (c->ssl == NULL) {
+ if (sscf->enable || hc->addr_conf->ssl) {
- c->log->action = "SSL handshaking";
+ c->log->action = "SSL handshaking";
- if (addr_conf->ssl && sscf->ssl.ctx == NULL) {
- ngx_log_error(NGX_LOG_ERR, c->log, 0,
- "no \"ssl_certificate\" is defined "
- "in server listening on SSL port");
- ngx_http_close_connection(c);
- return;
- }
+ if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) {
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
+ "no \"ssl_certificate\" is defined "
+ "in server listening on SSL port");
+ ngx_http_close_connection(c);
+ return;
+ }
- if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
- != NGX_OK)
- {
- ngx_http_close_connection(c);
- return;
- }
+ hc->ssl = 1;
+
+ rev->handler = ngx_http_ssl_handshake;
+ }
+ }
+#endif
- rev->handler = ngx_http_ssl_handshake;
+ if (rev->ready) {
+ /* the deferred accept(), rtsig, aio, iocp */
+
+ if (ngx_use_accept_mutex) {
+ ngx_post_event(rev, &ngx_posted_events);
+ return;
}
- r->main_filter_need_in_memory = 1;
+ rev->handler(rev);
+ return;
}
+
+ ngx_add_timer(rev, c->listening->post_accept_timeout);
+
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
+ ngx_http_close_connection(c);
+ return;
}
+}
-#endif
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- c->log->file = clcf->error_log->file;
- if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
- c->log->log_level = clcf->error_log->log_level;
+static void
+ngx_http_init_request(ngx_event_t *rev)
+{
+ ngx_pool_t *pool;
+ ngx_time_t *tp;
+ ngx_connection_t *c;
+ ngx_http_request_t *r;
+ ngx_http_log_ctx_t *ctx;
+ ngx_http_connection_t *hc;
+ ngx_http_core_srv_conf_t *cscf;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_core_main_conf_t *cmcf;
+
+ c = rev->data;
+
+ if (rev->timedout) {
+ ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
+
+ ngx_http_close_connection(c);
+ return;
+ }
+
+ c->requests++;
+
+ hc = c->data;
+
+ cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
+
+ pool = ngx_create_pool(cscf->request_pool_size, c->log);
+ if (pool == NULL) {
+ ngx_http_close_connection(c);
+ return;
+ }
+
+ r = ngx_pcalloc(pool, sizeof(ngx_http_request_t));
+ if (r == NULL) {
+ ngx_destroy_pool(pool);
+ ngx_http_close_connection(c);
+ return;
}
+ r->pool = pool;
+
+ r->pipeline = hc->pipeline;
+
+ c->data = r;
+ r->http_connection = hc;
+
+ c->sent = 0;
+ r->signature = NGX_HTTP_MODULE;
+
+ r->connection = c;
+
+ r->main_conf = hc->conf_ctx->main_conf;
+ r->srv_conf = hc->conf_ctx->srv_conf;
+ r->loc_conf = hc->conf_ctx->loc_conf;
+
+ r->read_event_handler = ngx_http_block_reading;
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ ngx_http_set_connection_log(r->connection, clcf->error_log);
+
if (c->buffer == NULL) {
c->buffer = ngx_create_temp_buf(c->pool,
cscf->client_header_buffer_size);
if (c->buffer == NULL) {
+ ngx_destroy_pool(r->pool);
ngx_http_close_connection(c);
return;
}
}
- if (r->header_in == NULL) {
- r->header_in = c->buffer;
- }
-
- r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
- if (r->pool == NULL) {
- ngx_http_close_connection(c);
- return;
- }
-
+ r->header_in = hc->nbusy ? hc->busy[0] : c->buffer;
if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
sizeof(ngx_table_elt_t))
@@ -498,6 +466,12 @@ ngx_http_init_request(ngx_event_t *rev)
c->single_connection = 1;
c->destroyed = 0;
+#if (NGX_HTTP_SSL)
+ if (c->ssl) {
+ r->main_filter_need_in_memory = 1;
+ }
+#endif
+
r->main = r;
r->count = 1;
@@ -528,7 +502,8 @@ ngx_http_init_request(ngx_event_t *rev)
(void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
#endif
- rev->handler(rev);
+ rev->handler = ngx_http_process_request_line;
+ ngx_http_process_request_line(rev);
}
@@ -537,37 +512,48 @@ ngx_http_init_request(ngx_event_t *rev)
static void
ngx_http_ssl_handshake(ngx_event_t *rev)
{
- u_char buf[1];
- ssize_t n;
- ngx_int_t rc;
- ngx_connection_t *c;
- ngx_http_request_t *r;
+ u_char buf[1];
+ ssize_t n;
+ ngx_err_t err;
+ ngx_int_t rc;
+ ngx_connection_t *c;
+ ngx_http_connection_t *hc;
+ ngx_http_ssl_srv_conf_t *sscf;
c = rev->data;
- r = c->data;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
"http check ssl handshake");
if (rev->timedout) {
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
- c->timedout = 1;
- ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
+ ngx_http_close_connection(c);
return;
}
n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
- if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
+ err = ngx_socket_errno;
- if (!rev->timer_set) {
- ngx_add_timer(rev, c->listening->post_accept_timeout);
- }
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %d", n);
- if (ngx_handle_read_event(rev, 0) != NGX_OK) {
- ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ if (n == -1) {
+ if (err == NGX_EAGAIN) {
+
+ if (!rev->timer_set) {
+ ngx_add_timer(rev, c->listening->post_accept_timeout);
+ }
+
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
+ ngx_http_close_connection(c);
+ }
+
+ return;
}
+ ngx_connection_error(c, err, "recv() failed");
+ ngx_http_close_connection(c);
+
return;
}
@@ -576,6 +562,17 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
"https ssl handshake: 0x%02Xd", buf[0]);
+ hc = c->data;
+ sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
+ ngx_http_ssl_module);
+
+ if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
+ != NGX_OK)
+ {
+ ngx_http_close_connection(c);
+ return;
+ }
+
rc = ngx_ssl_handshake(c);
if (rc == NGX_AGAIN) {
@@ -591,27 +588,26 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
ngx_http_ssl_handshake_handler(c);
return;
+ }
- } else {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
- "plain http");
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http");
- r->plain_http = 1;
- }
- }
+ c->log->action = "reading client request line";
- c->log->action = "reading client request line";
+ rev->handler = ngx_http_init_request;
+ ngx_http_init_request(rev);
- rev->handler = ngx_http_process_request_line;
- ngx_http_process_request_line(rev);
+ return;
+ }
+
+ ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection");
+ ngx_http_close_connection(c);
}
static void
ngx_http_ssl_handshake_handler(ngx_connection_t *c)
{
- ngx_http_request_t *r;
-
if (c->ssl->handshaked) {
/*
@@ -626,19 +622,19 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c)
c->log->action = "reading client request line";
- c->read->handler = ngx_http_process_request_line;
+ c->read->handler = ngx_http_init_request;
/* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
- ngx_http_process_request_line(c->read);
+ ngx_http_init_request(c->read);
return;
}
- r = c->data;
-
- ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
+ if (c->read->timedout) {
+ ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
+ }
- return;
+ ngx_http_close_connection(c);
}
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
@@ -646,12 +642,13 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c)
int
ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
{
- size_t len;
- u_char *host;
- const char *servername;
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_http_ssl_srv_conf_t *sscf;
+ ngx_str_t host;
+ const char *servername;
+ ngx_connection_t *c;
+ ngx_http_connection_t *hc;
+ ngx_http_ssl_srv_conf_t *sscf;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_core_srv_conf_t *cscf;
servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
@@ -664,27 +661,41 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"SSL server name: \"%s\"", servername);
- len = ngx_strlen(servername);
+ host.len = ngx_strlen(servername);
- if (len == 0) {
+ if (host.len == 0) {
return SSL_TLSEXT_ERR_NOACK;
}
- r = c->data;
+ host.data = (u_char *) servername;
- host = (u_char *) servername;
+ if (ngx_http_validate_host(&host, c->pool, 1) != NGX_OK) {
+ return SSL_TLSEXT_ERR_NOACK;
+ }
- len = ngx_http_validate_host(r, &host, len, 1);
+ hc = c->data;
- if (len <= 0) {
+ if (ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host,
+ NULL, &cscf)
+ != NGX_OK)
+ {
return SSL_TLSEXT_ERR_NOACK;
}
- if (ngx_http_find_virtual_server(r, host, len) != NGX_OK) {
+ hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t));
+ if (hc->ssl_servername == NULL) {
return SSL_TLSEXT_ERR_NOACK;
}
- sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
+ *hc->ssl_servername = host;
+
+ hc->conf_ctx = cscf->ctx;
+
+ clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module);
+
+ ngx_http_set_connection_log(c, clcf->error_log);
+
+ sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
if (sscf->ssl.ctx) {
SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
@@ -719,9 +730,9 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
static void
ngx_http_process_request_line(ngx_event_t *rev)
{
- u_char *host;
ssize_t n;
ngx_int_t rc, rv;
+ ngx_str_t host;
ngx_connection_t *c;
ngx_http_request_t *r;
ngx_http_core_srv_conf_t *cscf;
@@ -887,33 +898,36 @@ ngx_http_process_request_line(ngx_event_t *rev)
if (r->host_start && r->host_end) {
- host = r->host_start;
- n = ngx_http_validate_host(r, &host,
- r->host_end - r->host_start, 0);
+ host.len = r->host_end - r->host_start;
+ host.data = r->host_start;
+
+ rc = ngx_http_validate_host(&host, r->pool, 0);
- if (n == 0) {
+ if (rc == NGX_DECLINED) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client sent invalid host in request line");
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
}
- if (n < 0) {
+ if (rc == NGX_ERROR) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
- r->headers_in.server.len = n;
- r->headers_in.server.data = host;
+ if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
+ return;
+ }
+
+ r->headers_in.server = host;
}
if (r->http_version < NGX_HTTP_VERSION_10) {
- if (ngx_http_find_virtual_server(r, r->headers_in.server.data,
- r->headers_in.server.len)
- == NGX_ERROR)
+ if (r->headers_in.server.len == 0
+ && ngx_http_set_virtual_server(r, &r->headers_in.server)
+ == NGX_ERROR)
{
- ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
@@ -930,15 +944,6 @@ ngx_http_process_request_line(ngx_event_t *rev)
return;
}
-
- if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
- sizeof(ngx_table_elt_t *))
- != NGX_OK)
- {
- ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
c->log->action = "reading client request headers";
rev->handler = ngx_http_process_request_headers;
@@ -1010,7 +1015,6 @@ ngx_http_process_request_headers(ngx_event_t *rev)
}
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
- cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
rc = NGX_AGAIN;
@@ -1064,6 +1068,9 @@ ngx_http_process_request_headers(ngx_event_t *rev)
}
}
+ /* the host header could change the server configuration context */
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
+
rc = ngx_http_parse_header_line(r, r->header_in,
cscf->underscores_in_headers);
@@ -1413,24 +1420,25 @@ static ngx_int_t
ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset)
{
- u_char *host;
- ssize_t len;
+ ngx_int_t rc;
+ ngx_str_t host;
if (r->headers_in.host == NULL) {
r->headers_in.host = h;
}
- host = h->value.data;
- len = ngx_http_validate_host(r, &host, h->value.len, 0);
+ host = h->value;
+
+ rc = ngx_http_validate_host(&host, r->pool, 0);
- if (len == 0) {
+ if (rc == NGX_DECLINED) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client sent invalid host header");
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return NGX_ERROR;
}
- if (len < 0) {
+ if (rc == NGX_ERROR) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return NGX_ERROR;
}
@@ -1439,8 +1447,11 @@ ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
return NGX_OK;
}
- r->headers_in.server.len = len;
- r->headers_in.server.data = host;
+ if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ r->headers_in.server = host;
return NGX_OK;
}
@@ -1535,31 +1546,41 @@ ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
static ngx_int_t
-ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
+ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset)
{
- ngx_table_elt_t **cookie;
+ ngx_array_t *headers;
+ ngx_table_elt_t **ph;
- cookie = ngx_array_push(&r->headers_in.cookies);
- if (cookie) {
- *cookie = h;
- return NGX_OK;
+ headers = (ngx_array_t *) ((char *) &r->headers_in + offset);
+
+ if (headers->elts == NULL) {
+ if (ngx_array_init(headers, r->pool, 1, sizeof(ngx_table_elt_t *))
+ != NGX_OK)
+ {
+ ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_ERROR;
+ }
}
- ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ ph = ngx_array_push(headers);
+ if (ph == NULL) {
+ ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_ERROR;
+ }
- return NGX_ERROR;
+ *ph = h;
+ return NGX_OK;
}
static ngx_int_t
ngx_http_process_request_header(ngx_http_request_t *r)
{
- if (ngx_http_find_virtual_server(r, r->headers_in.server.data,
- r->headers_in.server.len)
- == NGX_ERROR)
+ if (r->headers_in.server.len == 0
+ && ngx_http_set_virtual_server(r, &r->headers_in.server)
+ == NGX_ERROR)
{
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return NGX_ERROR;
}
@@ -1630,20 +1651,20 @@ ngx_http_process_request(ngx_http_request_t *r)
c = r->connection;
- if (r->plain_http) {
- ngx_log_error(NGX_LOG_INFO, c->log, 0,
- "client sent plain HTTP request to HTTPS port");
- ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
- return;
- }
-
#if (NGX_HTTP_SSL)
- if (c->ssl) {
+ if (r->http_connection->ssl) {
long rc;
X509 *cert;
ngx_http_ssl_srv_conf_t *sscf;
+ if (c->ssl == NULL) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent plain HTTP request to HTTPS port");
+ ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
+ return;
+ }
+
sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
if (sscf->verify) {
@@ -1705,9 +1726,8 @@ ngx_http_process_request(ngx_http_request_t *r)
}
-static ssize_t
-ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len,
- ngx_uint_t alloc)
+static ngx_int_t
+ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
{
u_char *h, ch;
size_t i, dot_pos, host_len;
@@ -1718,21 +1738,21 @@ ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len,
sw_rest
} state;
- dot_pos = len;
- host_len = len;
+ dot_pos = host->len;
+ host_len = host->len;
- h = *host;
+ h = host->data;
state = sw_usual;
- for (i = 0; i < len; i++) {
+ for (i = 0; i < host->len; i++) {
ch = h[i];
switch (ch) {
case '.':
if (dot_pos == i - 1) {
- return 0;
+ return NGX_DECLINED;
}
dot_pos = i;
break;
@@ -1758,12 +1778,12 @@ ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len,
break;
case '\0':
- return 0;
+ return NGX_DECLINED;
default:
if (ngx_path_separator(ch)) {
- return 0;
+ return NGX_DECLINED;
}
if (ch >= 'A' && ch <= 'Z') {
@@ -1778,83 +1798,187 @@ ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len,
host_len--;
}
+ if (host_len == 0) {
+ return NGX_DECLINED;
+ }
+
if (alloc) {
- *host = ngx_pnalloc(r->pool, host_len);
- if (*host == NULL) {
- return -1;
+ host->data = ngx_pnalloc(pool, host_len);
+ if (host->data == NULL) {
+ return NGX_ERROR;
}
- ngx_strlow(*host, h, host_len);
+ ngx_strlow(host->data, h, host_len);
}
- return host_len;
+ host->len = host_len;
+
+ return NGX_OK;
}
static ngx_int_t
-ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len)
+ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host)
{
+ ngx_int_t rc;
+ ngx_http_connection_t *hc;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
- if (r->virtual_names == NULL) {
+ hc = r->http_connection;
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+
+ if (hc->ssl_servername) {
+ if (hc->ssl_servername->len == host->len
+ && ngx_strncmp(hc->ssl_servername->data,
+ host->data, host->len) == 0)
+ {
+#if (NGX_PCRE)
+ if (hc->ssl_servername_regex
+ && ngx_http_regex_exec(r, hc->ssl_servername_regex,
+ hc->ssl_servername) != NGX_OK)
+ {
+ ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_ERROR;
+ }
+#endif
+ return NGX_OK;
+ }
+ }
+
+#endif
+
+ rc = ngx_http_find_virtual_server(r->connection,
+ hc->addr_conf->virtual_names,
+ host, r, &cscf);
+
+ if (rc == NGX_ERROR) {
+ ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_ERROR;
+ }
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+
+ if (hc->ssl_servername) {
+ ngx_http_ssl_srv_conf_t *sscf;
+
+ if (rc == NGX_DECLINED) {
+ cscf = hc->addr_conf->default_server;
+ rc = NGX_OK;
+ }
+
+ sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module);
+
+ if (sscf->verify) {
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "client attempted to request the server name "
+ "different from that one was negotiated");
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+ return NGX_ERROR;
+ }
+ }
+
+#endif
+
+ if (rc == NGX_DECLINED) {
+ return NGX_OK;
+ }
+
+ r->srv_conf = cscf->ctx->srv_conf;
+ r->loc_conf = cscf->ctx->loc_conf;
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ ngx_http_set_connection_log(r->connection, clcf->error_log);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_find_virtual_server(ngx_connection_t *c,
+ ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
+ ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp)
+{
+ ngx_http_core_srv_conf_t *cscf;
+
+ if (virtual_names == NULL) {
return NGX_DECLINED;
}
- cscf = ngx_hash_find_combined(&r->virtual_names->names,
- ngx_hash_key(host, len), host, len);
+ cscf = ngx_hash_find_combined(&virtual_names->names,
+ ngx_hash_key(host->data, host->len),
+ host->data, host->len);
if (cscf) {
- goto found;
+ *cscfp = cscf;
+ return NGX_OK;
}
#if (NGX_PCRE)
- if (len && r->virtual_names->nregex) {
+ if (host->len && virtual_names->nregex) {
ngx_int_t n;
ngx_uint_t i;
- ngx_str_t name;
ngx_http_server_name_t *sn;
- name.len = len;
- name.data = host;
+ sn = virtual_names->regex;
- sn = r->virtual_names->regex;
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- for (i = 0; i < r->virtual_names->nregex; i++) {
+ if (r == NULL) {
+ ngx_http_connection_t *hc;
- n = ngx_http_regex_exec(r, sn[i].regex, &name);
+ for (i = 0; i < virtual_names->nregex; i++) {
- if (n == NGX_OK) {
- cscf = sn[i].server;
- goto found;
- }
+ n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0);
- if (n == NGX_DECLINED) {
- continue;
+ if (n == NGX_REGEX_NO_MATCHED) {
+ continue;
+ }
+
+ if (n >= 0) {
+ hc = c->data;
+ hc->ssl_servername_regex = sn[i].regex;
+
+ *cscfp = sn[i].server;
+ return NGX_OK;
+ }
+
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ ngx_regex_exec_n " failed: %i "
+ "on \"%V\" using \"%V\"",
+ n, host, &sn[i].regex->name);
+
+ return NGX_ERROR;
}
- return NGX_ERROR;
+ return NGX_DECLINED;
}
- }
-#endif
+#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
- return NGX_DECLINED;
+ for (i = 0; i < virtual_names->nregex; i++) {
-found:
+ n = ngx_http_regex_exec(r, sn[i].regex, host);
- r->srv_conf = cscf->ctx->srv_conf;
- r->loc_conf = cscf->ctx->loc_conf;
+ if (n == NGX_DECLINED) {
+ continue;
+ }
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- r->connection->log->file = clcf->error_log->file;
+ if (n == NGX_OK) {
+ *cscfp = sn[i].server;
+ return NGX_OK;
+ }
- if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
- r->connection->log->log_level = clcf->error_log->log_level;
+ return NGX_ERROR;
+ }
}
- return NGX_OK;
+#endif /* NGX_PCRE */
+
+ return NGX_DECLINED;
}
@@ -2528,6 +2652,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
}
}
+ /* guard against recursive call from ngx_http_finalize_connection() */
r->keepalive = 0;
ngx_http_free_request(r, 0);
@@ -2548,10 +2673,6 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
-#if (NGX_STAT_STUB)
- (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
-#endif
-
hc->pipeline = 1;
c->log->action = "reading client pipelined request line";
@@ -2563,17 +2684,12 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
hc->pipeline = 0;
/*
- * To keep a memory footprint as small as possible for an idle
- * keepalive connection we try to free the ngx_http_request_t and
- * c->buffer's memory if they were allocated outside the c->pool.
- * The large header buffers are always allocated outside the c->pool and
- * are freed too.
+ * To keep a memory footprint as small as possible for an idle keepalive
+ * connection we try to free c->buffer's memory if it was allocated outside
+ * the c->pool. The large header buffers are always allocated outside the
+ * c->pool and are freed too.
*/
- if (ngx_pfree(c->pool, r) == NGX_OK) {
- hc->request = NULL;
- }
-
b = c->buffer;
if (ngx_pfree(c->pool, b->start) == NGX_OK) {
@@ -2758,6 +2874,7 @@ ngx_http_keepalive_handler(ngx_event_t *rev)
if (n == NGX_AGAIN) {
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
+ return;
}
/*
@@ -2793,10 +2910,6 @@ ngx_http_keepalive_handler(ngx_event_t *rev)
b->last += n;
-#if (NGX_STAT_STUB)
- (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
-#endif
-
c->log->handler = ngx_http_log_error;
c->log->action = "reading client request line";
@@ -3027,6 +3140,7 @@ static void
ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
{
ngx_log_t *log;
+ ngx_pool_t *pool;
struct linger linger;
ngx_http_cleanup_t *cln;
ngx_http_log_ctx_t *ctx;
@@ -3093,7 +3207,15 @@ ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
r->connection->destroyed = 1;
- ngx_destroy_pool(r->pool);
+ /*
+ * Setting r->pool to NULL will increase probability to catch double close
+ * of request since the request object is allocated from its own pool.
+ */
+
+ pool = r->pool;
+ r->pool = NULL;
+
+ ngx_destroy_pool(pool);
}
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index f0c39adaf..fd004e8f1 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -200,7 +200,7 @@ typedef struct {
ngx_table_elt_t *keep_alive;
#if (NGX_HTTP_X_FORWARDED_FOR)
- ngx_table_elt_t *x_forwarded_for;
+ ngx_array_t x_forwarded_for;
#endif
#if (NGX_HTTP_REALIP)
@@ -289,8 +289,18 @@ typedef struct {
} ngx_http_request_body_t;
+typedef struct ngx_http_addr_conf_s ngx_http_addr_conf_t;
+
typedef struct {
- ngx_http_request_t *request;
+ ngx_http_addr_conf_t *addr_conf;
+ ngx_http_conf_ctx_t *conf_ctx;
+
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ ngx_str_t *ssl_servername;
+#if (NGX_PCRE)
+ ngx_http_regex_t *ssl_servername_regex;
+#endif
+#endif
ngx_buf_t **busy;
ngx_int_t nbusy;
@@ -298,21 +308,11 @@ typedef struct {
ngx_buf_t **free;
ngx_int_t nfree;
- ngx_uint_t pipeline; /* unsigned pipeline:1; */
+ unsigned pipeline:1;
+ unsigned ssl:1;
} ngx_http_connection_t;
-typedef struct ngx_http_server_name_s ngx_http_server_name_t;
-
-
-typedef struct {
- ngx_hash_combined_t names;
-
- ngx_uint_t nregex;
- ngx_http_server_name_t *regex;
-} ngx_http_virtual_names_t;
-
-
typedef void (*ngx_http_cleanup_pt)(void *data);
typedef struct ngx_http_cleanup_s ngx_http_cleanup_t;
@@ -406,8 +406,6 @@ struct ngx_http_request_s {
ngx_http_post_subrequest_t *post_subrequest;
ngx_http_posted_request_t *posted_requests;
- ngx_http_virtual_names_t *virtual_names;
-
ngx_int_t phase_handler;
ngx_http_handler_pt content_handler;
ngx_uint_t access_code;
@@ -500,7 +498,6 @@ struct ngx_http_request_s {
#endif
unsigned pipeline:1;
- unsigned plain_http:1;
unsigned chunked:1;
unsigned header_only:1;
unsigned keepalive:1;
@@ -580,4 +577,12 @@ extern ngx_http_header_t ngx_http_headers_in[];
extern ngx_http_header_out_t ngx_http_headers_out[];
+#define ngx_http_set_connection_log(c, l) \
+ \
+ c->log->file = l->file; \
+ if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { \
+ c->log->log_level = l->log_level; \
+ }
+
+
#endif /* _NGX_HTTP_REQUEST_H_INCLUDED_ */
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index b8190b030..6f1e0344d 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -21,8 +21,13 @@ static void ngx_http_variable_request_set_size(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+
+static ngx_int_t ngx_http_variable_cookies(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_headers_internal(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data, u_char sep);
static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
@@ -133,8 +138,8 @@ static ngx_int_t ngx_http_variable_time_local(ngx_http_request_t *r,
*/
/*
- * the $http_host, $http_user_agent, $http_referer, $http_via,
- * and $http_x_forwarded_for variables may be handled by generic
+ * the $http_host, $http_user_agent, $http_referer, and $http_via
+ * variables may be handled by generic
* ngx_http_variable_unknown_header_in(), but for performance reasons
* they are handled using dedicated entries
*/
@@ -156,11 +161,11 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
#endif
#if (NGX_HTTP_X_FORWARDED_FOR)
- { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_header,
+ { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_headers,
offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 },
#endif
- { ngx_string("http_cookie"), NULL, ngx_http_variable_headers,
+ { ngx_string("http_cookie"), NULL, ngx_http_variable_cookies,
offsetof(ngx_http_request_t, headers_in.cookies), 0, 0 },
{ ngx_string("content_length"), NULL, ngx_http_variable_content_length,
@@ -726,8 +731,24 @@ ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
static ngx_int_t
-ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- uintptr_t data)
+ngx_http_variable_cookies(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ return ngx_http_variable_headers_internal(r, v, data, ';');
+}
+
+
+static ngx_int_t
+ngx_http_variable_headers(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ return ngx_http_variable_headers_internal(r, v, data, ',');
+}
+
+
+static ngx_int_t
+ngx_http_variable_headers_internal(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data, u_char sep)
{
size_t len;
u_char *p, *end;
@@ -748,7 +769,7 @@ ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
continue;
}
- len += h[i]->value.len + sizeof("; ") - 1;
+ len += h[i]->value.len + 2;
}
if (len == 0) {
@@ -756,7 +777,7 @@ ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
return NGX_OK;
}
- len -= sizeof("; ") - 1;
+ len -= 2;
v->valid = 1;
v->no_cacheable = 0;
@@ -791,7 +812,7 @@ ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
break;
}
- *p++ = ';'; *p++ = ' ';
+ *p++ = sep; *p++ = ' ';
}
return NGX_OK;