diff options
Diffstat (limited to 'src/http/ngx_http_request.c')
-rw-r--r-- | src/http/ngx_http_request.c | 210 |
1 files changed, 173 insertions, 37 deletions
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index f80785d8f..7dbbcceb2 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -55,7 +55,6 @@ 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_log_request(ngx_http_request_t *r); -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); @@ -303,6 +302,46 @@ ngx_http_init_connection(ngx_connection_t *c) /* the default server configuration for the address:port */ hc->conf_ctx = hc->addr_conf->default_server->ctx; +#if (NGX_HTTP_QUIC) + + if (hc->addr_conf->quic) { + ngx_quic_conf_t *qcf; + ngx_http_ssl_srv_conf_t *sscf; + +#if (NGX_HTTP_V3) + + if (hc->addr_conf->http3) { + ngx_int_t rc; + + rc = ngx_http_v3_init_connection(c); + + if (rc == NGX_ERROR) { + ngx_http_close_connection(c); + return; + } + + if (rc == NGX_DONE) { + return; + } + } + +#endif + + if (c->qs == NULL) { + c->log->connection = c->number; + + qcf = ngx_http_get_module_srv_conf(hc->conf_ctx, + ngx_http_quic_module); + sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, + ngx_http_ssl_module); + + ngx_quic_run(c, &sscf->ssl, qcf); + return; + } + } + +#endif + ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t)); if (ctx == NULL) { ngx_http_close_connection(c); @@ -619,6 +658,12 @@ ngx_http_alloc_request(ngx_connection_t *c) r->method = NGX_HTTP_UNKNOWN; r->http_version = NGX_HTTP_VERSION_10; +#if (NGX_HTTP_V3) + if (hc->addr_conf->http3) { + r->http_version = NGX_HTTP_VERSION_30; + } +#endif + r->headers_in.content_length_n = -1; r->headers_in.keep_alive_n = -1; r->headers_out.content_length_n = -1; @@ -1068,7 +1113,16 @@ ngx_http_process_request_line(ngx_event_t *rev) } } - rc = ngx_http_parse_request_line(r, r->header_in); + switch (r->http_version) { +#if (NGX_HTTP_V3) + case NGX_HTTP_VERSION_30: + rc = ngx_http_v3_parse_request(r, r->header_in); + break; +#endif + + default: /* HTTP/1.x */ + rc = ngx_http_parse_request_line(r, r->header_in); + } if (rc == NGX_OK) { @@ -1076,17 +1130,13 @@ ngx_http_process_request_line(ngx_event_t *rev) r->request_line.len = r->request_end - r->request_start; r->request_line.data = r->request_start; - r->request_length = r->header_in->pos - r->request_start; + r->request_length = r->header_in->pos - r->parse_start; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http request line: \"%V\"", &r->request_line); - 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; - } + r->method_name.len = r->method_end - r->method_start; + r->method_name.data = r->method_start; if (ngx_http_process_request_uri(r) != NGX_OK) { break; @@ -1153,6 +1203,15 @@ ngx_http_process_request_line(ngx_event_t *rev) break; } + if (rc == NGX_BUSY) { + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + break; + } + if (rc != NGX_AGAIN) { /* there was error while a request line parsing */ @@ -1182,8 +1241,8 @@ ngx_http_process_request_line(ngx_event_t *rev) } if (rv == NGX_DECLINED) { - r->request_line.len = r->header_in->end - r->request_start; - r->request_line.data = r->request_start; + r->request_line.len = r->header_in->end - r->parse_start; + r->request_line.data = r->parse_start; ngx_log_error(NGX_LOG_INFO, c->log, 0, "client sent too long URI"); @@ -1343,7 +1402,7 @@ ngx_http_process_request_headers(ngx_event_t *rev) cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); - rc = NGX_AGAIN; + rc = NGX_OK; for ( ;; ) { @@ -1359,7 +1418,7 @@ ngx_http_process_request_headers(ngx_event_t *rev) } if (rv == NGX_DECLINED) { - p = r->header_name_start; + p = r->parse_start; r->lingering_close = 1; @@ -1379,7 +1438,7 @@ ngx_http_process_request_headers(ngx_event_t *rev) ngx_log_error(NGX_LOG_INFO, c->log, 0, "client sent too long header line: \"%*s...\"", - len, r->header_name_start); + len, r->parse_start); ngx_http_finalize_request(r, NGX_HTTP_REQUEST_HEADER_TOO_LARGE); @@ -1397,21 +1456,32 @@ ngx_http_process_request_headers(ngx_event_t *rev) /* the host header could change the server configuration context */ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - rc = ngx_http_parse_header_line(r, r->header_in, - cscf->underscores_in_headers); + switch (r->http_version) { +#if (NGX_HTTP_V3) + case NGX_HTTP_VERSION_30: + rc = ngx_http_v3_parse_header(r, r->header_in, + cscf->underscores_in_headers); + break; +#endif + + default: /* HTTP/1.x */ + rc = ngx_http_parse_header_line(r, r->header_in, + cscf->underscores_in_headers); + } if (rc == NGX_OK) { - r->request_length += r->header_in->pos - r->header_name_start; + r->request_length += r->header_in->pos - r->parse_start; if (r->invalid_header && cscf->ignore_invalid_headers) { /* there was error while a header line parsing */ ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent invalid header line: \"%*s\"", - r->header_end - r->header_name_start, - r->header_name_start); + "client sent invalid header line: \"%*s: %*s\"", + r->header_name_end - r->header_name_start, + r->header_name_start, + r->header_end - r->header_start, r->header_start); continue; } @@ -1427,11 +1497,17 @@ ngx_http_process_request_headers(ngx_event_t *rev) 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'; + + if (h->key.data[h->key.len]) { + 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'; + + if (h->value.data[h->value.len]) { + h->value.data[h->value.len] = '\0'; + } h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); if (h->lowcase_key == NULL) { @@ -1467,7 +1543,7 @@ ngx_http_process_request_headers(ngx_event_t *rev) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http header done"); - r->request_length += r->header_in->pos - r->header_name_start; + r->request_length += r->header_in->pos - r->parse_start; r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE; @@ -1582,7 +1658,7 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, return NGX_OK; } - old = request_line ? r->request_start : r->header_name_start; + old = r->parse_start; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); @@ -1660,6 +1736,14 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, b->pos = new + (r->header_in->pos - old); b->last = new + (r->header_in->pos - old); + r->parse_start = new; + + r->header_in = b; + + if (r->http_version > NGX_HTTP_VERSION_11) { + return NGX_OK; + } + if (request_line) { r->request_start = new; @@ -1708,8 +1792,6 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, r->header_end = new + (r->header_end - old); } - r->header_in = b; - return NGX_OK; } @@ -1930,13 +2012,46 @@ ngx_http_process_request_header(ngx_http_request_t *r) return NGX_ERROR; } - if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) { + if (r->headers_in.host == NULL && r->http_version == NGX_HTTP_VERSION_11) { 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; } + if (r->headers_in.host == NULL && r->http_version == NGX_HTTP_VERSION_20) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent HTTP/2 request without " + "\":authority\" or \"Host\" header"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + + if (r->http_version == NGX_HTTP_VERSION_30) { + if (r->headers_in.server.len == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent HTTP/3 request without " + "\":authority\" or \"Host\" header"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + + if (r->headers_in.host) { + if (r->headers_in.host->value.len != r->headers_in.server.len + || ngx_memcmp(r->headers_in.host->value.data, + r->headers_in.server.data, + r->headers_in.server.len) + != 0) + { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent HTTP/3 request with different " + "values of \":authority\" and \"Host\" headers"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + } + } + if (r->headers_in.content_length) { r->headers_in.content_length_n = ngx_atoof(r->headers_in.content_length->value.data, @@ -1975,6 +2090,12 @@ ngx_http_process_request_header(ngx_http_request_t *r) } } +#if (NGX_HTTP_V3) + if (r->http_version == NGX_HTTP_VERSION_30) { + r->headers_in.chunked = 1; + } +#endif + if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) { if (r->headers_in.keep_alive) { r->headers_in.keep_alive_n = @@ -2907,6 +3028,19 @@ ngx_http_test_reading(ngx_http_request_t *r) #endif +#if (NGX_HTTP_QUIC) + + if (c->qs) { + if (c->read->error) { + err = 0; + goto closed; + } + + return; + } + +#endif + #if (NGX_HAVE_KQUEUE) if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { @@ -3390,11 +3524,13 @@ ngx_http_set_lingering_close(ngx_http_request_t *r) } } - if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) { - ngx_connection_error(c, ngx_socket_errno, - ngx_shutdown_socket_n " failed"); - ngx_http_close_request(r, 0); - return; + if (c->fd != NGX_INVALID_FILE) { + if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) { + ngx_connection_error(c, ngx_socket_errno, + ngx_shutdown_socket_n " failed"); + ngx_http_close_request(r, 0); + return; + } } if (rev->ready) { @@ -3726,7 +3862,7 @@ ngx_http_close_connection(ngx_connection_t *c) } -static u_char * +u_char * ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len) { u_char *p; @@ -3773,15 +3909,15 @@ ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr, len -= p - buf; buf = p; - if (r->request_line.data == NULL && r->request_start) { - for (p = r->request_start; p < r->header_in->last; p++) { + if (r->request_line.data == NULL && r->parse_start) { + for (p = r->parse_start; p < r->header_in->last; p++) { if (*p == CR || *p == LF) { break; } } - r->request_line.len = p - r->request_start; - r->request_line.data = r->request_start; + r->request_line.len = p - r->parse_start; + r->request_line.data = r->parse_start; } if (r->request_line.len) { |