Mercurial > hg > nginx-quic
comparison src/http/ngx_http_upstream.c @ 7230:098bbd076a2d
Upstream: trailers support, u->conf->pass_trailers flag.
Basic trailer headers support allows one to access response trailers
via the $upstream_trailer_* variables.
Additionally, the u->conf->pass_trailers flag was introduced. When the
flag is set, trailer headers from the upstream response are passed to
the client. Like normal headers, trailer headers will be hidden
if present in u->conf->hide_headers_hash.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sat, 17 Mar 2018 23:04:21 +0300 |
parents | 20f139e9ffa8 |
children | 22f7bdbd96d3 |
comparison
equal
deleted
inserted
replaced
7229:87e9e4aabf1b | 7230:098bbd076a2d |
---|---|
52 ngx_http_upstream_t *u); | 52 ngx_http_upstream_t *u); |
53 static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r, | 53 static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r, |
54 ngx_http_upstream_t *u); | 54 ngx_http_upstream_t *u); |
55 static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c); | 55 static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c); |
56 static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r, | 56 static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r, |
57 ngx_http_upstream_t *u); | |
58 static ngx_int_t ngx_http_upstream_process_trailers(ngx_http_request_t *r, | |
57 ngx_http_upstream_t *u); | 59 ngx_http_upstream_t *u); |
58 static void ngx_http_upstream_send_response(ngx_http_request_t *r, | 60 static void ngx_http_upstream_send_response(ngx_http_request_t *r, |
59 ngx_http_upstream_t *u); | 61 ngx_http_upstream_t *u); |
60 static void ngx_http_upstream_upgrade(ngx_http_request_t *r, | 62 static void ngx_http_upstream_upgrade(ngx_http_request_t *r, |
61 ngx_http_upstream_t *u); | 63 ngx_http_upstream_t *u); |
162 ngx_http_variable_value_t *v, uintptr_t data); | 164 ngx_http_variable_value_t *v, uintptr_t data); |
163 static ngx_int_t ngx_http_upstream_response_length_variable( | 165 static ngx_int_t ngx_http_upstream_response_length_variable( |
164 ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); | 166 ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); |
165 static ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r, | 167 static ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r, |
166 ngx_http_variable_value_t *v, uintptr_t data); | 168 ngx_http_variable_value_t *v, uintptr_t data); |
169 static ngx_int_t ngx_http_upstream_trailer_variable(ngx_http_request_t *r, | |
170 ngx_http_variable_value_t *v, uintptr_t data); | |
167 static ngx_int_t ngx_http_upstream_cookie_variable(ngx_http_request_t *r, | 171 static ngx_int_t ngx_http_upstream_cookie_variable(ngx_http_request_t *r, |
168 ngx_http_variable_value_t *v, uintptr_t data); | 172 ngx_http_variable_value_t *v, uintptr_t data); |
169 | 173 |
170 static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy); | 174 static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy); |
171 static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, | 175 static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, |
421 #endif | 425 #endif |
422 | 426 |
423 { ngx_string("upstream_http_"), NULL, ngx_http_upstream_header_variable, | 427 { ngx_string("upstream_http_"), NULL, ngx_http_upstream_header_variable, |
424 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 }, | 428 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 }, |
425 | 429 |
430 { ngx_string("upstream_trailer_"), NULL, ngx_http_upstream_trailer_variable, | |
431 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 }, | |
432 | |
426 { ngx_string("upstream_cookie_"), NULL, ngx_http_upstream_cookie_variable, | 433 { ngx_string("upstream_cookie_"), NULL, ngx_http_upstream_cookie_variable, |
427 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 }, | 434 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 }, |
428 | 435 |
429 ngx_http_null_variable | 436 ngx_http_null_variable |
430 }; | 437 }; |
1044 != NGX_OK) | 1051 != NGX_OK) |
1045 { | 1052 { |
1046 return NGX_ERROR; | 1053 return NGX_ERROR; |
1047 } | 1054 } |
1048 | 1055 |
1056 if (ngx_list_init(&u->headers_in.trailers, r->pool, 2, | |
1057 sizeof(ngx_table_elt_t)) | |
1058 != NGX_OK) | |
1059 { | |
1060 return NGX_ERROR; | |
1061 } | |
1062 | |
1049 rc = u->process_header(r); | 1063 rc = u->process_header(r); |
1050 | 1064 |
1051 if (rc == NGX_OK) { | 1065 if (rc == NGX_OK) { |
1052 | 1066 |
1053 if (ngx_http_upstream_process_headers(r, u) != NGX_OK) { | 1067 if (ngx_http_upstream_process_headers(r, u) != NGX_OK) { |
1881 != NGX_OK) | 1895 != NGX_OK) |
1882 { | 1896 { |
1883 return NGX_ERROR; | 1897 return NGX_ERROR; |
1884 } | 1898 } |
1885 | 1899 |
1900 if (ngx_list_init(&u->headers_in.trailers, r->pool, 2, | |
1901 sizeof(ngx_table_elt_t)) | |
1902 != NGX_OK) | |
1903 { | |
1904 return NGX_ERROR; | |
1905 } | |
1906 | |
1886 /* reinit the request chain */ | 1907 /* reinit the request chain */ |
1887 | 1908 |
1888 file_pos = 0; | 1909 file_pos = 0; |
1889 | 1910 |
1890 for (cl = u->request_bufs; cl; cl = cl->next) { | 1911 for (cl = u->request_bufs; cl; cl = cl->next) { |
2235 ngx_http_upstream_finalize_request(r, u, | 2256 ngx_http_upstream_finalize_request(r, u, |
2236 NGX_HTTP_INTERNAL_SERVER_ERROR); | 2257 NGX_HTTP_INTERNAL_SERVER_ERROR); |
2237 return; | 2258 return; |
2238 } | 2259 } |
2239 | 2260 |
2261 if (ngx_list_init(&u->headers_in.trailers, r->pool, 2, | |
2262 sizeof(ngx_table_elt_t)) | |
2263 != NGX_OK) | |
2264 { | |
2265 ngx_http_upstream_finalize_request(r, u, | |
2266 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
2267 return; | |
2268 } | |
2269 | |
2240 #if (NGX_HTTP_CACHE) | 2270 #if (NGX_HTTP_CACHE) |
2241 | 2271 |
2242 if (r->cache) { | 2272 if (r->cache) { |
2243 u->buffer.pos += r->cache->header_start; | 2273 u->buffer.pos += r->cache->header_start; |
2244 u->buffer.last = u->buffer.pos; | 2274 u->buffer.last = u->buffer.pos; |
2728 } | 2758 } |
2729 #endif | 2759 #endif |
2730 } | 2760 } |
2731 | 2761 |
2732 u->length = -1; | 2762 u->length = -1; |
2763 | |
2764 return NGX_OK; | |
2765 } | |
2766 | |
2767 | |
2768 static ngx_int_t | |
2769 ngx_http_upstream_process_trailers(ngx_http_request_t *r, | |
2770 ngx_http_upstream_t *u) | |
2771 { | |
2772 ngx_uint_t i; | |
2773 ngx_list_part_t *part; | |
2774 ngx_table_elt_t *h, *ho; | |
2775 | |
2776 if (!u->conf->pass_trailers) { | |
2777 return NGX_OK; | |
2778 } | |
2779 | |
2780 part = &u->headers_in.trailers.part; | |
2781 h = part->elts; | |
2782 | |
2783 for (i = 0; /* void */; i++) { | |
2784 | |
2785 if (i >= part->nelts) { | |
2786 if (part->next == NULL) { | |
2787 break; | |
2788 } | |
2789 | |
2790 part = part->next; | |
2791 h = part->elts; | |
2792 i = 0; | |
2793 } | |
2794 | |
2795 if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash, | |
2796 h[i].lowcase_key, h[i].key.len)) | |
2797 { | |
2798 continue; | |
2799 } | |
2800 | |
2801 ho = ngx_list_push(&r->headers_out.trailers); | |
2802 if (ho == NULL) { | |
2803 return NGX_ERROR; | |
2804 } | |
2805 | |
2806 *ho = h[i]; | |
2807 } | |
2733 | 2808 |
2734 return NGX_OK; | 2809 return NGX_OK; |
2735 } | 2810 } |
2736 | 2811 |
2737 | 2812 |
4270 ngx_http_finalize_request(r, rc); | 4345 ngx_http_finalize_request(r, rc); |
4271 return; | 4346 return; |
4272 } | 4347 } |
4273 | 4348 |
4274 if (rc == 0) { | 4349 if (rc == 0) { |
4350 | |
4351 if (ngx_http_upstream_process_trailers(r, u) != NGX_OK) { | |
4352 ngx_http_finalize_request(r, NGX_ERROR); | |
4353 return; | |
4354 } | |
4355 | |
4275 rc = ngx_http_send_special(r, NGX_HTTP_LAST); | 4356 rc = ngx_http_send_special(r, NGX_HTTP_LAST); |
4276 | 4357 |
4277 } else if (flush) { | 4358 } else if (flush) { |
4278 r->keepalive = 0; | 4359 r->keepalive = 0; |
4279 rc = ngx_http_send_special(r, NGX_HTTP_FLUSH); | 4360 rc = ngx_http_send_special(r, NGX_HTTP_FLUSH); |
5376 } | 5457 } |
5377 | 5458 |
5378 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, | 5459 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, |
5379 &r->upstream->headers_in.headers.part, | 5460 &r->upstream->headers_in.headers.part, |
5380 sizeof("upstream_http_") - 1); | 5461 sizeof("upstream_http_") - 1); |
5462 } | |
5463 | |
5464 | |
5465 static ngx_int_t | |
5466 ngx_http_upstream_trailer_variable(ngx_http_request_t *r, | |
5467 ngx_http_variable_value_t *v, uintptr_t data) | |
5468 { | |
5469 if (r->upstream == NULL) { | |
5470 v->not_found = 1; | |
5471 return NGX_OK; | |
5472 } | |
5473 | |
5474 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, | |
5475 &r->upstream->headers_in.trailers.part, | |
5476 sizeof("upstream_trailer_") - 1); | |
5381 } | 5477 } |
5382 | 5478 |
5383 | 5479 |
5384 static ngx_int_t | 5480 static ngx_int_t |
5385 ngx_http_upstream_cookie_variable(ngx_http_request_t *r, | 5481 ngx_http_upstream_cookie_variable(ngx_http_request_t *r, |