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,