mirror of
https://github.com/nginx/nginx.git
synced 2026-05-13 09:36:42 +00:00
Merge 342b52e9e8 into 319b4ea63f
This commit is contained in:
commit
a5a2b5dacd
4 changed files with 261 additions and 43 deletions
|
|
@ -427,6 +427,7 @@ struct ngx_http_request_s {
|
|||
ngx_str_t method_name;
|
||||
ngx_str_t http_protocol;
|
||||
ngx_str_t schema;
|
||||
ngx_str_t connect_protocol;
|
||||
|
||||
ngx_chain_t *out;
|
||||
ngx_http_request_t *main;
|
||||
|
|
|
|||
|
|
@ -79,7 +79,17 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
|
|||
|
||||
r->request_body = rb;
|
||||
|
||||
if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) {
|
||||
if (r->headers_in.content_length_n < 0
|
||||
&& !r->headers_in.chunked
|
||||
#if (NGX_HTTP_V2)
|
||||
&& !(r->stream && r->method == NGX_HTTP_CONNECT)
|
||||
#endif
|
||||
#if (NGX_HTTP_V3)
|
||||
&& !(r->http_version == NGX_HTTP_VERSION_30
|
||||
&& r->method == NGX_HTTP_CONNECT)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
r->request_body_no_buffering = 0;
|
||||
post_handler(r);
|
||||
return NGX_OK;
|
||||
|
|
|
|||
|
|
@ -154,6 +154,8 @@ static ngx_int_t ngx_http_v2_parse_scheme(ngx_http_request_t *r,
|
|||
ngx_str_t *value);
|
||||
static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r,
|
||||
ngx_str_t *value);
|
||||
static ngx_int_t ngx_http_v2_parse_protocol(ngx_http_request_t *r,
|
||||
ngx_str_t *value);
|
||||
static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r);
|
||||
static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r,
|
||||
ngx_http_v2_header_t *header);
|
||||
|
|
@ -3325,6 +3327,16 @@ ngx_http_v2_pseudo_header(ngx_http_request_t *r, ngx_http_v2_header_t *header)
|
|||
|
||||
break;
|
||||
|
||||
case 8:
|
||||
if (ngx_memcmp(header->name.data, "protocol",
|
||||
sizeof("protocol") - 1)
|
||||
== 0)
|
||||
{
|
||||
return ngx_http_v2_parse_protocol(r, &header->value);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 9:
|
||||
if (ngx_memcmp(header->name.data, "authority", sizeof("authority") - 1)
|
||||
== 0)
|
||||
|
|
@ -3567,37 +3579,133 @@ ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value)
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_v2_parse_protocol(ngx_http_request_t *r, ngx_str_t *value)
|
||||
{
|
||||
if (r->connect_protocol.len) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent duplicate :protocol header");
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
if (value->len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent empty :protocol header");
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
r->connect_protocol = *value;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_v2_construct_request_line(ngx_http_request_t *r)
|
||||
{
|
||||
u_char *p;
|
||||
size_t len;
|
||||
u_char *p;
|
||||
ngx_uint_t classic_connect;
|
||||
ngx_http_core_srv_conf_t *cscf;
|
||||
|
||||
static const u_char ending[] = " HTTP/2.0";
|
||||
|
||||
if (r->method_name.len == 0
|
||||
|| r->schema.len == 0
|
||||
|| r->unparsed_uri.len == 0)
|
||||
{
|
||||
if (r->method_name.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no :method header");
|
||||
|
||||
} else if (r->schema.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no :scheme header");
|
||||
|
||||
} else {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no :path header");
|
||||
}
|
||||
|
||||
if (r->method_name.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no :method header");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->request_line.len = r->method_name.len + 1
|
||||
+ r->unparsed_uri.len
|
||||
+ sizeof(ending) - 1;
|
||||
if (r->method == NGX_HTTP_CONNECT) {
|
||||
goto method_connect;
|
||||
}
|
||||
|
||||
if (r->connect_protocol.len) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent :protocol header with non-CONNECT method");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
classic_connect = 0;
|
||||
|
||||
if (r->schema.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no :scheme header");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r->unparsed_uri.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no :path header");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
len = r->unparsed_uri.len;
|
||||
|
||||
goto construct_request_line;
|
||||
|
||||
method_connect:
|
||||
|
||||
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
||||
|
||||
if (!cscf->allow_connect) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent CONNECT method");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r->schema.len == 0 && r->unparsed_uri.len == 0
|
||||
&& r->connect_protocol.len == 0)
|
||||
{
|
||||
classic_connect = 1;
|
||||
|
||||
if (r->headers_in.server.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no :authority header");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
len = r->headers_in.server.len;
|
||||
|
||||
goto construct_request_line;
|
||||
}
|
||||
|
||||
classic_connect = 0;
|
||||
|
||||
if (r->schema.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no :scheme header");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r->connect_protocol.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent extended CONNECT without :protocol header");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r->unparsed_uri.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no :path header");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
len = r->unparsed_uri.len;
|
||||
|
||||
construct_request_line:
|
||||
|
||||
r->request_line.len = r->method_name.len + 1 + len + sizeof(ending) - 1;
|
||||
|
||||
p = ngx_pnalloc(r->pool, r->request_line.len + 1);
|
||||
if (p == NULL) {
|
||||
|
|
@ -3611,7 +3719,18 @@ ngx_http_v2_construct_request_line(ngx_http_request_t *r)
|
|||
|
||||
*p++ = ' ';
|
||||
|
||||
p = ngx_cpymem(p, r->unparsed_uri.data, r->unparsed_uri.len);
|
||||
if (classic_connect) {
|
||||
p = ngx_cpymem(p, r->headers_in.server.data, r->headers_in.server.len);
|
||||
|
||||
r->uri_start = (u_char *) "/";
|
||||
r->uri_end = r->uri_start + 1;
|
||||
ngx_str_set(&r->uri, "/");
|
||||
ngx_str_set(&r->unparsed_uri, "/");
|
||||
r->valid_unparsed_uri = 1;
|
||||
|
||||
} else {
|
||||
p = ngx_cpymem(p, r->unparsed_uri.data, r->unparsed_uri.len);
|
||||
}
|
||||
|
||||
ngx_memcpy(p, ending, sizeof(ending));
|
||||
|
||||
|
|
@ -3920,12 +4039,6 @@ ngx_http_v2_run_request(ngx_http_request_t *r)
|
|||
r->headers_in.chunked = 1;
|
||||
}
|
||||
|
||||
if (r->method == NGX_HTTP_CONNECT) {
|
||||
ngx_log_error(NGX_LOG_INFO, fc->log, 0, "client sent CONNECT method");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (r->method == NGX_HTTP_TRACE) {
|
||||
ngx_log_error(NGX_LOG_INFO, fc->log, 0, "client sent TRACE method");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
||||
|
|
|
|||
|
|
@ -896,6 +896,27 @@ ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name,
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (name->len == 9 && ngx_strncmp(name->data, ":protocol", 9) == 0) {
|
||||
|
||||
if (r->connect_protocol.len) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent duplicate \":protocol\" header");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (value->len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent empty \":protocol\" header");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
r->connect_protocol = *value;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http3 protocol \"%V\"", value);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent unknown pseudo-header \"%V\"", name);
|
||||
|
||||
|
|
@ -909,10 +930,12 @@ failed:
|
|||
static ngx_int_t
|
||||
ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r)
|
||||
{
|
||||
size_t len;
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t host;
|
||||
size_t len, target_len;
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t classic_connect;
|
||||
ngx_str_t host;
|
||||
ngx_http_core_srv_conf_t *cscf;
|
||||
in_port_t port;
|
||||
|
||||
if (r->request_line.len) {
|
||||
|
|
@ -925,6 +948,19 @@ ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r)
|
|||
goto failed;
|
||||
}
|
||||
|
||||
if (r->method == NGX_HTTP_CONNECT) {
|
||||
goto method_connect;
|
||||
}
|
||||
|
||||
if (r->connect_protocol.len) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent \":protocol\" header with non-CONNECT "
|
||||
"method");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
classic_connect = 0;
|
||||
|
||||
if (r->schema.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no \":scheme\" header");
|
||||
|
|
@ -937,9 +973,66 @@ ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r)
|
|||
goto failed;
|
||||
}
|
||||
|
||||
len = r->method_name.len + 1
|
||||
+ (r->uri_end - r->uri_start) + 1
|
||||
+ sizeof("HTTP/3.0") - 1;
|
||||
target_len = (size_t) (r->uri_end - r->uri_start);
|
||||
|
||||
goto construct_request_line;
|
||||
|
||||
method_connect:
|
||||
|
||||
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
||||
|
||||
if (!cscf->allow_connect) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent CONNECT method");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r->schema.len == 0 && r->uri_start == NULL
|
||||
&& r->connect_protocol.len == 0)
|
||||
{
|
||||
classic_connect = 1;
|
||||
|
||||
if (r->host_start == NULL) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no \":authority\" header");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
r->uri_start = (u_char *) "/";
|
||||
r->uri_end = r->uri_start + 1;
|
||||
|
||||
target_len = (size_t) (r->host_end - r->host_start);
|
||||
|
||||
goto construct_request_line;
|
||||
}
|
||||
|
||||
classic_connect = 0;
|
||||
|
||||
if (r->schema.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no \":scheme\" header");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (r->connect_protocol.len == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent extended CONNECT without "
|
||||
"\":protocol\" header");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (r->uri_start == NULL) {
|
||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||
"client sent no \":path\" header");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
target_len = (size_t) (r->uri_end - r->uri_start);
|
||||
|
||||
construct_request_line:
|
||||
|
||||
len = r->method_name.len + 1 + target_len + 1 + sizeof("HTTP/3.0") - 1;
|
||||
|
||||
p = ngx_pnalloc(r->pool, len);
|
||||
if (p == NULL) {
|
||||
|
|
@ -951,7 +1044,14 @@ ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r)
|
|||
|
||||
p = ngx_cpymem(p, r->method_name.data, r->method_name.len);
|
||||
*p++ = ' ';
|
||||
p = ngx_cpymem(p, r->uri_start, r->uri_end - r->uri_start);
|
||||
|
||||
if (classic_connect) {
|
||||
p = ngx_cpymem(p, r->host_start, target_len);
|
||||
|
||||
} else {
|
||||
p = ngx_cpymem(p, r->uri_start, target_len);
|
||||
}
|
||||
|
||||
*p++ = ' ';
|
||||
p = ngx_cpymem(p, "HTTP/3.0", sizeof("HTTP/3.0") - 1);
|
||||
|
||||
|
|
@ -1136,12 +1236,6 @@ ngx_http_v3_process_request_header(ngx_http_request_t *r)
|
|||
}
|
||||
}
|
||||
|
||||
if (r->method == NGX_HTTP_CONNECT) {
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0, "client sent CONNECT method");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r->method == NGX_HTTP_TRACE) {
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0, "client sent TRACE method");
|
||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue