10000 Merge branch 'master' into patch-1 · nginx/nginx@06c2ee0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 06c2ee0

Browse files
authored
Merge branch 'master' into patch-1
2 parents 1af9c6f + 1a64c19 commit 06c2ee0

File tree

5 files changed

+235
-17
lines changed

5 files changed

+235
-17
lines changed

src/http/modules/ngx_http_proxy_module.c

Lines changed: 221 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ typedef struct {
138138
ngx_chain_t *free;
139139
ngx_chain_t *busy;
140140

141+
ngx_buf_t *trailers;
142+
141143
unsigned head:1;
142144
unsigned internal_chunked:1;
143145
unsigned header_sent:1;
@@ -163,6 +165,8 @@ static ngx_int_t ngx_http_proxy_non_buffered_copy_filter(void *data,
163165
ssize_t bytes);
164166
static ngx_int_t ngx_http_proxy_non_buffered_chunked_filter(void *data,
165167
ssize_t bytes);
168+
static ngx_int_t ngx_http_proxy_process_trailer(ngx_http_request_t *r,
169+
ngx_buf_t *buf);
166170
static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
167171
static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
168172
ngx_int_t rc);
@@ -457,6 +461,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
457461
offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_body),
458462
NULL },
459463

464+
{ ngx_string("proxy_pass_trailers"),
465+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
466+
ngx_conf_set_flag_slot,
467+
NGX_HTTP_LOC_CONF_OFFSET,
468+
offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_trailers),
469+
NULL },
470+
460471
{ ngx_string("proxy_buffer_size"),
461472
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
462473
ngx_conf_set_size_slot,
@@ -2181,11 +2192,12 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
21812192
static ngx_int_t
21822193
ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
21832194
{
2184-
ngx_int_t rc;
2185-
ngx_buf_t *b, **prev;
2186-
ngx_chain_t *cl;
2187-
ngx_http_request_t *r;
2188-
ngx_http_proxy_ctx_t *ctx;
2195+
ngx_int_t rc;
2196+
ngx_buf_t *b, **prev;
2197+
ngx_chain_t *cl;
2198+
ngx_http_request_t *r;
2199+
ngx_http_proxy_ctx_t *ctx;
2200+
ngx_http_proxy_loc_conf_t *plcf;
21892201

21902202
if (buf->pos == buf->last) {
21912203
return NGX_OK;
@@ -2216,11 +2228,39 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
22162228
}
22172229

22182230
b = NULL;
2231+
2232+
if (ctx->trailers) {
2233+
rc = ngx_http_proxy_process_trailer(r, buf);
2234+
2235+
if (rc == NGX_ERROR) {
2236+
return NGX_ERROR;
2237+
}
2238+
2239+
if (rc == NGX_OK) {
2240+
2241+
/* a whole response has been parsed successfully */
2242+
2243+
p->length = 0;
2244+
r->upstream->keepalive = !r->upstream->headers_in.connection_close;
2245+
2246+
if (buf->pos != buf->last) {
2247+
ngx_log_error(NGX_LOG_WARN, p->log, 0,
2248+
"upstream sent data after trailers");
2249+
r->upstream->keepalive = 0;
2250+
}
2251+
}
2252+
2253+
goto free_buf;
2254+
}
2255+
2256+
plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
2257+
22192258
prev = &buf->shadow;
22202259

22212260
for ( ;; ) {
22222261

2223-
rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
2262+
rc = ngx_http_parse_chunked(r, buf, &ctx->chunked,
2263+
plcf->upstream.pass_trailers);
22242264

22252265
if (rc == NGX_OK) {
22262266

@@ -2275,6 +2315,19 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
22752315

22762316
if (rc == NGX_DONE) {
22772317

2318+
if (plcf->upstream.pass_trailers) {
2319+
rc = ngx_http_proxy_process_trailer(r, buf);
2320+
2321+
if (rc == NGX_ERROR) {
2322+
return NGX_ERROR;
2323+
}
2324+
2325+
if (rc == NGX_AGAIN) {
2326+
p->length = 1;
2327+
break;
2328+
}
2329+
}
2330+
22782331
/* a whole response has been parsed successfully */
22792332

22802333
p->length = 0;
@@ -2306,6 +2359,8 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
23062359
return NGX_ERROR;
23072360
}
23082361

2362+
free_buf:
2363+
23092364
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->log, 0,
23102365
"http proxy chunked state %ui, length %O",
23112366
ctx->chunked.state, p->length);
@@ -2401,11 +2456,14 @@ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
24012456
{
24022457
ngx_http_request_t *r = data;
24032458

2404-
ngx_int_t rc;
2405-
ngx_buf_t *b, *buf;
2406-
ngx_chain_t *cl, **ll;
2407-
ngx_http_upstream_t *u;
2408-
ngx_http_proxy_ctx_t *ctx;
2459+
ngx_int_t rc;
2460+
ngx_buf_t *b, *buf;
2461+
ngx_chain_t *cl, **ll;
2462+
ngx_http_upstream_t *u;
2463+
ngx_http_proxy_ctx_t *ctx;
2464+
ngx_http_proxy_loc_conf_t *plcf;
2465+
2466+
plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
24092467

24102468
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
24112469

@@ -2419,13 +2477,38 @@ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
24192477
buf->pos = buf->last;
24202478
buf->last += bytes;
24212479

2480+
if (ctx->trailers) {
2481+
rc = ngx_http_proxy_process_trailer(r, buf);
2482+
2483+
if (rc == NGX_ERROR) {
2484+
return NGX_ERROR;
2485+
}
2486+
2487+
if (rc == NGX_OK) {
2488+
2489+
/* a whole response has been parsed successfully */
2490+
2491+
r->upstream->keepalive = !u->headers_in.connection_close;
2492+
u->length = 0;
2493+
2494+
if (buf->pos != buf->last) {
2495+
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
2496+
"upstream sent data after trailers");
2497+
u->keepalive = 0;
2498+
}
2499+
}
2500+
2501+
return NGX_OK;
2502+
}
2503+
24222504
for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
24232505
ll = &cl->next;
24242506
}
24252507

24262508
for ( ;; ) {
24272509

2428-
rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
2510+
rc = ngx_http_parse_chunked(r, buf, &ctx->chunked,
2511+
plcf->upstream.pass_trailers);
24292512

24302513
if (rc == NGX_OK) {
24312514

@@ -2467,6 +2550,19 @@ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
24672550

24682551
if (rc == NGX_DONE) {
24692552

2553+
if (plcf->upstream.pass_trailers) {
2554+
rc = ngx_http_proxy_process_trailer(r, buf);
2555+
2556+
if (rc == NGX_ERROR) {
2557+
return NGX_ERROR;
2558+
}
2559+
2560+
if (rc == NGX_AGAIN) {
2561+
u->length = 1;
2562+
break;
2563+
}
2564+
}
2565+
24702566
/* a whole response has been parsed successfully */
24712567

24722568
u->keepalive = !u->headers_in.connection_close;
@@ -2497,6 +2593,115 @@ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
24972593
}
24982594

24992595

2596+
static ngx_int_t
2597+
ngx_http_proxy_process_trailer(ngx_http_request_t *r, ngx_buf_t *buf)
2598+
{
2599+
size_t len;
2600+
ngx_int_t rc;
2601+
ngx_buf_t *b;
2602+
ngx_table_elt_t *h;
2603+
ngx_http_proxy_ctx_t *ctx;
2604+
ngx_http_proxy_loc_conf_t *plcf;
2605+
2606+
plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
2607+
2608+
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2609+
2610+
if (ctx->trailers == NULL) {
2611+
ctx->trailers = ngx_create_temp_buf(r->pool,
2612+
plcf->upstream.buffer_size);
2613+
if (ctx->trailers == NULL) {
2614+
return NGX_ERROR;
2615+
}
2616+
}
2617+
2618+
b = ctx->trailers;
2619+
len = ngx_min(buf->last - buf->pos, b->end - b->last);
2620+
2621+
b->last = ngx_cpymem(b->last, buf->pos, len);
2622+
2623+
for ( ;; ) {
2624+
2625+
rc = ngx_http_parse_header_line(r, b, 1);
2626+
2627+
if (rc == NGX_OK) {
2628+
2629+
/* a header line has been parsed successfully */
2630+
2631+
h = ngx_list_push(&r->upstream->headers_in.trailers);
2632+
if (h == NULL) {
2633+
return NGX_ERROR;
2634+
}
2635+
2636+
h->hash = r->header_hash;
2637+
2638+
h->key.len = r->header_name_end - r->header_name_start;
2639+
h->value.len = r->header_end - r->header_start;
2640+
2641+
h->key.data = ngx_pnalloc(r->pool,
2642+
h->key.len + 1 + h->value.len + 1 + h->key.len);
2643+
if (h->key.data == NULL) {
2644+
h->hash = 0;
2645+
return NGX_ERROR;
2646+
}
2647+
2648+
h->value.data = h->key.data + h->key.len + 1;
2649+
h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
2650+
2651+
ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
2652+
h->key.data[h->key.len] = '\0';
2653+
ngx_memcpy(h->value.data, r->header_start, h->value.len);
2654+
h->value.data[h->value.len] = '\0';
2655+
2656+
if (h->key.len == r->lowcase_index) {
2657+
ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
2658+
2659+
} else {
2660+
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
2661+
}
2662+
2663+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2664+
"http proxy trailer: \"%V: %V\"",
2665+
&h->key, &h->value);
2666+
continue;
2667+
}
2668+
2669+
if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
2670+
2671+
/* a whole header has been parsed successfully */
2672+
2673+
buf->pos += len - (b->last - b->pos);
2674+
2675+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2676+
"http proxy trailer done");
2677+
2678+
return NGX_OK;
2679+
}
2680+
2681+
if (rc == NGX_AGAIN) {
2682+
buf->pos += len;
2683+
2684+
if (b->last == b->end) {
2685+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2686+
"upstream sent too big trailers");
2687+
return NGX_ERROR;
2688+
}
2689+
2690+
return NGX_AGAIN;
2691+
}
2692+
2693+
/* rc == NGX_HTTP_PARSE_INVALID_HEADER */
2694+
2695+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2696+
"upstream sent invalid trailer: \"%*s\\x%02xd...\"",
2697+
r->header_end - r->header_name_start,
2698+
r->header_name_start, *r->header_end);
2699+
2700+
return NGX_ERROR;
2701+
}
2702+
}
2703+
2704+
25002705
static void
25012706
ngx_http_proxy_abort_request(ngx_http_request_t *r)
25022707
{
@@ -3379,6 +3584,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
33793584

33803585
conf->upstream.pass_request_headers = NGX_CONF_UNSET;
33813586
conf->upstream.pass_request_body = NGX_CONF_UNSET;
3587+
conf->upstream.pass_trailers = NGX_CONF_UNSET;
33823588

33833589
#if (NGX_HTTP_CACHE)
33843590
conf->upstream.cache = NGX_CONF_UNSET;
@@ -3721,6 +3927,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
37213927
ngx_conf_merge_value(conf->upstream.pass_request_body,
37223928
prev->upstream.pass_request_body, 1);
37233929

3930+
ngx_conf_merge_value(conf->upstream.pass_trailers,
3931+
prev->upstream.pass_trailers, 0);
3932+
37243933
ngx_conf_merge_value(conf->upstream.intercept_errors,
37253934
prev->upstream.intercept_errors, 0);
37263935

src/http/ngx_http.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ ngx_int_t ngx_http_arg(ngx_http_request_t *r, u_char *name, size_t len,
117117
void ngx_http_split_args(ngx_http_request_t *r, ngx_str_t *uri,
118118
ngx_str_t *args);
119119
ngx_int_t ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b,
120-
ngx_http_chunked_t *ctx);
120+
ngx_http_chunked_t *ctx, ngx_uint_t keep_trailers);
121121

122122

123123
ngx_http_request_t *ngx_http_create_request(ngx_connection_t *c);

src/http/ngx_http_parse.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2140,7 +2140,7 @@ ngx_http_split_args(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args)
21402140

21412141
ngx_int_t
21422142
ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b,
2143-
ngx_http_chunked_t *ctx)
2143+
ngx_http_chunked_t *ctx, ngx_uint_t keep_trailers)
21442144
{
21452145
u_char *pos, ch, c;
21462146
ngx_int_t rc;
@@ -2218,6 +2218,9 @@ ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b,
22182218
state = sw_last_chunk_extension_almost_done;
22192219
break;
22202220
case LF:
2221+
if (keep_trailers) {
2222+
goto done;
2223+
}
22212224
state = sw_trailer;
22222225
break;
22232226
case ';':
@@ -2297,12 +2300,18 @@ ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b,
22972300
state = sw_last_chunk_extension_almost_done;
22982301
break;
22992302
case LF:
2303+
if (keep_trailers) {
2304+
goto done;
2305+
}
23002306
state = sw_trailer;
23012307
}
23022308
break;
23032309

23042310
case sw_last_chunk_extension_almost_done:
23052311
if (ch == LF) {
2312+
if (keep_trailers) {
2313+
goto done;
2314+
}
23062315
state = sw_trailer;
23072316
break;
23082317
}

src/http/ngx_http_request_body.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,7 @@ ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
870870

871871
for ( ;; ) {
872872

873-
rc = ngx_http_parse_chunked(r, b, rb->chunked);
873+
rc = ngx_http_parse_chunked(r, b, rb->chunked, 0);
874874

875875
if (rc == NGX_OK) {
876876

@@ -1131,7 +1131,7 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
11311131
cl->buf->file_pos,
11321132
cl->buf->file_last - cl->buf->file_pos);
11331133

1134-
rc = ngx_http_parse_chunked(r, cl->buf, rb->chunked);
1134+
rc = ngx_http_parse_chunked(r, cl->buf, rb->chunked, 0);
11351135

11361136
if (rc == NGX_OK) {
11371137

0 commit comments

Comments
 (0)
0