ngx_http_request.c

来自「Nginx是一个高性能的HTTP和反向代理服务器」· C语言 代码 · 共 2,528 行 · 第 1/5 页

C
2,528
字号
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_event.h>#include <ngx_http.h>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);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_unique_header_line(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_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 void ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host,    size_t len, ngx_uint_t hash);static void ngx_http_request_handler(ngx_event_t *ev);static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);static void ngx_http_writer(ngx_http_request_t *r);static void ngx_http_test_reading(ngx_http_request_t *r);static void ngx_http_set_keepalive(ngx_http_request_t *r);static void ngx_http_keepalive_handler(ngx_event_t *ev);static void ngx_http_set_lingering_close(ngx_http_request_t *r);static void ngx_http_lingering_close_handler(ngx_event_t *ev);static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);static void ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error);static void ngx_http_close_connection(ngx_connection_t *c);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,    ngx_http_request_t *sr, u_char *buf, size_t len);#if (NGX_HTTP_SSL)static void ngx_http_ssl_handshake(ngx_event_t *rev);static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);#endifstatic char *ngx_http_client_errors[] = {    /* NGX_HTTP_PARSE_INVALID_METHOD */    "client sent invalid method",    /* NGX_HTTP_PARSE_INVALID_REQUEST */    "client sent invalid request",    /* NGX_HTTP_PARSE_INVALID_09_METHOD */    "client sent invalid method in HTTP/0.9 request"};ngx_http_header_t  ngx_http_headers_in[] = {    { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),                 ngx_http_process_unique_header_line },    { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),                 ngx_http_process_connection },    { ngx_string("If-Modified-Since"),                 offsetof(ngx_http_headers_in_t, if_modified_since),                 ngx_http_process_unique_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),                 ngx_http_process_unique_header_line },    { ngx_string("Content-Type"),                 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 },    { ngx_string("If-Range"),                 offsetof(ngx_http_headers_in_t, if_range),                 ngx_http_process_unique_header_line },    { ngx_string("Transfer-Encoding"),                 offsetof(ngx_http_headers_in_t, transfer_encoding),                 ngx_http_process_header_line },#if (NGX_HTTP_GZIP)    { ngx_string("Accept-Encoding"),                 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_http_process_unique_header_line },    { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),                 ngx_http_process_header_line },#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)    { ngx_string("X-Forwarded-For"),                 offsetof(ngx_http_headers_in_t, x_forwarded_for),                 ngx_http_process_header_line },#endif#if (NGX_HTTP_REALIP)    { ngx_string("X-Real-IP"),                 offsetof(ngx_http_headers_in_t, x_real_ip),                 ngx_http_process_header_line },#endif#if (NGX_HTTP_HEADERS)    { 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),                 ngx_http_process_header_line },#endif#if (NGX_HTTP_DAV)    { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),                 ngx_http_process_header_line },    { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),                 ngx_http_process_header_line },    { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),                 ngx_http_process_header_line },    { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),                 ngx_http_process_header_line },#endif    { ngx_string("Cookie"), 0, ngx_http_process_cookie },    { ngx_null_string, 0, NULL }};voidngx_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)    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_ERROR) {#if (NGX_STAT_STUB)        ngx_atomic_fetch_add(ngx_stat_reading, -1);#endif        ngx_http_close_connection(c);        return;    }}static voidngx_http_init_request(ngx_event_t *rev){    ngx_time_t                 *tp;    ngx_uint_t                  i;    ngx_connection_t           *c;    ngx_http_request_t         *r;    ngx_http_in_port_t         *hip;    ngx_http_in_addr_t         *hia;    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;#if (NGX_STAT_STUB)    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");        ngx_http_close_connection(c);        return;    }    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;    /* find the server configuration for the address:port */    /* AF_INET only */    hip = c->listening->servers;    hia = hip->addrs;    r->port = hip->port;    r->port_text = &hip->port_text;    i = 0;    r->connection = c;    if (hip->naddrs > 1) {        /*         * There are several addresses on this port and one of them         * is the "*:port" wildcard so getsockname() is needed to determine         * the server address.         *         * AcceptEx() already has given this address.         */#if (NGX_WIN32)        if (c->local_sockaddr) {            r->in_addr =                   ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;        } else#endif        {            if (ngx_http_server_addr(r, NULL) != NGX_OK) {                ngx_http_close_connection(c);                return;            }        }        /* the last address is "*" */        for ( /* void */ ; i < hip->naddrs - 1; i++) {            if (hia[i].addr == r->in_addr) {                break;            }        }    } else {        r->in_addr = hia[0].addr;    }    r->virtual_names = hia[i].virtual_names;    /* the default server configuration for the address:port */    cscf = hia[i].core_srv_conf;    r->main_conf = cscf->ctx->main_conf;    r->srv_conf = cscf->ctx->srv_conf;    r->loc_conf = cscf->ctx->loc_conf;    rev->handler = ngx_http_process_request_line;#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) {        if (c->ssl == NULL) {            if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)                == NGX_ERROR)            {                ngx_http_close_connection(c);                return;            }            rev->handler = ngx_http_ssl_handshake;        }        r->main_filter_need_in_memory = 1;    }    }#endif    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);    c->log->file = clcf->err_log->file;    if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {        c->log->log_level = clcf->err_log->log_level;    }    if (c->buffer == NULL) {        c->buffer = ngx_create_temp_buf(c->pool,                                        cscf->client_header_buffer_size);        if (c->buffer == NULL) {            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;    }    if (ngx_list_init(&r->headers_out.headers, r->pool, 20,                      sizeof(ngx_table_elt_t))        == NGX_ERROR)    {        ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);        return;    }    r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);    if (r->ctx == NULL) {        ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);        return;    }    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);    r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts                                        * sizeof(ngx_http_variable_value_t));    if (r->variables == NULL) {        ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);        return;    }    c->single_connection = 1;    c->destroyed = 0;    r->main = r;    tp = ngx_timeofday();    r->start_sec = tp->sec;    r->start_msec = tp->msec;    r->method = NGX_HTTP_UNKNOWN;    r->headers_in.content_length_n = -1;    r->headers_in.keep_alive_n = -1;    r->headers_out.content_length_n = -1;    r->headers_out.last_modified_time = -1;    r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;    r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;    r->http_state = NGX_HTTP_READING_REQUEST_STATE;    ctx = c->log->data;    ctx->request = r;    ctx->current_request = r;    r->log_handler = ngx_http_log_error_handler;#if (NGX_STAT_STUB)    ngx_atomic_fetch_add(ngx_stat_reading, 1);    r->stat_reading = 1;    ngx_atomic_fetch_add(ngx_stat_requests, 1);#endif    rev->handler(rev);}#if (NGX_HTTP_SSL)static voidngx_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;    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);        return;    }    n = recv(c->fd, (char *) buf, 1, MSG_PEEK);    if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {        if (!rev->timer_set) {            ngx_add_timer(rev, c->listening->post_accept_timeout);        }        if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {            ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);        }        return;    }    if (n == 1) {        if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,                           "https ssl handshake: 0x%02Xd", buf[0]);            rc = ngx_ssl_handshake(c);            if (rc == NGX_AGAIN) {                if (!rev->timer_set) {                    ngx_add_timer(rev, c->listening->post_accept_timeout);                }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?