Index: modules/proxy/mod_proxy_http.c =================================================================== --- modules/proxy/mod_proxy_http.c (revision 1710345) +++ modules/proxy/mod_proxy_http.c (working copy) @@ -196,6 +196,39 @@ APR_BRIGADE_INSERT_TAIL(header_brigade, e); } +static void add_trailer_line(const char * key, const char *val, apr_pool_t *p, + apr_bucket_alloc_t *bucket_alloc, + apr_bucket_brigade *bb) +{ + apr_bucket *e; + char *buf; + + buf = apr_pstrcat(p, key, ": ", val, CRLF, NULL); + ap_xlate_proto_to_ascii(buf, strlen(buf)); + + e = apr_bucket_immortal_create(buf, strlen(buf), bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, e); +} + +static void forward_declared_trailers(apr_pool_t *p, const request_rec *r, + apr_bucket_alloc_t *bucket_alloc, + apr_bucket_brigade *bb) +{ + const char *declared_trailers = apr_table_get(r->headers_in, "Trailer"); + if (declared_trailers) { + char *mod_trailers = apr_pstrcat(p, declared_trailers, NULL); + char *key; + char *last = NULL; + while ((key = apr_strtok(mod_trailers, ", ", &last))) { + const char *value = apr_table_get(r->trailers_in, key); + if (value) { + add_trailer_line(key, value, p, bucket_alloc, bb); + } + mod_trailers = last; + } + } +} + static void add_cl(apr_pool_t *p, apr_bucket_alloc_t *bucket_alloc, apr_bucket_brigade *header_brigade, @@ -357,10 +390,18 @@ bb = input_brigade; } - e = apr_bucket_immortal_create(ASCII_ZERO ASCII_CRLF - /* */ - ASCII_CRLF, - 5, bucket_alloc); + if (apr_is_empty_table(r->trailers_in)) { + e = apr_bucket_immortal_create(ASCII_ZERO ASCII_CRLF + /* */ + ASCII_CRLF, + 5, bucket_alloc); + } else { + e = apr_bucket_immortal_create(ASCII_ZERO ASCII_CRLF, + 3, bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, e); + forward_declared_trailers(p, r, bucket_alloc, bb); + e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc); + } APR_BRIGADE_INSERT_TAIL(bb, e); if (apr_table_get(r->subprocess_env, "proxy-sendextracrlf")) { @@ -982,6 +1023,18 @@ e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(header_brigade, e); } + /** pass tailer header and enforce chunked */ + if (*old_te_val) { + const char *trailer = apr_table_get(r->headers_in, "Trailer"); + if (trailer) { + char *buf = apr_pstrcat(p, "Trailer: ", trailer, CRLF, NULL); + ap_xlate_proto_to_ascii(buf, strlen(buf)); + APR_BRIGADE_INSERT_TAIL(header_brigade, + apr_bucket_pool_create(buf, strlen(buf), + p, bucket_alloc)); + *rb_method = RB_STREAM_CHUNKED; + } + } return OK; }