summaryrefslogtreecommitdiff
path: root/src/http/ngx_http_request.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/http/ngx_http_request.c')
-rw-r--r--src/http/ngx_http_request.c788
1 files changed, 455 insertions, 333 deletions
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);
}