comparison src/http/v3/ngx_http_v3_filter_module.c @ 8851:051968b73c59 quic

HTTP/3: Huffman encoding for the Location response field.
author Sergey Kandaurov <pluknet@nginx.com>
date Mon, 13 Sep 2021 16:25:32 +0300
parents 355461f0cc3b
children 8fc9c7f2c533
comparison
equal deleted inserted replaced
8850:355461f0cc3b 8851:051968b73c59
93 ngx_http_v3_header_filter(ngx_http_request_t *r) 93 ngx_http_v3_header_filter(ngx_http_request_t *r)
94 { 94 {
95 u_char *p; 95 u_char *p;
96 size_t len, n; 96 size_t len, n;
97 ngx_buf_t *b; 97 ngx_buf_t *b;
98 ngx_str_t host; 98 ngx_str_t host, location;
99 ngx_uint_t i, port; 99 ngx_uint_t i, port;
100 ngx_chain_t *out, *hl, *cl, **ll; 100 ngx_chain_t *out, *hl, *cl, **ll;
101 ngx_list_part_t *part; 101 ngx_list_part_t *part;
102 ngx_table_elt_t *header; 102 ngx_table_elt_t *header;
103 ngx_connection_t *c; 103 ngx_connection_t *c;
227 len += ngx_http_v3_encode_field_lri(NULL, 0, 227 len += ngx_http_v3_encode_field_lri(NULL, 0,
228 NGX_HTTP_V3_HEADER_LAST_MODIFIED, NULL, 228 NGX_HTTP_V3_HEADER_LAST_MODIFIED, NULL,
229 sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1); 229 sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1);
230 } 230 }
231 231
232 if (r->headers_out.location 232 if (r->headers_out.location && r->headers_out.location->value.len) {
233 && r->headers_out.location->value.len 233
234 && r->headers_out.location->value.data[0] == '/' 234 if (r->headers_out.location->value.data[0] == '/'
235 && clcf->absolute_redirect) 235 && clcf->absolute_redirect)
236 { 236 {
237 if (clcf->server_name_in_redirect) {
238 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
239 host = cscf->server_name;
240
241 } else if (r->headers_in.server.len) {
242 host = r->headers_in.server;
243
244 } else {
245 host.len = NGX_SOCKADDR_STRLEN;
246 host.data = addr;
247
248 if (ngx_connection_local_sockaddr(c, &host, 0) != NGX_OK) {
249 return NGX_ERROR;
250 }
251 }
252
253 port = ngx_inet_get_port(c->local_sockaddr);
254
255 location.len = sizeof("https://") - 1 + host.len
256 + r->headers_out.location->value.len;
257
258 if (clcf->port_in_redirect) {
259 port = (port == 443) ? 0 : port;
260
261 } else {
262 port = 0;
263 }
264
265 if (port) {
266 location.len += sizeof(":65535") - 1;
267 }
268
269 location.data = ngx_pnalloc(r->pool, location.len);
270 if (location.data == NULL) {
271 return NGX_ERROR;
272 }
273
274 p = ngx_cpymem(location.data, "https://", sizeof("https://") - 1);
275 p = ngx_cpymem(p, host.data, host.len);
276
277 if (port) {
278 p = ngx_sprintf(p, ":%ui", port);
279 }
280
281 p = ngx_cpymem(p, r->headers_out.location->value.data,
282 r->headers_out.location->value.len);
283
284 /* update r->headers_out.location->value for possible logging */
285
286 r->headers_out.location->value.len = p - location.data;
287 r->headers_out.location->value.data = location.data;
288 ngx_str_set(&r->headers_out.location->key, "Location");
289 }
290
237 r->headers_out.location->hash = 0; 291 r->headers_out.location->hash = 0;
238 292
239 if (clcf->server_name_in_redirect) {
240 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
241 host = cscf->server_name;
242
243 } else if (r->headers_in.server.len) {
244 host = r->headers_in.server;
245
246 } else {
247 host.len = NGX_SOCKADDR_STRLEN;
248 host.data = addr;
249
250 if (ngx_connection_local_sockaddr(c, &host, 0) != NGX_OK) {
251 return NGX_ERROR;
252 }
253 }
254
255 port = ngx_inet_get_port(c->local_sockaddr);
256
257 n = sizeof("https://") - 1 + host.len
258 + r->headers_out.location->value.len;
259
260 if (clcf->port_in_redirect) {
261 port = (port == 443) ? 0 : port;
262
263 } else {
264 port = 0;
265 }
266
267 if (port) {
268 n += sizeof(":65535") - 1;
269 }
270
271 len += ngx_http_v3_encode_field_lri(NULL, 0, 293 len += ngx_http_v3_encode_field_lri(NULL, 0,
272 NGX_HTTP_V3_HEADER_LOCATION, NULL, n); 294 NGX_HTTP_V3_HEADER_LOCATION, NULL,
273 295 r->headers_out.location->value.len);
274 } else {
275 ngx_str_null(&host);
276 port = 0;
277 } 296 }
278 297
279 #if (NGX_HTTP_GZIP) 298 #if (NGX_HTTP_GZIP)
280 if (r->gzip_vary) { 299 if (r->gzip_vary) {
281 if (clcf->gzip_vary) { 300 if (clcf->gzip_vary) {
423 b->last = (u_char *) ngx_http_v3_encode_field_lri(b->last, 0, 442 b->last = (u_char *) ngx_http_v3_encode_field_lri(b->last, 0,
424 NGX_HTTP_V3_HEADER_LAST_MODIFIED, 443 NGX_HTTP_V3_HEADER_LAST_MODIFIED,
425 p, n); 444 p, n);
426 } 445 }
427 446
428 if (host.data) { 447 if (r->headers_out.location && r->headers_out.location->value.len) {
429 n = sizeof("https://") - 1 + host.len
430 + r->headers_out.location->value.len;
431
432 if (port) {
433 n += ngx_sprintf(b->last, ":%ui", port) - b->last;
434 }
435
436 b->last = (u_char *) ngx_http_v3_encode_field_lri(b->last, 0, 448 b->last = (u_char *) ngx_http_v3_encode_field_lri(b->last, 0,
437 NGX_HTTP_V3_HEADER_LOCATION, 449 NGX_HTTP_V3_HEADER_LOCATION,
438 NULL, n); 450 r->headers_out.location->value.data,
439 451 r->headers_out.location->value.len);
440 p = b->last;
441 b->last = ngx_cpymem(b->last, "https://", sizeof("https://") - 1);
442 b->last = ngx_cpymem(b->last, host.data, host.len);
443
444 if (port) {
445 b->last = ngx_sprintf(b->last, ":%ui", port);
446 }
447
448 b->last = ngx_cpymem(b->last, r->headers_out.location->value.data,
449 r->headers_out.location->value.len);
450
451 /* update r->headers_out.location->value for possible logging */
452
453 r->headers_out.location->value.len = b->last - p;
454 r->headers_out.location->value.data = p;
455 ngx_str_set(&r->headers_out.location->key, "Location");
456 } 452 }
457 453
458 #if (NGX_HTTP_GZIP) 454 #if (NGX_HTTP_GZIP)
459 if (r->gzip_vary) { 455 if (r->gzip_vary) {
460 b->last = (u_char *) ngx_http_v3_encode_field_ri(b->last, 0, 456 b->last = (u_char *) ngx_http_v3_encode_field_ri(b->last, 0,