ngx_http_request.c

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

C
2,528
字号
    }    if (n == 0 || n == NGX_ERROR) {        c->error = 1;        c->log->action = "reading client request headers";        ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);        return NGX_ERROR;    }    r->header_in->last += n;    return n;}static ngx_int_tngx_http_alloc_large_header_buffer(ngx_http_request_t *r,    ngx_uint_t request_line){    u_char                    *old, *new;    ngx_buf_t                 *b;    ngx_http_connection_t     *hc;    ngx_http_core_srv_conf_t  *cscf;    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,                   "http alloc large header buffer");    if (request_line && r->state == 0) {        /* the client fills up the buffer with "\r\n" */        r->request_length += r->header_in->end - r->header_in->start;        r->header_in->pos = r->header_in->start;        r->header_in->last = r->header_in->start;        return NGX_OK;    }    old = request_line ? r->request_start : r->header_name_start;    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);    if (r->state != 0        && (size_t) (r->header_in->pos - old)                                     >= cscf->large_client_header_buffers.size)    {        return NGX_DECLINED;    }    hc = r->http_connection;    if (hc->nfree) {        b = hc->free[--hc->nfree];        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,                       "http large header free: %p %uz",                       b->pos, b->end - b->last);    } else if (hc->nbusy < cscf->large_client_header_buffers.num) {        if (hc->busy == NULL) {            hc->busy = ngx_palloc(r->connection->pool,                  cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));            if (hc->busy == NULL) {                return NGX_ERROR;            }        }        b = ngx_create_temp_buf(r->connection->pool,                                cscf->large_client_header_buffers.size);        if (b == NULL) {            return NGX_ERROR;        }        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,                       "http large header alloc: %p %uz",                       b->pos, b->end - b->last);    } else {        return NGX_DECLINED;    }    hc->busy[hc->nbusy++] = b;    if (r->state == 0) {        /*         * r->state == 0 means that a header line was parsed successfully         * and we do not need to copy incomplete header line and         * to relocate the parser header pointers         */        r->request_length += r->header_in->end - r->header_in->start;        r->header_in = b;        return NGX_OK;    }    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,                   "http large header copy: %d", r->header_in->pos - old);    r->request_length += old - r->header_in->start;    new = b->start;    ngx_memcpy(new, old, r->header_in->pos - old);    b->pos = new + (r->header_in->pos - old);    b->last = new + (r->header_in->pos - old);    if (request_line) {        r->request_start = new;        if (r->request_end) {            r->request_end = new + (r->request_end - old);        }        r->method_end = new + (r->method_end - old);        r->uri_start = new + (r->uri_start - old);        r->uri_end = new + (r->uri_end - old);        if (r->schema_start) {            r->schema_start = new + (r->schema_start - old);            r->schema_end = new + (r->schema_end - old);        }        if (r->host_start) {            r->host_start = new + (r->host_start - old);            if (r->host_end) {                r->host_end = new + (r->host_end - old);            }        }        if (r->port_start) {            r->port_start = new + (r->port_start - old);            r->port_end = new + (r->port_end - old);        }        if (r->uri_ext) {            r->uri_ext = new + (r->uri_ext - old);        }        if (r->args_start) {            r->args_start = new + (r->args_start - old);        }        if (r->http_protocol.data) {            r->http_protocol.data = new + (r->http_protocol.data - old);        }    } else {        r->header_name_start = new;        r->header_name_end = new + (r->header_name_end - old);        r->header_start = new + (r->header_start - old);        r->header_end = new + (r->header_end - old);    }    r->header_in = b;    return NGX_OK;}static ngx_int_tngx_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_tngx_http_process_unique_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;    }    ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,                  "client sent duplicate header line: \"%V: %V\", "                  "previous value: \"%V: %V\"",                  &h->key, &h->value, &(*ph)->key, &(*ph)->value);    ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);    return NGX_ERROR;}static ngx_int_tngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,    ngx_uint_t offset){    if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {        r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;    } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {        r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;    }    return NGX_OK;}static ngx_int_tngx_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) {        *cookie = h;        return NGX_OK;    }    ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);    return NGX_ERROR;}static ngx_int_tngx_http_process_request_header(ngx_http_request_t *r){    size_t       len;    u_char      *host, *ua, *user_agent, ch;    ngx_uint_t   hash;    if (r->headers_in.host) {        hash = 0;        for (len = 0; len < r->headers_in.host->value.len; len++) {            ch = r->headers_in.host->value.data[len];            if (ch == ':') {                break;            }            ch = ngx_tolower(ch);            r->headers_in.host->value.data[len] = ch;            hash = ngx_hash(hash, ch);        }        if (len && r->headers_in.host->value.data[len - 1] == '.') {            len--;            hash = ngx_hash_key(r->headers_in.host->value.data, len);        }        r->headers_in.host_name_len = len;        if (r->virtual_names) {            host = r->host_start;            if (host == NULL) {                host = r->headers_in.host->value.data;                len = r->headers_in.host_name_len;            } else {                len = r->host_end - host;            }            ngx_http_find_virtual_server(r, host, len, hash);        }    } else {        if (r->http_version > NGX_HTTP_VERSION_10) {            ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,                       "client sent HTTP/1.1 request without \"Host\" header");            ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);            return NGX_ERROR;        }        r->headers_in.host_name_len = 0;    }    if (r->headers_in.content_length) {        r->headers_in.content_length_n =                            ngx_atoof(r->headers_in.content_length->value.data,                                      r->headers_in.content_length->value.len);        if (r->headers_in.content_length_n == NGX_ERROR) {            ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,                          "client sent invalid \"Content-Length\" header");            ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);            return NGX_ERROR;        }    }    if (r->method & (NGX_HTTP_POST|NGX_HTTP_PUT)        && r->headers_in.content_length_n == -1)    {        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,                  "client sent %V method without \"Content-Length\" header",                  &r->method_name);        ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);        return NGX_ERROR;    }    if (r->method & NGX_HTTP_TRACE) {        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,                      "client sent TRACE method");        ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);        return NGX_ERROR;    }    if (r->headers_in.transfer_encoding        && ngx_strcasestrn(r->headers_in.transfer_encoding->value.data,                           "chunked", 7 - 1))    {        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,                      "client sent \"Transfer-Encoding: chunked\" header");        ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);        return NGX_ERROR;    }    if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {        if (r->headers_in.keep_alive) {            r->headers_in.keep_alive_n =                            ngx_atotm(r->headers_in.keep_alive->value.data,                                      r->headers_in.keep_alive->value.len);        }    }    if (r->headers_in.user_agent) {        /*         * check some widespread browsers while the headers are still         * in CPU cache         */        user_agent = r->headers_in.user_agent->value.data;        ua = ngx_strstrn(user_agent, "MSIE", 4 - 1);        if (ua && ua + 8 < user_agent + r->headers_in.user_agent->value.len) {            r->headers_in.msie = 1;            if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') {                r->headers_in.msie4 = 1;            }#if 0            /* MSIE ignores the SSL "close notify" alert */            if (c->ssl) {                c->ssl->no_send_shutdown = 1;            }#endif        }        if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {            r->headers_in.opera = 1;            r->headers_in.msie = 0;            r->headers_in.msie4 = 0;        }        if (!r->headers_in.msie && !r->headers_in.opera) {            if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {                r->headers_in.gecko = 1;            } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {                r->headers_in.konqueror = 1;            }        }    }    return NGX_OK;}static voidngx_http_process_request(ngx_http_request_t *r){    ngx_connection_t  *c;    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) {        long                      rc;        X509                     *cert;        ngx_http_ssl_srv_conf_t  *sscf;        sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);        if (sscf->verify) {            rc = SSL_get_verify_result(c->ssl->connection);            if (rc != X509_V_OK) {                ngx_log_error(NGX_LOG_INFO, c->log, 0,                              "client SSL certificate verify error: (%l:%s)",                              rc, X509_verify_cert_error_string(rc));                ngx_ssl_remove_cached_session(sscf->ssl.ctx,                                       (SSL_get0_session(c->ssl->connection)));                ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);                return;            }            cert = SSL_get_peer_certificate(c->ssl->connection);            if (cert == NULL) {                ngx_log_error(NGX_LOG_INFO, c->log, 0,                              "client sent no required SSL certificate");                ngx_ssl_remove_cached_session(sscf->ssl.ctx,                                       (SSL_get0_session(c->ssl->connection)));                ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);                return;            }            X509_free(cert);        }    }#endif    if (c->read->timer_set) {        ngx_del_timer(c->read);    }#if (NGX_STAT_STUB)    ngx_atomic_fetch_add(ngx_stat_reading, -1);    r->stat_reading = 0;    ngx_atomic_fetch_add(ngx_stat_writing, 1);    r->stat_writing = 1;#endif    c->read->handler = ngx_http_request_handler;    c->write->handler = ngx_http_request_handler;    r->read_event_handler = ngx_http_block_reading;    ngx_http_handler(r);    return;}static voidngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len,    ngx_uint_t hash){    ngx_http_core_loc_conf_t  *clcf;    ngx_http_core_srv_conf_t  *cscf;    cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, host, len);    if (cscf) {        goto found;    }#if (NGX_PCRE)    if (r->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 = r->virtual_names->regex;        for (i = 0; i < r->virtual_names->nregex; i++) {            n = ngx_regex_exec(sn[i].regex, &name, NULL, 0);            if (n == NGX_REGEX_NO_MATCHED) {                continue;            }            if (n < 0) {                ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,                              ngx_regex_exec_n

⌨️ 快捷键说明

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