comparison src/http/modules/ngx_http_chunked_filter_module.c @ 8635:ef83990f0e25 quic

Fixed generating chunked response after 46e3542d51b3. If trailers were missing and a chain carrying the last_buf flag had no data in it, then last HTTP/1 chunk was broken. The problem was introduced while implementing HTTP/3 response body generation. The change fixes the issue and reduces diff to the mainline nginx.
author Roman Arutyunyan <arut@nginx.com>
date Tue, 10 Nov 2020 20:42:45 +0000
parents 46e3542d51b3
children b80d9179ba2a
comparison
equal deleted inserted replaced
8634:831d1960826f 8635:ef83990f0e25
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, size_t size); 21 ngx_http_chunked_filter_ctx_t *ctx);
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 */
202 202
203 tl->next = out; 203 tl->next = out;
204 out = tl; 204 out = tl;
205 } 205 }
206 206
207 #if (NGX_HTTP_V3)
208 if (r->http_version == NGX_HTTP_VERSION_30) {
209
210 if (cl->buf->last_buf) {
211 tl = ngx_http_v3_create_trailers(r);
212 if (tl == NULL) {
213 return NGX_ERROR;
214 }
215
216 cl->buf->last_buf = 0;
217
218 *ll = tl;
219 }
220
221 } else
222 #endif
223
207 if (cl->buf->last_buf) { 224 if (cl->buf->last_buf) {
208 tl = ngx_http_chunked_create_trailers(r, ctx, size); 225 tl = ngx_http_chunked_create_trailers(r, ctx);
209 if (tl == NULL) { 226 if (tl == NULL) {
210 return NGX_ERROR; 227 return NGX_ERROR;
211 } 228 }
212 229
213 cl->buf->last_buf = 0; 230 cl->buf->last_buf = 0;
214 231
215 *ll = tl; 232 *ll = tl;
216 233
217 } else if (size > 0 234 if (size == 0) {
218 #if (NGX_HTTP_V3) 235 tl->buf->pos += 2;
219 && r->http_version != NGX_HTTP_VERSION_30 236 }
220 #endif 237
221 ) 238 } else if (size > 0) {
222 {
223 tl = ngx_chain_get_free_buf(r->pool, &ctx->free); 239 tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
224 if (tl == NULL) { 240 if (tl == NULL) {
225 return NGX_ERROR; 241 return NGX_ERROR;
226 } 242 }
227 243
248 } 264 }
249 265
250 266
251 static ngx_chain_t * 267 static ngx_chain_t *
252 ngx_http_chunked_create_trailers(ngx_http_request_t *r, 268 ngx_http_chunked_create_trailers(ngx_http_request_t *r,
253 ngx_http_chunked_filter_ctx_t *ctx, size_t size) 269 ngx_http_chunked_filter_ctx_t *ctx)
254 { 270 {
255 size_t len; 271 size_t len;
256 ngx_buf_t *b; 272 ngx_buf_t *b;
257 ngx_uint_t i; 273 ngx_uint_t i;
258 ngx_chain_t *cl; 274 ngx_chain_t *cl;
259 ngx_list_part_t *part; 275 ngx_list_part_t *part;
260 ngx_table_elt_t *header; 276 ngx_table_elt_t *header;
261 277
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
268 len = 0; 278 len = 0;
269 279
270 part = &r->headers_out.trailers.part; 280 part = &r->headers_out.trailers.part;
271 header = part->elts; 281 header = part->elts;
272 282
315 return NULL; 325 return NULL;
316 } 326 }
317 327
318 b->last = b->pos; 328 b->last = b->pos;
319 329
320 if (size > 0) { 330 *b->last++ = CR; *b->last++ = LF;
321 *b->last++ = CR; *b->last++ = LF;
322 }
323
324 *b->last++ = '0'; 331 *b->last++ = '0';
325 *b->last++ = CR; *b->last++ = LF; 332 *b->last++ = CR; *b->last++ = LF;
326 333
327 part = &r->headers_out.trailers.part; 334 part = &r->headers_out.trailers.part;
328 header = part->elts; 335 header = part->elts;