mirror of
https://github.com/nginx/nginx.git
synced 2025-02-25 18:55:26 -06:00
Parsing HTTP/3 request body.
This commit is contained in:
parent
84a7835015
commit
fa1e1beadc
@ -63,6 +63,9 @@ struct ngx_http_chunked_s {
|
|||||||
ngx_uint_t state;
|
ngx_uint_t state;
|
||||||
off_t size;
|
off_t size;
|
||||||
off_t length;
|
off_t length;
|
||||||
|
#if (NGX_HTTP_V3)
|
||||||
|
void *h3_parse;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2185,6 +2185,12 @@ ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b,
|
|||||||
sw_trailer_header_almost_done
|
sw_trailer_header_almost_done
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
|
#if (NGX_HTTP_V3)
|
||||||
|
if (r->http_version == NGX_HTTP_VERSION_30) {
|
||||||
|
return ngx_http_v3_parse_request_body(r, b, ctx);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
state = ctx->state;
|
state = ctx->state;
|
||||||
|
|
||||||
if (state == sw_chunk_data && ctx->size == 0) {
|
if (state == sw_chunk_data && ctx->size == 0) {
|
||||||
@ -2371,6 +2377,11 @@ ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (b->last_buf) {
|
||||||
|
/* XXX client prematurely closed connection */
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
data:
|
data:
|
||||||
|
|
||||||
ctx->state = state;
|
ctx->state = state;
|
||||||
|
@ -709,6 +709,7 @@ ngx_http_alloc_request(ngx_connection_t *c)
|
|||||||
#if (NGX_HTTP_V3)
|
#if (NGX_HTTP_V3)
|
||||||
if (hc->quic) {
|
if (hc->quic) {
|
||||||
r->http_version = NGX_HTTP_VERSION_30;
|
r->http_version = NGX_HTTP_VERSION_30;
|
||||||
|
r->headers_in.chunked = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -343,11 +343,10 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
rb->buf->last_buf = 1;
|
||||||
"client prematurely closed connection");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == 0 || n == NGX_ERROR) {
|
if (n == NGX_ERROR) {
|
||||||
c->error = 1;
|
c->error = 1;
|
||||||
return NGX_HTTP_BAD_REQUEST;
|
return NGX_HTTP_BAD_REQUEST;
|
||||||
}
|
}
|
||||||
@ -355,7 +354,7 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|||||||
rb->buf->last += n;
|
rb->buf->last += n;
|
||||||
r->request_length += n;
|
r->request_length += n;
|
||||||
|
|
||||||
if (n == rest) {
|
if (n == rest || n == 0) {
|
||||||
/* pass buffer to request body filter chain */
|
/* pass buffer to request body filter chain */
|
||||||
|
|
||||||
out.buf = rb->buf;
|
out.buf = rb->buf;
|
||||||
@ -805,11 +804,7 @@ ngx_http_test_expect(ngx_http_request_t *r)
|
|||||||
|
|
||||||
if (r->expect_tested
|
if (r->expect_tested
|
||||||
|| r->headers_in.expect == NULL
|
|| r->headers_in.expect == NULL
|
||||||
|| r->http_version < NGX_HTTP_VERSION_11
|
|| r->http_version != NGX_HTTP_VERSION_11)
|
||||||
#if (NGX_HTTP_V2)
|
|
||||||
|| r->stream != NULL
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@ -914,6 +909,11 @@ ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
b->last_buf = 1;
|
b->last_buf = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cl->buf->last_buf && rb->rest > 0) {
|
||||||
|
/* XXX client prematurely closed connection */
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
*ll = tl;
|
*ll = tl;
|
||||||
ll = &tl->next;
|
ll = &tl->next;
|
||||||
}
|
}
|
||||||
@ -950,7 +950,16 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
}
|
}
|
||||||
|
|
||||||
r->headers_in.content_length_n = 0;
|
r->headers_in.content_length_n = 0;
|
||||||
rb->rest = 3;
|
|
||||||
|
#if (NGX_HTTP_V3)
|
||||||
|
if (r->http_version == NGX_HTTP_VERSION_30) {
|
||||||
|
rb->rest = 1;
|
||||||
|
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
rb->rest = 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out = NULL;
|
out = NULL;
|
||||||
|
@ -68,6 +68,8 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
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_http_chunked_t *ctx);
|
||||||
ngx_chain_t *ngx_http_v3_create_header(ngx_http_request_t *r);
|
ngx_chain_t *ngx_http_v3_create_header(ngx_http_request_t *r);
|
||||||
ngx_chain_t *ngx_http_v3_create_trailers(ngx_http_request_t *r);
|
ngx_chain_t *ngx_http_v3_create_trailers(ngx_http_request_t *r);
|
||||||
|
|
||||||
|
@ -1421,3 +1421,61 @@ done:
|
|||||||
st->state = sw_start;
|
st->state = sw_start;
|
||||||
return NGX_DONE;
|
return NGX_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_http_v3_parse_data(ngx_connection_t *c, ngx_http_v3_parse_data_t *st,
|
||||||
|
u_char ch)
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
sw_start = 0,
|
||||||
|
sw_type,
|
||||||
|
sw_length
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (st->state) {
|
||||||
|
|
||||||
|
case sw_start:
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse data");
|
||||||
|
|
||||||
|
st->state = sw_type;
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case sw_type:
|
||||||
|
|
||||||
|
if (ngx_http_v3_parse_varlen_int(c, &st->vlint, ch) != NGX_DONE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st->vlint.value != NGX_HTTP_V3_FRAME_DATA) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
st->state = sw_length;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sw_length:
|
||||||
|
|
||||||
|
if (ngx_http_v3_parse_varlen_int(c, &st->vlint, ch) != NGX_DONE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
st->length = st->vlint.value;
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||||
|
"http3 parse data frame len:%ui", st->length);
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_AGAIN;
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse data done");
|
||||||
|
|
||||||
|
st->state = sw_start;
|
||||||
|
return NGX_DONE;
|
||||||
|
}
|
||||||
|
@ -105,6 +105,13 @@ typedef struct {
|
|||||||
} ngx_http_v3_parse_control_t;
|
} ngx_http_v3_parse_control_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_uint_t state;
|
||||||
|
ngx_uint_t length;
|
||||||
|
ngx_http_v3_parse_varlen_int_t vlint;
|
||||||
|
} ngx_http_v3_parse_data_t;
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t ngx_http_v3_parse_varlen_int(ngx_connection_t *c,
|
ngx_int_t ngx_http_v3_parse_varlen_int(ngx_connection_t *c,
|
||||||
ngx_http_v3_parse_varlen_int_t *st, u_char ch);
|
ngx_http_v3_parse_varlen_int_t *st, u_char ch);
|
||||||
ngx_int_t ngx_http_v3_parse_prefix_int(ngx_connection_t *c,
|
ngx_int_t ngx_http_v3_parse_prefix_int(ngx_connection_t *c,
|
||||||
@ -141,5 +148,8 @@ ngx_int_t ngx_http_v3_parse_header_iwnr(ngx_connection_t *c,
|
|||||||
|
|
||||||
ngx_int_t ngx_http_v3_parse_decoder(ngx_connection_t *c, void *data, u_char ch);
|
ngx_int_t ngx_http_v3_parse_decoder(ngx_connection_t *c, void *data, u_char ch);
|
||||||
|
|
||||||
|
ngx_int_t ngx_http_v3_parse_data(ngx_connection_t *c,
|
||||||
|
ngx_http_v3_parse_data_t *st, u_char ch);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _NGX_HTTP_V3_PARSE_H_INCLUDED_ */
|
#endif /* _NGX_HTTP_V3_PARSE_H_INCLUDED_ */
|
||||||
|
@ -241,6 +241,69 @@ ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_http_v3_parse_request_body(ngx_http_request_t *r, ngx_buf_t *b,
|
||||||
|
ngx_http_chunked_t *ctx)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_http_v3_parse_data_t *st;
|
||||||
|
|
||||||
|
c = r->connection;
|
||||||
|
st = ctx->h3_parse;
|
||||||
|
|
||||||
|
if (st == NULL) {
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||||
|
"http3 parse request body");
|
||||||
|
|
||||||
|
st = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_parse_data_t));
|
||||||
|
if (st == NULL) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->h3_parse = st;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->size) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (b->pos < b->last) {
|
||||||
|
rc = ngx_http_v3_parse_data(c, st, *b->pos++);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_AGAIN) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rc == NGX_DONE */
|
||||||
|
|
||||||
|
ctx->size = st->length;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!b->last_buf) {
|
||||||
|
ctx->length = 1;
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st->state) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header done");
|
||||||
|
|
||||||
|
return NGX_DONE;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ngx_chain_t *
|
ngx_chain_t *
|
||||||
ngx_http_v3_create_header(ngx_http_request_t *r)
|
ngx_http_v3_create_header(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user