Mercurial > hg > nginx-vendor-current
diff src/http/ngx_http_request.c @ 58:b55cbf18157e NGINX_0_1_29
nginx 0.1.29
*) Feature: the ngx_http_ssi_module supports "include virtual" command.
*) Feature: the ngx_http_ssi_module supports the condition command like
'if expr="$NAME"' and "else" and "endif" commands. Only one nested
level is supported.
*) Feature: the ngx_http_ssi_module supports the DATE_LOCAL and
DATE_GMT variables and "config timefmt" command.
*) Feature: the "ssi_ignore_recycled_buffers" directive.
*) Bugfix: the "echo" command did not show the default value for the
empty QUERY_STRING variable.
*) Change: the ngx_http_proxy_module was rewritten.
*) Feature: the "proxy_redirect", "proxy_pass_request_headers",
"proxy_pass_request_body", and "proxy_method" directives.
*) Feature: the "proxy_set_header" directive. The "proxy_x_var" was
canceled and must be replaced with the proxy_set_header directive.
*) Change: the "proxy_preserve_host" is canceled and must be replaced
with the "proxy_set_header Host $host" and the "proxy_redirect off"
directives, the "proxy_set_header Host $host:$proxy_port" directive
and the appropriate proxy_redirect directives.
*) Change: the "proxy_set_x_real_ip" is canceled and must be replaced
with the "proxy_set_header X-Real-IP $remote_addr" directive.
*) Change: the "proxy_add_x_forwarded_for" is canceled and must be
replaced with
the "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for"
directive.
*) Change: the "proxy_set_x_url" is canceled and must be replaced with
the "proxy_set_header X-URL http://$host:$server_port$request_uri"
directive.
*) Feature: the "fastcgi_param" directive.
*) Change: the "fastcgi_root", "fastcgi_set_var" and "fastcgi_params"
directive are canceled and must be replaced with the fastcgi_param
directives.
*) Feature: the "index" directive can use the variables.
*) Feature: the "index" directive can be used at http and server levels.
*) Change: the last index only in the "index" directive can be absolute.
*) Feature: the "rewrite" directive can use the variables.
*) Feature: the "internal" directive.
*) Feature: the CONTENT_LENGTH, CONTENT_TYPE, REMOTE_PORT, SERVER_ADDR,
SERVER_PORT, SERVER_PROTOCOL, DOCUMENT_ROOT, SERVER_NAME,
REQUEST_METHOD, REQUEST_URI, and REMOTE_USER variables.
*) Change: nginx now passes the invalid lines in a client request
headers or a backend response header.
*) Bugfix: if the backend did not transfer response for a long time and
the "send_timeout" was less than "proxy_read_timeout", then nginx
returned the 408 response.
*) Bugfix: the segmentation fault was occurred if the backend sent an
invalid line in response header; bug appeared in 0.1.26.
*) Bugfix: the segmentation fault may occurred in FastCGI fault
tolerance configuration.
*) Bugfix: the "expires" directive did not remove the previous
"Expires" and "Cache-Control" headers.
*) Bugfix: nginx did not take into account trailing dot in "Host"
header line.
*) Bugfix: the ngx_http_auth_module did not work under Linux.
*) Bugfix: the rewrite directive worked incorrectly, if the arguments
were in a request.
*) Bugfix: nginx could not be built on MacOS X.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Thu, 12 May 2005 00:00:00 +0400 |
parents | 3050baa54a26 |
children | df7d3fff122b |
line wrap: on
line diff
--- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -19,13 +19,22 @@ static void ngx_http_process_request_hea static ssize_t ngx_http_read_request_header(ngx_http_request_t *r); static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, ngx_uint_t request_line); + +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_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 ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r); +static void ngx_http_request_handler(ngx_event_t *ev); static void ngx_http_set_write_handler(ngx_http_request_t *r); - -static void ngx_http_block_read(ngx_event_t *ev); -static void ngx_http_read_discarded_body_event(ngx_event_t *rev); +static void ngx_http_writer(ngx_http_request_t *r); +static ngx_int_t ngx_http_postponed_handler(ngx_http_request_t *r); + +static void ngx_http_block_read(ngx_http_request_t *r); +static void ngx_http_read_discarded_body_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r); static void ngx_http_set_keepalive(ngx_http_request_t *r); @@ -34,6 +43,8 @@ static void ngx_http_set_lingering_close static void ngx_http_lingering_close_handler(ngx_event_t *ev); static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len); +static u_char *ngx_http_log_error_handler(ngx_http_request_t *r, u_char *buf, + size_t len); static char *ngx_http_client_errors[] = { @@ -50,59 +61,81 @@ static char *ngx_http_client_errors[] = ngx_http_header_t ngx_http_headers_in[] = { - { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host) }, - { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection) }, + { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host), + ngx_http_process_header_line }, + + { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection), + ngx_http_process_header_line }, + { ngx_string("If-Modified-Since"), - offsetof(ngx_http_headers_in_t, if_modified_since) }, - { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) }, - { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer) }, + offsetof(ngx_http_headers_in_t, if_modified_since), + ngx_http_process_header_line }, + + { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent), + ngx_http_process_header_line }, + + { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer), + ngx_http_process_header_line }, + { ngx_string("Content-Length"), - offsetof(ngx_http_headers_in_t, content_length) }, + offsetof(ngx_http_headers_in_t, content_length), + ngx_http_process_header_line }, + { ngx_string("Content-Type"), - offsetof(ngx_http_headers_in_t, content_type) }, - - { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range) }, + offsetof(ngx_http_headers_in_t, content_type), + ngx_http_process_header_line }, + + { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range), + ngx_http_process_header_line }, + #if 0 - { ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range) }, + { ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range), + ngx_http_process_header_line }, #endif #if (NGX_HTTP_GZIP) { ngx_string("Accept-Encoding"), - offsetof(ngx_http_headers_in_t, accept_encoding) }, - { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via) }, + offsetof(ngx_http_headers_in_t, accept_encoding), + ngx_http_process_header_line }, + + { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via), + ngx_http_process_header_line }, #endif { ngx_string("Authorization"), - offsetof(ngx_http_headers_in_t, authorization) }, - - { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive) }, + offsetof(ngx_http_headers_in_t, authorization), + ngx_http_process_header_line }, + + { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive), + ngx_http_process_header_line }, #if (NGX_HTTP_PROXY) { ngx_string("X-Forwarded-For"), - offsetof(ngx_http_headers_in_t, x_forwarded_for) }, - { ngx_string("X-Real-IP"), offsetof(ngx_http_headers_in_t, x_real_ip) }, - { ngx_string("X-URL"), offsetof(ngx_http_headers_in_t, x_url) }, + offsetof(ngx_http_headers_in_t, x_forwarded_for), + ngx_http_process_header_line }, + + { ngx_string("X-Real-IP"), offsetof(ngx_http_headers_in_t, x_real_ip), + ngx_http_process_header_line }, + + { ngx_string("X-URL"), offsetof(ngx_http_headers_in_t, x_url), + ngx_http_process_header_line }, #endif #if (NGX_HTTP_HEADERS) - { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept) }, + { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept), + ngx_http_process_header_line }, + { ngx_string("Accept-Language"), - offsetof(ngx_http_headers_in_t, accept_language) }, + offsetof(ngx_http_headers_in_t, accept_language), + ngx_http_process_header_line }, #endif - { ngx_null_string, 0 } + { ngx_string("Cookie"), 0, ngx_http_process_cookie }, + + { ngx_null_string, 0, NULL } }; -#if 0 -static void -ngx_http_dummy(ngx_event_t *wev) -{ - return; -} -#endif - - void ngx_http_init_connection(ngx_connection_t *c) { @@ -126,9 +159,9 @@ ngx_http_init_connection(ngx_connection_ c->log_error = NGX_ERROR_INFO; rev = c->read; - rev->event_handler = ngx_http_init_request; - - /* STUB: epoll edge */ c->write->event_handler = ngx_http_empty_handler; + rev->handler = ngx_http_init_request; + + /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler; if (rev->ready) { /* the deferred accept(), rtsig, aio, iocp */ @@ -165,18 +198,6 @@ ngx_http_init_connection(ngx_connection_ return; } -#if 0 - /* TODO: learn SO_SNDBUF (to use in zerocopy) via kqueue's EV_CLEAR event */ - - c->write->ready = 0; - c->write->event_handler = ngx_http_dummy; - - if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { - ngx_http_close_connection(c); - return; - } -#endif - #if (NGX_STAT_STUB) ngx_atomic_inc(ngx_stat_reading); #endif @@ -335,7 +356,7 @@ void ngx_http_init_request(ngx_event_t * r->srv_conf = cscf->ctx->srv_conf; r->loc_conf = cscf->ctx->loc_conf; - rev->event_handler = ngx_http_process_request_line; + rev->handler = ngx_http_process_request_line; #if (NGX_HTTP_SSL) @@ -350,7 +371,7 @@ void ngx_http_init_request(ngx_event_t * return; } - rev->event_handler = ngx_http_ssl_handshake; + rev->handler = ngx_http_ssl_handshake; /* * The majority of browsers do not send the "close notify" alert. @@ -396,17 +417,9 @@ void ngx_http_init_request(ngx_event_t * return; } - if (ngx_array_init(&r->cleanup, r->pool, 4, sizeof(ngx_http_cleanup_t)) - == NGX_ERROR) - { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); - return; - } - if (ngx_list_init(&r->headers_out.headers, r->pool, 20, - sizeof(ngx_table_elt_t)) == NGX_ERROR) + sizeof(ngx_table_elt_t)) == NGX_ERROR) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); ngx_http_close_connection(c); @@ -426,8 +439,6 @@ void ngx_http_init_request(ngx_event_t * r->start_time = ngx_time(); - r->file.fd = NGX_INVALID_FILE; - r->headers_in.content_length_n = -1; r->headers_in.keep_alive_n = -1; r->headers_out.content_length_n = -1; @@ -437,6 +448,7 @@ void ngx_http_init_request(ngx_event_t * ctx = c->log->data; ctx->request = r; + r->log_handler = ngx_http_log_error_handler; #if (NGX_STAT_STUB) ngx_atomic_inc(ngx_stat_reading); @@ -444,7 +456,7 @@ void ngx_http_init_request(ngx_event_t * ngx_atomic_inc(ngx_stat_requests); #endif - rev->event_handler(rev); + rev->handler(rev); } @@ -507,7 +519,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev) } } - rev->event_handler = ngx_http_process_request_line; + rev->handler = ngx_http_process_request_line; ngx_http_process_request_line(rev); } @@ -593,10 +605,8 @@ ngx_http_process_request_line(ngx_event_ r->unparsed_uri.data = r->uri_start; - if (r->method == 0) { - r->method_name.len = r->method_end - r->request_start + 1; - r->method_name.data = r->request_line.data; - } + r->method_name.len = r->method_end - r->request_start + 1; + r->method_name.data = r->request_line.data; if (r->http_protocol.data) { @@ -634,7 +644,7 @@ ngx_http_process_request_line(ngx_event_ "http exten: \"%V\"", &r->exten); if (r->http_version < NGX_HTTP_VERSION_10) { - rev->event_handler = ngx_http_block_read; + r->read_event_handler = ngx_http_block_read; ngx_http_handler(r); return; } @@ -659,7 +669,7 @@ ngx_http_process_request_line(ngx_event_ c->log->action = "reading client request headers"; - rev->event_handler = ngx_http_process_request_headers; + rev->handler = ngx_http_process_request_headers; ngx_http_process_request_headers(rev); return; @@ -711,7 +721,7 @@ ngx_http_process_request_headers(ngx_eve ngx_int_t rc, rv; ngx_uint_t key; ngx_str_t header; - ngx_table_elt_t *h, **cookie; + ngx_table_elt_t *h; ngx_connection_t *c; ngx_http_header_t *hh; ngx_http_request_t *r; @@ -773,6 +783,7 @@ ngx_http_process_request_headers(ngx_eve if (rc == NGX_OK) { +#if 0 if (r->invalid_header) { /* there was error while a header line parsing */ @@ -785,11 +796,10 @@ ngx_http_process_request_headers(ngx_eve &header); continue; } +#endif /* a header line has been parsed successfully */ - r->headers_n++; - h = ngx_list_push(&r->headers_in.headers); if (h == NULL) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -807,27 +817,14 @@ ngx_http_process_request_headers(ngx_eve h->value.data = r->header_start; h->value.data[h->value.len] = '\0'; - if (h->key.len == sizeof("Cookie") - 1 - && ngx_strcasecmp(h->key.data, "Cookie") == 0) + key = h->hash % cmcf->headers_in_hash.hash_size; + + if (hh[key].name.len == h->key.len + && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0) { - cookie = ngx_array_push(&r->headers_in.cookies); - if (cookie == NULL) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_close_connection(c); + if (hh[key].handler(r, h, hh[key].offset) != NGX_OK) { return; } - - *cookie = h; - - } else { - key = h->hash % cmcf->headers_in_hash.hash_size; - - if (hh[key].name.len == h->key.len - && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0) - { - *((ngx_table_elt_t **) - ((char *) &r->headers_in + hh[key].offset)) = h; - } } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -865,7 +862,10 @@ ngx_http_process_request_headers(ngx_eve r->stat_writing = 1; #endif - rev->event_handler = ngx_http_block_read; + rev->handler = ngx_http_request_handler; + c->write->handler = ngx_http_request_handler; + r->read_event_handler = ngx_http_block_read; + ngx_http_handler(r); return; } @@ -1091,6 +1091,41 @@ ngx_http_alloc_large_header_buffer(ngx_h static ngx_int_t +ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_table_elt_t **ph; + + ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset); + + if (*ph == NULL) { + *ph = h; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_table_elt_t **cookie; + + cookie = ngx_array_push(&r->headers_in.cookies); + if (cookie == NULL) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(r->connection); + return NGX_ERROR; + } + + *cookie = h; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r) { size_t len; @@ -1108,6 +1143,10 @@ ngx_http_process_request_header(ngx_http r->headers_in.host->value.data[len] = ngx_tolower(ch); } + if (r->headers_in.host->value.data[len - 1] == '.') { + len--; + } + r->headers_in.host_name_len = len; if (ngx_http_find_virtual_server(r) != NGX_OK) { @@ -1167,13 +1206,13 @@ ngx_http_process_request_header(ngx_http if (r->headers_in.connection) { if (r->headers_in.connection->value.len == 5 && ngx_strcasecmp(r->headers_in.connection->value.data, "close") - == 0) + == 0) { r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE; } else if (r->headers_in.connection->value.len == 10 && ngx_strcasecmp(r->headers_in.connection->value.data, - "keep-alive") == 0) + "keep-alive") == 0) { r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE; @@ -1237,7 +1276,7 @@ static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r) { ngx_int_t rc; - ngx_uint_t i, n, key, found; + ngx_uint_t i, n, key; ngx_http_server_name_t *name; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; @@ -1259,8 +1298,6 @@ ngx_http_find_virtual_server(ngx_http_re n = r->virtual_names->names.nelts; } - found = 0; - for (i = 0; i < n; i++) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -1275,9 +1312,7 @@ ngx_http_find_virtual_server(ngx_http_re if (rc == 0) { r->server_name = name[i].name; - - found = 1; - break; + goto found; } if (rc < 0) { @@ -1286,7 +1321,7 @@ ngx_http_find_virtual_server(ngx_http_re } } - if (!found && r->virtual_names->wildcards.nelts) { + if (r->virtual_names->wildcards.nelts) { name = r->virtual_names->wildcards.elts; for (i = 0; i < r->virtual_names->wildcards.nelts; i++) { @@ -1310,49 +1345,110 @@ ngx_http_find_virtual_server(ngx_http_re r->server_name.len = r->headers_in.host_name_len; r->server_name.data = r->headers_in.host->value.data; - found = 1; - break; + goto found; } } } - if (found) { - r->srv_conf = name[i].core_srv_conf->ctx->srv_conf; - r->loc_conf = name[i].core_srv_conf->ctx->loc_conf; - - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - r->connection->log->file = clcf->err_log->file; - - if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { - r->connection->log->log_level = clcf->err_log->log_level; - } - + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + if (cscf->restrict_host_names == NGX_HTTP_RESTRICT_HOST_OFF) { return NGX_OK; } - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - if (cscf->restrict_host_names != NGX_HTTP_RESTRICT_HOST_OFF) { - return NGX_ERROR; + return NGX_ERROR; + +found: + + r->srv_conf = name[i].core_srv_conf->ctx->srv_conf; + r->loc_conf = name[i].core_srv_conf->ctx->loc_conf; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + r->connection->log->file = clcf->err_log->file; + + if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { + r->connection->log->log_level = clcf->err_log->log_level; } return NGX_OK; } +static void +ngx_http_request_handler(ngx_event_t *ev) +{ + ngx_connection_t *c; + ngx_http_request_t *r; + + c = ev->data; + r = c->data; + + if (ev->write) { + r->write_event_handler(r); + + } else { + r->read_event_handler(r); + } +} + + void -ngx_http_finalize_request(ngx_http_request_t *r, int rc) +ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) { + ngx_http_request_t *pr; ngx_http_core_loc_conf_t *clcf; - /* r may be already destroyed when rc == NGX_DONE */ - - if (rc == NGX_DONE || r->main) { + if (rc == NGX_DONE) { + /* r may be already destroyed when rc == NGX_DONE */ + return; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http finalize request: %d, \"%V\"", rc, &r->uri); + + if (r->parent && rc >= NGX_HTTP_SPECIAL_RESPONSE) { + ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc)); return; } - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http finalize request: %d", rc); + if (r->parent || rc == NGX_AGAIN) { + r->write_event_handler = ngx_http_writer; + } + + r->done = 1; + + if (r != r->connection->data) { + return; + } + + if (r->parent) { + + pr = r->parent; + + if (rc != NGX_AGAIN) { + pr->connection->data = pr; + } + + if (pr->postponed) { + + if (rc != NGX_AGAIN && pr->postponed->request == r) { + pr->postponed = pr->postponed->next; + + if (pr->postponed == NULL) { + return; + } + } + + if (pr->done) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http wake request: \"%V\"", &pr->uri); + + pr->write_event_handler(pr); + } + } + + return; + } if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { @@ -1379,7 +1475,7 @@ ngx_http_finalize_request(ngx_http_reque ngx_http_close_connection(r->connection); return; - } else if (rc == NGX_AGAIN) { + } else if (rc == NGX_AGAIN || r->out) { ngx_http_set_write_handler(r); return; } @@ -1430,17 +1526,15 @@ ngx_http_set_write_handler(ngx_http_requ ngx_event_t *wev; ngx_http_core_loc_conf_t *clcf; + r->http_state = NGX_HTTP_WRITING_REQUEST_STATE; + wev = r->connection->write; - wev->event_handler = ngx_http_writer; - - r->http_state = NGX_HTTP_WRITING_REQUEST_STATE; if (wev->ready && wev->delayed) { return; } - clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r, - ngx_http_core_module); + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (!wev->delayed) { ngx_add_timer(wev, clcf->send_timeout); } @@ -1449,23 +1543,22 @@ ngx_http_set_write_handler(ngx_http_requ ngx_http_close_request(r, 0); ngx_http_close_connection(r->connection); } - - return; } -void -ngx_http_writer(ngx_event_t *wev) +static void +ngx_http_writer(ngx_http_request_t *r) { int rc; + ngx_event_t *wev; ngx_connection_t *c; - ngx_http_request_t *r; ngx_http_core_loc_conf_t *clcf; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer handler"); - - c = wev->data; - r = c->data; + c = r->connection; + wev = c->write; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, wev->log, 0, + "http writer handler: \"%V\"", &r->uri); if (wev->timedout) { if (!wev->delayed) { @@ -1510,10 +1603,21 @@ ngx_http_writer(ngx_event_t *wev) } } - rc = ngx_http_output_filter(r, NULL); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http writer output filter: %d", rc); + if (r->postponed) { + rc = ngx_http_postponed_handler(r); + + if (rc == NGX_DONE) { + /* r may be already destroyed when rc == NGX_DONE */ + return; + } + + } else { + rc = ngx_http_output_filter(r, NULL); + + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http writer output filter: %d, \"%V\"", rc, &r->uri); if (rc == NGX_AGAIN) { clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r, @@ -1530,28 +1634,81 @@ ngx_http_writer(ngx_event_t *wev) return; } - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http writer done"); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, wev->log, 0, + "http writer done: \"%V\"", &r->uri); ngx_http_finalize_request(r, rc); } +static ngx_int_t +ngx_http_postponed_handler(ngx_http_request_t *r) +{ + ngx_int_t rc; + ngx_http_postponed_request_t *pr; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http postpone handler \"%V\"", &r->uri); + + pr = r->postponed; + + if (pr->request == NULL) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http postponed data \"%V\" %p", &r->uri, pr->out); + + rc = ngx_http_output_filter(r, NULL); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http postponed output filter: %d", rc); + + if (rc == NGX_AGAIN) { + return rc; + } + + if (rc == NGX_ERROR) { + /* NGX_ERROR may be returned by any filter */ + r->connection->write->error = 1; + + ngx_http_finalize_request(r, rc); + + return NGX_DONE; + } + + pr = r->postponed; + + if (pr == NULL) { + return NGX_OK; + } + } + + r = pr->request; + r->connection->data = r; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http postponed request \"%V\"", &r->uri); + + r->write_event_handler(r); + + return NGX_DONE; +} + + static void -ngx_http_block_read(ngx_event_t *rev) +ngx_http_block_read(ngx_http_request_t *r) { - ngx_connection_t *c; - ngx_http_request_t *r; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http read blocked"); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http read blocked"); /* aio does not call this handler */ - if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) { - if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { - c = rev->data; - r = c->data; + if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) + && r->connection->read->active) + { + if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) + == NGX_ERROR) + { ngx_http_close_request(r, 0); - ngx_http_close_connection(c); + ngx_http_close_connection(r->connection); } } } @@ -1588,9 +1745,9 @@ ngx_http_discard_body(ngx_http_request_t } } - rev->event_handler = ngx_http_read_discarded_body_event; - - if (ngx_handle_level_read_event(rev) == NGX_ERROR) { + r->read_event_handler = ngx_http_read_discarded_body_handler; + + if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -1599,28 +1756,23 @@ ngx_http_discard_body(ngx_http_request_t static void -ngx_http_read_discarded_body_event(ngx_event_t *rev) +ngx_http_read_discarded_body_handler(ngx_http_request_t *r) { - ngx_int_t rc; - ngx_connection_t *c; - ngx_http_request_t *r; - - c = rev->data; - r = c->data; + ngx_int_t rc; rc = ngx_http_read_discarded_body(r); if (rc == NGX_AGAIN) { - if (ngx_handle_level_read_event(rev) == NGX_ERROR) { + if (ngx_handle_read_event(r->connection->read, 0) == NGX_ERROR) { ngx_http_close_request(r, rc); - ngx_http_close_connection(c); + ngx_http_close_connection(r->connection); return; } } if (rc != NGX_OK) { ngx_http_close_request(r, rc); - ngx_http_close_connection(c); + ngx_http_close_connection(r->connection); } } @@ -1737,13 +1889,13 @@ ngx_http_set_keepalive(ngx_http_request_ ngx_add_timer(rev, clcf->keepalive_timeout); - if (ngx_handle_level_read_event(rev) == NGX_ERROR) { + if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { ngx_http_close_connection(c); return; } wev = c->write; - wev->event_handler = ngx_http_empty_handler; + wev->handler = ngx_http_empty_handler; if (b->pos < b->last) { @@ -1809,7 +1961,7 @@ ngx_http_set_keepalive(ngx_http_request_ hc->nbusy = 0; } - rev->event_handler = ngx_http_keepalive_handler; + rev->handler = ngx_http_keepalive_handler; if (wev->active) { if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { @@ -1944,7 +2096,7 @@ ngx_http_keepalive_handler(ngx_event_t * c->log_error = NGX_ERROR_INFO; if (n == NGX_AGAIN) { - if (ngx_handle_level_read_event(rev) == NGX_ERROR) { + if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { ngx_http_close_connection(c); } @@ -1986,19 +2138,19 @@ ngx_http_set_lingering_close(ngx_http_re clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); rev = c->read; - rev->event_handler = ngx_http_lingering_close_handler; + rev->handler = ngx_http_lingering_close_handler; r->lingering_time = ngx_time() + clcf->lingering_time / 1000; ngx_add_timer(rev, clcf->lingering_timeout); - if (ngx_handle_level_read_event(rev) == NGX_ERROR) { + if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { ngx_http_close_request(r, 0); ngx_http_close_connection(c); return; } wev = c->write; - wev->event_handler = ngx_http_empty_handler; + wev->handler = ngx_http_empty_handler; if (wev->active) { if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { @@ -2075,7 +2227,7 @@ ngx_http_lingering_close_handler(ngx_eve } while (rev->ready); - if (ngx_handle_level_read_event(rev) == NGX_ERROR) { + if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { ngx_http_close_request(r, 0); ngx_http_close_connection(c); return; @@ -2102,6 +2254,16 @@ ngx_http_empty_handler(ngx_event_t *wev) } +void +ngx_http_request_empty_handler(ngx_http_request_t *r) +{ + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http requets empty handler"); + + return; +} + + ngx_int_t ngx_http_send_last(ngx_http_request_t *r) { @@ -2122,14 +2284,12 @@ ngx_http_send_last(ngx_http_request_t *r void -ngx_http_close_request(ngx_http_request_t *r, int error) +ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error) { - ngx_uint_t i; ngx_log_t *log; + struct linger linger; ngx_http_log_ctx_t *ctx; - ngx_http_cleanup_t *cleanup; ngx_http_core_loc_conf_t *clcf; - struct linger l; log = r->connection->log; @@ -2157,62 +2317,15 @@ ngx_http_close_request(ngx_http_request_ ngx_http_log_handler(r); - cleanup = r->cleanup.elts; - for (i = 0; i < r->cleanup.nelts; i++) { - if (!cleanup[i].valid) { - continue; - } - -#if (NGX_HTTP_CACHE) - - if (cleanup[i].cache) { - ngx_http_cache_unlock(cleanup[i].data.cache.hash, - cleanup[i].data.cache.cache, log); - continue; - } - -#endif - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http cleanup fd: %d", - cleanup[i].data.file.fd); - - if (ngx_close_file(cleanup[i].data.file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - ngx_close_file_n " \"%s\" failed", - cleanup[i].data.file.name); - } - } - - /* STUB */ - if (r->file.fd != NGX_INVALID_FILE) { - if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - ngx_close_file_n " \"%V\" failed", &r->file.name); - } - } - - if (r->request_body - && r->request_body->temp_file - && r->request_body->temp_file->file.fd != NGX_INVALID_FILE) - { - if (ngx_close_file(r->request_body->temp_file->file.fd) - == NGX_FILE_ERROR) - { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - ngx_close_file_n " deleted file \"%V\" failed", - &r->request_body->temp_file->file.name); - } - } - if (r->connection->timedout) { clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (clcf->reset_timedout_connection) { - l.l_onoff = 1; - l.l_linger = 0; + linger.l_onoff = 1; + linger.l_linger = 0; if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER, - (const void *) &l, sizeof(struct linger)) == -1) + (const void *) &linger, sizeof(struct linger)) == -1) { ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno, "setsockopt(SO_LINGER) failed"); @@ -2220,7 +2333,7 @@ ngx_http_close_request(ngx_http_request_ } } - /* the variuos request strings were allocated from r->pool */ + /* the various request strings were allocated from r->pool */ ctx = log->data; ctx->request = NULL; @@ -2263,8 +2376,8 @@ ngx_http_close_connection(ngx_connection if (c->ssl) { if (ngx_ssl_shutdown(c) == NGX_AGAIN) { - c->read->event_handler = ngx_ssl_close_handler; - c->write->event_handler = ngx_ssl_close_handler; + c->read->handler = ngx_ssl_close_handler; + c->write->handler = ngx_ssl_close_handler; return; } } @@ -2290,26 +2403,31 @@ ngx_http_log_error(ngx_log_t *log, u_cha ngx_http_request_t *r; ngx_http_log_ctx_t *ctx; - p = buf; - - ctx = log->data; - if (log->action) { - p = ngx_snprintf(p, len, " while %s", log->action); + p = ngx_snprintf(buf, len, " while %s", log->action); len -= p - buf; buf = p; } + ctx = log->data; + p = ngx_snprintf(buf, len, ", client: %V", ctx->client); + len -= p - buf; r = ctx->request; - if (r == NULL) { - return p; + if (r) { + return r->log_handler(r, p, len); } - len -= p - buf; - buf = p; + return p; +} + + +static u_char * +ngx_http_log_error_handler(ngx_http_request_t *r, u_char *buf, size_t len) +{ + u_char *p; if (r->server_name.data) { p = ngx_snprintf(buf, len, ", server: %V", &r->server_name);