ngx_http_request.c

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

C
2,528
字号
                c->ssl->handler = ngx_http_ssl_handshake_handler;                return;            }            ngx_http_ssl_handshake_handler(c);            return;        } else {            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,                           "plain http");            r->plain_http = 1;        }    }    rev->handler = ngx_http_process_request_line;    ngx_http_process_request_line(rev);}static voidngx_http_ssl_handshake_handler(ngx_connection_t *c){    ngx_http_request_t  *r;    if (c->ssl->handshaked) {        /*         * The majority of browsers do not send the "close notify" alert.         * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,         * and Links.  And what is more, MSIE ignores the server's alert.         *         * Opera and recent Mozilla send the alert.         */        c->ssl->no_wait_shutdown = 1;        c->read->handler = ngx_http_process_request_line;        /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;        ngx_http_process_request_line(c->read);        return;    }    r = c->data;    ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);    return;}#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAMEintngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg){    u_char                   *p;    ngx_uint_t                hash;    const char               *servername;    ngx_connection_t         *c;    ngx_http_request_t       *r;    ngx_http_ssl_srv_conf_t  *sscf;    servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);    if (servername == NULL) {        return SSL_TLSEXT_ERR_NOACK;    }    c = ngx_ssl_get_connection(ssl_conn);    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,                   "SSL server name: \"%s\"", servername);    r = c->data;    if (r->virtual_names == NULL) {        return SSL_TLSEXT_ERR_NOACK;    }    /* it seems browsers send low case server name */    hash = 0;    for (p = (u_char *) servername; *p; p++) {        hash = ngx_hash(hash, *p);    }    ngx_http_find_virtual_server(r, (u_char *) servername,                                 p - (u_char *) servername, hash);    sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);    SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);    return SSL_TLSEXT_ERR_OK;}#endif#endifstatic voidngx_http_process_request_line(ngx_event_t *rev){    ssize_t                    n;    ngx_int_t                  rc, rv;    ngx_connection_t          *c;    ngx_http_request_t        *r;    ngx_http_core_srv_conf_t  *cscf;    c = rev->data;    r = c->data;    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,                   "http process request line");    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;    }    rc = NGX_AGAIN;    for ( ;; ) {        if (rc == NGX_AGAIN) {            n = ngx_http_read_request_header(r);            if (n == NGX_AGAIN || n == NGX_ERROR) {                return;            }        }        rc = ngx_http_parse_request_line(r, r->header_in);        if (rc == NGX_OK) {            /* the request line has been parsed successfully */            r->request_line.len = r->request_end - r->request_start;            r->request_line.data = r->request_start;            if (r->args_start) {                r->uri.len = r->args_start - 1 - r->uri_start;            } else {                r->uri.len = r->uri_end - r->uri_start;            }            if (r->complex_uri || r->quoted_uri) {                r->uri.data = ngx_palloc(r->pool, r->uri.len + 1);                if (r->uri.data == NULL) {                    ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);                    return;                }                cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);                rc = ngx_http_parse_complex_uri(r, cscf->merge_slashes);                if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) {                    ngx_log_error(NGX_LOG_INFO, c->log, 0,                                  "client sent invalid request");                    ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);                    return;                }            } else {                r->uri.data = r->uri_start;            }            r->unparsed_uri.len = r->uri_end - r->uri_start;            r->unparsed_uri.data = r->uri_start;            r->method_name.len = r->method_end - r->request_start + 1;            r->method_name.data = r->request_line.data;            if (r->http_protocol.data) {                r->http_protocol.len = r->request_end - r->http_protocol.data;            }            if (r->uri_ext) {                if (r->args_start) {                    r->exten.len = r->args_start - 1 - r->uri_ext;                } else {                    r->exten.len = r->uri_end - r->uri_ext;                }                r->exten.data = r->uri_ext;            }            if (r->args_start && r->uri_end > r->args_start) {                r->args.len = r->uri_end - r->args_start;                r->args.data = r->args_start;            }            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,                           "http request line: \"%V\"", &r->request_line);            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,                           "http uri: \"%V\"", &r->uri);            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,                           "http args: \"%V\"", &r->args);            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,                           "http exten: \"%V\"", &r->exten);            if (r->http_version < NGX_HTTP_VERSION_10) {                ngx_http_process_request(r);                return;            }            if (ngx_list_init(&r->headers_in.headers, r->pool, 20,                              sizeof(ngx_table_elt_t))                == NGX_ERROR)            {                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);                return;            }            if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,                               sizeof(ngx_table_elt_t *))                == NGX_ERROR)            {                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;            ngx_http_process_request_headers(rev);            return;        }        if (rc != NGX_AGAIN) {            /* there was error while a request line parsing */            ngx_log_error(NGX_LOG_INFO, c->log, 0,                          ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);            ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);            return;        }        /* NGX_AGAIN: a request line parsing is still incomplete */        if (r->header_in->pos == r->header_in->end) {            rv = ngx_http_alloc_large_header_buffer(r, 1);            if (rv == NGX_ERROR) {                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);                return;            }            if (rv == NGX_DECLINED) {                r->request_line.len = r->header_in->end - r->request_start;                r->request_line.data = r->request_start;                ngx_log_error(NGX_LOG_INFO, c->log, 0,                              "client sent too long URI");                ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);                return;            }        }    }}static voidngx_http_process_request_headers(ngx_event_t *rev){    ssize_t                     n;    ngx_int_t                   rc, rv;    ngx_str_t                   header;    ngx_uint_t                  i;    ngx_table_elt_t            *h;    ngx_connection_t           *c;    ngx_http_header_t          *hh;    ngx_http_request_t         *r;    ngx_http_core_srv_conf_t   *cscf;    ngx_http_core_main_conf_t  *cmcf;    c = rev->data;    r = c->data;    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,                   "http process request header line");    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;    }    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;    for ( ;; ) {        if (rc == NGX_AGAIN) {            if (r->header_in->pos == r->header_in->end) {                rv = ngx_http_alloc_large_header_buffer(r, 0);                if (rv == NGX_ERROR) {                    ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);                    return;                }                if (rv == NGX_DECLINED) {                    header.len = r->header_in->end - r->header_name_start;                    header.data = r->header_name_start;                    if (header.len > NGX_MAX_ERROR_STR - 300) {                        header.len = NGX_MAX_ERROR_STR - 300;                        header.data[header.len++] = '.';                        header.data[header.len++] = '.';                        header.data[header.len++] = '.';                    }                    ngx_log_error(NGX_LOG_INFO, c->log, 0,                                  "client sent too long header line: \"%V\"",                                  &header);                    ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);                    return;                }            }            n = ngx_http_read_request_header(r);            if (n == NGX_AGAIN || n == NGX_ERROR) {                return;            }        }        rc = ngx_http_parse_header_line(r, r->header_in);        if (rc == NGX_OK) {            if (r->invalid_header && cscf->ignore_invalid_headers) {                /* there was error while a header line parsing */                header.len = r->header_end - r->header_name_start;                header.data = r->header_name_start;                ngx_log_error(NGX_LOG_INFO, c->log, 0,                              "client sent invalid header line: \"%V\"",                              &header);                continue;            }            /* a header line has been parsed successfully */            h = ngx_list_push(&r->headers_in.headers);            if (h == NULL) {                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);                return;            }            h->hash = r->header_hash;            h->key.len = r->header_name_end - r->header_name_start;            h->key.data = r->header_name_start;            h->key.data[h->key.len] = '\0';            h->value.len = r->header_end - r->header_start;            h->value.data = r->header_start;            h->value.data[h->value.len] = '\0';            h->lowcase_key = ngx_palloc(r->pool, h->key.len);            if (h->lowcase_key == NULL) {                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);                return;            }            if (h->key.len == r->lowcase_index) {                ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);            } else {                for (i = 0; i < h->key.len; i++) {                    h->lowcase_key[i] = ngx_tolower(h->key.data[i]);                }            }            hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,                               h->lowcase_key, h->key.len);            if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {                return;            }            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,                           "http header: \"%V: %V\"",                           &h->key, &h->value);            continue;        }        if (rc == NGX_HTTP_PARSE_HEADER_DONE) {            /* a whole header has been parsed successfully */            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,                           "http header done");            r->request_length += r->header_in->pos - r->header_in->start;            r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;            rc = ngx_http_process_request_header(r);            if (rc != NGX_OK) {                return;            }            ngx_http_process_request(r);            return;        }        if (rc == NGX_AGAIN) {            /* a header line parsing is still not complete */            continue;        }        /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */        header.len = r->header_end - r->header_name_start;        header.data = r->header_name_start;        ngx_log_error(NGX_LOG_INFO, c->log, 0,                      "client sent invalid header line: \"%V\\r...\"",                      &header);        ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);        return;    }}static ssize_tngx_http_read_request_header(ngx_http_request_t *r){    ssize_t                    n;    ngx_event_t               *rev;    ngx_connection_t          *c;    ngx_http_core_srv_conf_t  *cscf;    c = r->connection;    rev = c->read;    n = r->header_in->last - r->header_in->pos;    if (n > 0) {        return n;    }    if (rev->ready) {        n = c->recv(c, r->header_in->last,                    r->header_in->end - r->header_in->last);    } else {        n = NGX_AGAIN;    }    if (n == NGX_AGAIN) {        if (!rev->timer_set) {            cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);            ngx_add_timer(rev, cscf->client_header_timeout);        }        if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {            ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);            return NGX_ERROR;        }        return NGX_AGAIN;    }    if (n == 0) {        ngx_log_error(NGX_LOG_INFO, c->log, 0,                      "client closed prematurely connection");

⌨️ 快捷键说明

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