mirror of
https://github.com/nginx/nginx.git
synced 2024-12-12 02:09:04 +08:00
Create request object only after the first byte was received.
Previously, we always created an object and logged 400 (Bad Request) in access log if a client closed connection without sending any data. Such a connection was counted as "reading". Since it's common for modern browsers to behave like this, it's no longer considered an error if a client closes connection without sending any data, and such a connection will be counted as "waiting". Now, we do not log 400 (Bad Request) and keep memory footprint as small as possible.
This commit is contained in:
parent
1e1b93b51f
commit
a46a3ab68d
@ -10,6 +10,7 @@
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
static void ngx_http_wait_request_handler(ngx_event_t *ev);
|
||||
static void ngx_http_init_request(ngx_event_t *ev);
|
||||
static void ngx_http_process_request_line(ngx_event_t *rev);
|
||||
static void ngx_http_process_request_headers(ngx_event_t *rev);
|
||||
@ -308,12 +309,12 @@ ngx_http_init_connection(ngx_connection_t *c)
|
||||
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->action = "waiting for request";
|
||||
|
||||
c->log_error = NGX_ERROR_INFO;
|
||||
|
||||
rev = c->read;
|
||||
rev->handler = ngx_http_init_request;
|
||||
rev->handler = ngx_http_wait_request_handler;
|
||||
c->write->handler = ngx_http_empty_handler;
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
@ -362,6 +363,99 @@ ngx_http_init_connection(ngx_connection_t *c)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_wait_request_handler(ngx_event_t *rev)
|
||||
{
|
||||
size_t size;
|
||||
ssize_t n;
|
||||
ngx_buf_t *b;
|
||||
ngx_connection_t *c;
|
||||
ngx_http_connection_t *hc;
|
||||
ngx_http_core_srv_conf_t *cscf;
|
||||
|
||||
c = rev->data;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http wait request handler");
|
||||
|
||||
if (rev->timedout) {
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
hc = c->data;
|
||||
cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
|
||||
|
||||
size = cscf->client_header_buffer_size;
|
||||
|
||||
b = c->buffer;
|
||||
|
||||
if (b == NULL) {
|
||||
b = ngx_create_temp_buf(c->pool, size);
|
||||
if (b == NULL) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
c->buffer = b;
|
||||
|
||||
} else if (b->start == NULL) {
|
||||
|
||||
b->start = ngx_palloc(c->pool, size);
|
||||
if (b->start == NULL) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
b->pos = b->start;
|
||||
b->last = b->start;
|
||||
b->end = b->last + size;
|
||||
}
|
||||
|
||||
n = c->recv(c, b->last, size);
|
||||
|
||||
if (n == NGX_AGAIN) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are trying to not hold c->buffer's memory for an idle connection.
|
||||
*/
|
||||
|
||||
if (ngx_pfree(c->pool, b->start) == NGX_OK) {
|
||||
b->start = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (n == NGX_ERROR) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
|
||||
"client closed connection");
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
b->last += n;
|
||||
|
||||
c->log->action = "reading client request line";
|
||||
|
||||
ngx_http_init_request(rev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_init_request(ngx_event_t *rev)
|
||||
{
|
||||
@ -377,13 +471,6 @@ ngx_http_init_request(ngx_event_t *rev)
|
||||
|
||||
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;
|
||||
@ -425,16 +512,6 @@ ngx_http_init_request(ngx_event_t *rev)
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
r->header_in = hc->nbusy ? hc->busy[0] : c->buffer;
|
||||
|
||||
if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
|
||||
@ -592,10 +669,10 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http");
|
||||
|
||||
c->log->action = "reading client request line";
|
||||
c->log->action = "waiting for request";
|
||||
|
||||
rev->handler = ngx_http_init_request;
|
||||
ngx_http_init_request(rev);
|
||||
rev->handler = ngx_http_wait_request_handler;
|
||||
ngx_http_wait_request_handler(rev);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -620,12 +697,12 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c)
|
||||
|
||||
c->ssl->no_wait_shutdown = 1;
|
||||
|
||||
c->log->action = "reading client request line";
|
||||
c->log->action = "waiting for request";
|
||||
|
||||
c->read->handler = ngx_http_init_request;
|
||||
c->read->handler = ngx_http_wait_request_handler;
|
||||
/* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
|
||||
|
||||
ngx_http_init_request(c->read);
|
||||
ngx_http_wait_request_handler(c->read);
|
||||
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user