mirror of
https://github.com/nginx/nginx.git
synced 2025-02-25 18:55:26 -06:00
HTTP/3: split header parser in two functions.
The first one parses pseudo-headers and is analagous to the request line parser in HTTP/1. The second one parses regular headers and is analogous to the header parser in HTTP/1. Additionally, error handling of client passing malformed uri is now fixed.
This commit is contained in:
parent
d69f678e9c
commit
6abb50658f
@ -1164,7 +1164,7 @@ ngx_http_process_request_line(ngx_event_t *rev)
|
|||||||
switch (r->http_version) {
|
switch (r->http_version) {
|
||||||
#if (NGX_HTTP_V3)
|
#if (NGX_HTTP_V3)
|
||||||
case NGX_HTTP_VERSION_30:
|
case NGX_HTTP_VERSION_30:
|
||||||
rc = ngx_http_v3_parse_header(r, r->header_in);
|
rc = ngx_http_v3_parse_request(r, r->header_in);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ typedef struct {
|
|||||||
} ngx_http_v3_header_t;
|
} ngx_http_v3_header_t;
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t ngx_http_v3_parse_request(ngx_http_request_t *r, ngx_buf_t *b);
|
||||||
ngx_int_t ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b);
|
ngx_int_t ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b);
|
||||||
ngx_int_t ngx_http_v3_parse_request_body(ngx_http_request_t *r, ngx_buf_t *b,
|
ngx_int_t ngx_http_v3_parse_request_body(ngx_http_request_t *r, ngx_buf_t *b,
|
||||||
ngx_http_chunked_t *ctx);
|
ngx_http_chunked_t *ctx);
|
||||||
|
@ -38,21 +38,14 @@ struct {
|
|||||||
|
|
||||||
|
|
||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b)
|
ngx_http_v3_parse_request(ngx_http_request_t *r, ngx_buf_t *b)
|
||||||
{
|
{
|
||||||
size_t n;
|
size_t len;
|
||||||
u_char *p;
|
u_char *p;
|
||||||
ngx_int_t rc;
|
ngx_int_t rc, n;
|
||||||
ngx_str_t *name, *value;
|
ngx_str_t *name, *value;
|
||||||
ngx_connection_t *c;
|
ngx_connection_t *c;
|
||||||
ngx_http_v3_parse_headers_t *st;
|
ngx_http_v3_parse_headers_t *st;
|
||||||
enum {
|
|
||||||
sw_start = 0,
|
|
||||||
sw_prev,
|
|
||||||
sw_headers,
|
|
||||||
sw_last,
|
|
||||||
sw_done
|
|
||||||
};
|
|
||||||
|
|
||||||
c = r->connection;
|
c = r->connection;
|
||||||
st = r->h3_parse;
|
st = r->h3_parse;
|
||||||
@ -68,23 +61,6 @@ ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b)
|
|||||||
r->h3_parse = st;
|
r->h3_parse = st;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (r->state) {
|
|
||||||
|
|
||||||
case sw_prev:
|
|
||||||
r->state = sw_headers;
|
|
||||||
return NGX_OK;
|
|
||||||
|
|
||||||
case sw_done:
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
case sw_last:
|
|
||||||
r->state = sw_done;
|
|
||||||
return NGX_OK;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (b->pos < b->last) {
|
while (b->pos < b->last) {
|
||||||
rc = ngx_http_v3_parse_headers(c, st, *b->pos++);
|
rc = ngx_http_v3_parse_headers(c, st, *b->pos++);
|
||||||
|
|
||||||
@ -99,52 +75,34 @@ ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b)
|
|||||||
name = &st->header_rep.header.name;
|
name = &st->header_rep.header.name;
|
||||||
value = &st->header_rep.header.value;
|
value = &st->header_rep.header.value;
|
||||||
|
|
||||||
if (r->state == sw_start) {
|
n = ngx_http_v3_process_pseudo_header(r, name, value);
|
||||||
|
|
||||||
if (ngx_http_v3_process_pseudo_header(r, name, value) == NGX_OK) {
|
if (n == NGX_ERROR) {
|
||||||
if (rc == NGX_OK) {
|
goto failed;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
r->state = sw_done;
|
|
||||||
|
|
||||||
} else if (rc == NGX_OK) {
|
|
||||||
r->state = sw_prev;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
r->state = sw_last;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = (r->method_end - r->method_start) + 1
|
|
||||||
+ (r->uri_end - r->uri_start) + 1
|
|
||||||
+ sizeof("HTTP/3") - 1;
|
|
||||||
|
|
||||||
p = ngx_pnalloc(c->pool, n);
|
|
||||||
if (p == NULL) {
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
r->request_start = p;
|
|
||||||
|
|
||||||
p = ngx_cpymem(p, r->method_start, r->method_end - r->method_start);
|
|
||||||
*p++ = ' ';
|
|
||||||
p = ngx_cpymem(p, r->uri_start, r->uri_end - r->uri_start);
|
|
||||||
*p++ = ' ';
|
|
||||||
p = ngx_cpymem(p, "HTTP/3", sizeof("HTTP/3") - 1);
|
|
||||||
|
|
||||||
r->request_end = p;
|
|
||||||
|
|
||||||
} else if (rc == NGX_DONE) {
|
|
||||||
r->state = sw_done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r->header_name_start = name->data;
|
if (n == NGX_OK && rc == NGX_OK) {
|
||||||
r->header_name_end = name->data + name->len;
|
continue;
|
||||||
r->header_start = value->data;
|
}
|
||||||
r->header_end = value->data + value->len;
|
|
||||||
r->header_hash = ngx_hash_key(name->data, name->len);
|
|
||||||
|
|
||||||
/* XXX r->lowcase_index = i; */
|
len = (r->method_end - r->method_start) + 1
|
||||||
|
+ (r->uri_end - r->uri_start) + 1
|
||||||
|
+ sizeof("HTTP/3") - 1;
|
||||||
|
|
||||||
|
p = ngx_pnalloc(c->pool, len);
|
||||||
|
if (p == NULL) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->request_start = p;
|
||||||
|
|
||||||
|
p = ngx_cpymem(p, r->method_start, r->method_end - r->method_start);
|
||||||
|
*p++ = ' ';
|
||||||
|
p = ngx_cpymem(p, r->uri_start, r->uri_end - r->uri_start);
|
||||||
|
*p++ = ' ';
|
||||||
|
p = ngx_cpymem(p, "HTTP/3", sizeof("HTTP/3") - 1);
|
||||||
|
|
||||||
|
r->request_end = p;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@ -153,14 +111,64 @@ ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b)
|
|||||||
|
|
||||||
failed:
|
failed:
|
||||||
|
|
||||||
return r->state == sw_start ? NGX_HTTP_PARSE_INVALID_REQUEST
|
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||||
: NGX_HTTP_PARSE_INVALID_HEADER;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_str_t *name, *value;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_http_v3_parse_headers_t *st;
|
||||||
|
|
||||||
|
c = r->connection;
|
||||||
|
st = r->h3_parse;
|
||||||
|
|
||||||
|
if (st->state == 0) {
|
||||||
|
if (r->header_name_start == NULL) {
|
||||||
|
name = &st->header_rep.header.name;
|
||||||
|
|
||||||
|
if (name->len && name->data[0] != ':') {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||||
|
"http3 parse header done");
|
||||||
|
|
||||||
|
return NGX_HTTP_PARSE_HEADER_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (b->pos < b->last) {
|
||||||
|
rc = ngx_http_v3_parse_headers(c, st, *b->pos++);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
return NGX_HTTP_PARSE_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc != NGX_AGAIN) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_AGAIN;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header done");
|
name = &st->header_rep.header.name;
|
||||||
|
value = &st->header_rep.header.value;
|
||||||
|
|
||||||
return NGX_HTTP_PARSE_HEADER_DONE;
|
r->header_name_start = name->data;
|
||||||
|
r->header_name_end = name->data + name->len;
|
||||||
|
r->header_start = value->data;
|
||||||
|
r->header_end = value->data + value->len;
|
||||||
|
r->header_hash = ngx_hash_key(name->data, name->len);
|
||||||
|
|
||||||
|
/* XXX r->lowcase_index = i; */
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user