Chunked response body in HTTP/3.

This commit is contained in:
Roman Arutyunyan 2020-03-27 19:46:54 +03:00
parent 81f7cff632
commit 80a38580bd
3 changed files with 76 additions and 18 deletions

View File

@ -18,7 +18,7 @@ typedef struct {
static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf);
static ngx_chain_t *ngx_http_chunked_create_trailers(ngx_http_request_t *r,
ngx_http_chunked_filter_ctx_t *ctx);
ngx_http_chunked_filter_ctx_t *ctx, size_t size);
static ngx_http_module_t ngx_http_chunked_filter_module_ctx = {
@ -106,6 +106,7 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
u_char *chunk;
off_t size;
size_t n;
ngx_int_t rc;
ngx_buf_t *b;
ngx_chain_t *out, *cl, *tl, **ll;
@ -161,29 +162,50 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
chunk = b->start;
if (chunk == NULL) {
/* the "0000000000000000" is 64-bit hexadecimal string */
chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1);
#if (NGX_HTTP_V3)
if (r->http_version == NGX_HTTP_VERSION_30) {
n = NGX_HTTP_V3_VARLEN_INT_LEN * 2;
} else
#endif
{
/* the "0000000000000000" is 64-bit hexadecimal string */
n = sizeof("0000000000000000" CRLF) - 1;
}
chunk = ngx_palloc(r->pool, n);
if (chunk == NULL) {
return NGX_ERROR;
}
b->start = chunk;
b->end = chunk + sizeof("0000000000000000" CRLF) - 1;
b->end = chunk + n;
}
b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
b->memory = 0;
b->temporary = 1;
b->pos = chunk;
#if (NGX_HTTP_V3)
if (r->http_version == NGX_HTTP_VERSION_30) {
b->last = (u_char *) ngx_http_v3_encode_varlen_int(chunk,
NGX_HTTP_V3_FRAME_DATA);
b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, size);
} else
#endif
{
b->last = ngx_sprintf(chunk, "%xO" CRLF, size);
}
tl->next = out;
out = tl;
}
if (cl->buf->last_buf) {
tl = ngx_http_chunked_create_trailers(r, ctx);
tl = ngx_http_chunked_create_trailers(r, ctx, size);
if (tl == NULL) {
return NGX_ERROR;
}
@ -192,11 +214,12 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
*ll = tl;
if (size == 0) {
tl->buf->pos += 2;
}
} else if (size > 0) {
} else if (size > 0
#if (NGX_HTTP_V3)
&& r->http_version != NGX_HTTP_VERSION_30
#endif
)
{
tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
if (tl == NULL) {
return NGX_ERROR;
@ -227,7 +250,7 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
static ngx_chain_t *
ngx_http_chunked_create_trailers(ngx_http_request_t *r,
ngx_http_chunked_filter_ctx_t *ctx)
ngx_http_chunked_filter_ctx_t *ctx, size_t size)
{
size_t len;
ngx_buf_t *b;
@ -236,6 +259,12 @@ ngx_http_chunked_create_trailers(ngx_http_request_t *r,
ngx_list_part_t *part;
ngx_table_elt_t *header;
#if (NGX_HTTP_V3)
if (r->http_version == NGX_HTTP_VERSION_30) {
return ngx_http_v3_create_trailers(r);
}
#endif
len = 0;
part = &r->headers_out.trailers.part;
@ -288,7 +317,10 @@ ngx_http_chunked_create_trailers(ngx_http_request_t *r,
b->last = b->pos;
if (size > 0) {
*b->last++ = CR; *b->last++ = LF;
}
*b->last++ = '0';
*b->last++ = CR; *b->last++ = LF;

View File

@ -69,6 +69,7 @@ typedef struct {
ngx_int_t ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b);
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);
uintptr_t ngx_http_v3_encode_varlen_int(u_char *p, uint64_t value);
uintptr_t ngx_http_v3_encode_prefix_int(u_char *p, uint64_t value,

View File

@ -258,11 +258,6 @@ ngx_http_v3_create_header(ngx_http_request_t *r)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 create header");
/* XXX support chunked body in the chunked filter */
if (!r->header_only && r->headers_out.content_length_n == -1) {
return NULL;
}
len = 2;
if (r->headers_out.status == NGX_HTTP_OK) {
@ -578,3 +573,33 @@ ngx_http_v3_create_header(ngx_http_request_t *r)
return hl;
}
ngx_chain_t *
ngx_http_v3_create_trailers(ngx_http_request_t *r)
{
ngx_buf_t *b;
ngx_chain_t *cl;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http3 create trailers");
/* XXX */
b = ngx_calloc_buf(r->pool);
if (b == NULL) {
return NULL;
}
b->last_buf = 1;
cl = ngx_alloc_chain_link(r->pool);
if (cl == NULL) {
return NULL;
}
cl->buf = b;
cl->next = NULL;
return cl;
}