comparison src/http/modules/ngx_http_chunked_filter_module.c @ 8292:46e3542d51b3 quic

Chunked response body in HTTP/3.
author Roman Arutyunyan <arut@nginx.com>
date Fri, 27 Mar 2020 19:46:54 +0300
parents 1b068a4e82d8
children ef83990f0e25
comparison
equal deleted inserted replaced
8291:4feae8bc0ca9 8292:46e3542d51b3
16 } ngx_http_chunked_filter_ctx_t; 16 } ngx_http_chunked_filter_ctx_t;
17 17
18 18
19 static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf); 19 static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf);
20 static ngx_chain_t *ngx_http_chunked_create_trailers(ngx_http_request_t *r, 20 static ngx_chain_t *ngx_http_chunked_create_trailers(ngx_http_request_t *r,
21 ngx_http_chunked_filter_ctx_t *ctx); 21 ngx_http_chunked_filter_ctx_t *ctx, size_t size);
22 22
23 23
24 static ngx_http_module_t ngx_http_chunked_filter_module_ctx = { 24 static ngx_http_module_t ngx_http_chunked_filter_module_ctx = {
25 NULL, /* preconfiguration */ 25 NULL, /* preconfiguration */
26 ngx_http_chunked_filter_init, /* postconfiguration */ 26 ngx_http_chunked_filter_init, /* postconfiguration */
104 static ngx_int_t 104 static ngx_int_t
105 ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) 105 ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
106 { 106 {
107 u_char *chunk; 107 u_char *chunk;
108 off_t size; 108 off_t size;
109 size_t n;
109 ngx_int_t rc; 110 ngx_int_t rc;
110 ngx_buf_t *b; 111 ngx_buf_t *b;
111 ngx_chain_t *out, *cl, *tl, **ll; 112 ngx_chain_t *out, *cl, *tl, **ll;
112 ngx_http_chunked_filter_ctx_t *ctx; 113 ngx_http_chunked_filter_ctx_t *ctx;
113 114
159 160
160 b = tl->buf; 161 b = tl->buf;
161 chunk = b->start; 162 chunk = b->start;
162 163
163 if (chunk == NULL) { 164 if (chunk == NULL) {
164 /* the "0000000000000000" is 64-bit hexadecimal string */ 165
165 166 #if (NGX_HTTP_V3)
166 chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1); 167 if (r->http_version == NGX_HTTP_VERSION_30) {
168 n = NGX_HTTP_V3_VARLEN_INT_LEN * 2;
169
170 } else
171 #endif
172 {
173 /* the "0000000000000000" is 64-bit hexadecimal string */
174 n = sizeof("0000000000000000" CRLF) - 1;
175 }
176
177 chunk = ngx_palloc(r->pool, n);
167 if (chunk == NULL) { 178 if (chunk == NULL) {
168 return NGX_ERROR; 179 return NGX_ERROR;
169 } 180 }
170 181
171 b->start = chunk; 182 b->start = chunk;
172 b->end = chunk + sizeof("0000000000000000" CRLF) - 1; 183 b->end = chunk + n;
173 } 184 }
174 185
175 b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module; 186 b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
176 b->memory = 0; 187 b->memory = 0;
177 b->temporary = 1; 188 b->temporary = 1;
178 b->pos = chunk; 189 b->pos = chunk;
179 b->last = ngx_sprintf(chunk, "%xO" CRLF, size); 190
191 #if (NGX_HTTP_V3)
192 if (r->http_version == NGX_HTTP_VERSION_30) {
193 b->last = (u_char *) ngx_http_v3_encode_varlen_int(chunk,
194 NGX_HTTP_V3_FRAME_DATA);
195 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, size);
196
197 } else
198 #endif
199 {
200 b->last = ngx_sprintf(chunk, "%xO" CRLF, size);
201 }
180 202
181 tl->next = out; 203 tl->next = out;
182 out = tl; 204 out = tl;
183 } 205 }
184 206
185 if (cl->buf->last_buf) { 207 if (cl->buf->last_buf) {
186 tl = ngx_http_chunked_create_trailers(r, ctx); 208 tl = ngx_http_chunked_create_trailers(r, ctx, size);
187 if (tl == NULL) { 209 if (tl == NULL) {
188 return NGX_ERROR; 210 return NGX_ERROR;
189 } 211 }
190 212
191 cl->buf->last_buf = 0; 213 cl->buf->last_buf = 0;
192 214
193 *ll = tl; 215 *ll = tl;
194 216
195 if (size == 0) { 217 } else if (size > 0
196 tl->buf->pos += 2; 218 #if (NGX_HTTP_V3)
197 } 219 && r->http_version != NGX_HTTP_VERSION_30
198 220 #endif
199 } else if (size > 0) { 221 )
222 {
200 tl = ngx_chain_get_free_buf(r->pool, &ctx->free); 223 tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
201 if (tl == NULL) { 224 if (tl == NULL) {
202 return NGX_ERROR; 225 return NGX_ERROR;
203 } 226 }
204 227
225 } 248 }
226 249
227 250
228 static ngx_chain_t * 251 static ngx_chain_t *
229 ngx_http_chunked_create_trailers(ngx_http_request_t *r, 252 ngx_http_chunked_create_trailers(ngx_http_request_t *r,
230 ngx_http_chunked_filter_ctx_t *ctx) 253 ngx_http_chunked_filter_ctx_t *ctx, size_t size)
231 { 254 {
232 size_t len; 255 size_t len;
233 ngx_buf_t *b; 256 ngx_buf_t *b;
234 ngx_uint_t i; 257 ngx_uint_t i;
235 ngx_chain_t *cl; 258 ngx_chain_t *cl;
236 ngx_list_part_t *part; 259 ngx_list_part_t *part;
237 ngx_table_elt_t *header; 260 ngx_table_elt_t *header;
238 261
262 #if (NGX_HTTP_V3)
263 if (r->http_version == NGX_HTTP_VERSION_30) {
264 return ngx_http_v3_create_trailers(r);
265 }
266 #endif
267
239 len = 0; 268 len = 0;
240 269
241 part = &r->headers_out.trailers.part; 270 part = &r->headers_out.trailers.part;
242 header = part->elts; 271 header = part->elts;
243 272
286 return NULL; 315 return NULL;
287 } 316 }
288 317
289 b->last = b->pos; 318 b->last = b->pos;
290 319
291 *b->last++ = CR; *b->last++ = LF; 320 if (size > 0) {
321 *b->last++ = CR; *b->last++ = LF;
322 }
323
292 *b->last++ = '0'; 324 *b->last++ = '0';
293 *b->last++ = CR; *b->last++ = LF; 325 *b->last++ = CR; *b->last++ = LF;
294 326
295 part = &r->headers_out.trailers.part; 327 part = &r->headers_out.trailers.part;
296 header = part->elts; 328 header = part->elts;