Mercurial > hg > nginx
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; |