From: Stefan Eissing Date: Mon, 14 Dec 2015 10:33:11 +0000 (+0000) Subject: incoming trailers passed directly to request_rec, work independant of chunked encoding X-Git-Tag: 2.5.0-alpha~2535 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6d956222782e4168ebc6e5d95f9554886d58d26d;p=thirdparty%2Fapache%2Fhttpd.git incoming trailers passed directly to request_rec, work independant of chunked encoding git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1719876 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/http2/h2_h2.c b/modules/http2/h2_h2.c index dee6f1e1493..20fbe30d1ed 100644 --- a/modules/http2/h2_h2.c +++ b/modules/http2/h2_h2.c @@ -651,6 +651,8 @@ static int h2_h2_post_read_req(request_rec *r) * that we manipulate filters only once. */ /* our slave connection? */ if (task && !task->filters_set) { + ap_filter_t *f; + /* setup the correct output filters to process the response * on the proper mod_http2 way. */ ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r, "adding task output filter"); @@ -663,6 +665,16 @@ static int h2_h2_post_read_req(request_rec *r) ap_remove_output_filter_byhandle(r->output_filters, "HTTP_HEADER"); ap_add_output_filter("H2_RESPONSE", task, r, r->connection); } + + /* trailers processing. Incoming trailers are added to this + * request via our h2 input filter, outgoing trailers + * in a special h2 out filter. */ + for (f = r->input_filters; f; f = f->next) { + if (!strcmp("H2_TO_H1", f->frec->name)) { + f->r = r; + break; + } + } ap_add_output_filter("H2_TRAILERS", task, r, r->connection); task->filters_set = 1; } diff --git a/modules/http2/h2_io.c b/modules/http2/h2_io.c index 9e968286565..d3880797ed9 100644 --- a/modules/http2/h2_io.c +++ b/modules/http2/h2_io.c @@ -105,15 +105,23 @@ static int add_trailer(void *ctx, const char *key, const char *value) return (status == APR_SUCCESS); } -static apr_status_t append_eos(h2_io *io, apr_bucket_brigade *bb) +static apr_status_t append_eos(h2_io *io, apr_bucket_brigade *bb, + apr_table_t *trailers) { apr_status_t status = APR_SUCCESS; + apr_table_t *t = io->request->trailers; + + if (trailers && t && !apr_is_empty_table(trailers)) { + /* trailers passed in, transfer directly. */ + apr_table_overlap(trailers, t, APR_OVERLAP_TABLES_SET); + t = NULL; + } if (io->request->chunked) { - apr_table_t *trailers = io->request->trailers; - if (trailers && !apr_is_empty_table(trailers)) { + if (t && !apr_is_empty_table(t)) { + /* no trailers passed in, transfer via chunked */ status = apr_brigade_puts(bb, NULL, NULL, "0\r\n"); - apr_table_do(add_trailer, bb, trailers, NULL); + apr_table_do(add_trailer, bb, t, NULL); status = apr_brigade_puts(bb, NULL, NULL, "\r\n"); } else { @@ -125,7 +133,7 @@ static apr_status_t append_eos(h2_io *io, apr_bucket_brigade *bb) } apr_status_t h2_io_in_read(h2_io *io, apr_bucket_brigade *bb, - apr_size_t maxlen) + apr_size_t maxlen, apr_table_t *trailers) { apr_off_t start_len = 0; apr_status_t status; @@ -137,7 +145,7 @@ apr_status_t h2_io_in_read(h2_io *io, apr_bucket_brigade *bb, if (!io->bbin || APR_BRIGADE_EMPTY(io->bbin)) { if (io->eos_in) { if (!io->eos_in_written) { - status = append_eos(io, bb); + status = append_eos(io, bb, trailers); io->eos_in_written = 1; return status; } diff --git a/modules/http2/h2_io.h b/modules/http2/h2_io.h index 6dd44742119..c2ecbb91221 100644 --- a/modules/http2/h2_io.h +++ b/modules/http2/h2_io.h @@ -96,7 +96,7 @@ int h2_io_out_has_data(h2_io *io); * is currently available, APR_EOF if end of input has been reached. */ apr_status_t h2_io_in_read(h2_io *io, apr_bucket_brigade *bb, - apr_size_t maxlen); + apr_size_t maxlen, apr_table_t *trailers); /** * Appends given bucket to the input. diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c index 4c3d16dce97..9f50b8cb8bd 100644 --- a/modules/http2/h2_mplx.c +++ b/modules/http2/h2_mplx.c @@ -339,7 +339,8 @@ void h2_mplx_task_done(h2_mplx *m, int stream_id) } apr_status_t h2_mplx_in_read(h2_mplx *m, apr_read_type_e block, - int stream_id, apr_bucket_brigade *bb, + int stream_id, apr_bucket_brigade *bb, + apr_table_t *trailers, struct apr_thread_cond_t *iowait) { apr_status_t status; @@ -353,7 +354,7 @@ apr_status_t h2_mplx_in_read(h2_mplx *m, apr_read_type_e block, if (io && !io->orphaned) { io->input_arrived = iowait; H2_MPLX_IO_IN(APLOG_TRACE2, m, io, "h2_mplx_in_read_pre"); - status = h2_io_in_read(io, bb, -1); + status = h2_io_in_read(io, bb, -1, trailers); while (APR_STATUS_IS_EAGAIN(status) && !is_aborted(m, &status) && block == APR_BLOCK_READ) { @@ -361,7 +362,7 @@ apr_status_t h2_mplx_in_read(h2_mplx *m, apr_read_type_e block, "h2_mplx(%ld-%d): wait on in data (BLOCK_READ)", m->id, stream_id); apr_thread_cond_wait(io->input_arrived, m->lock); - status = h2_io_in_read(io, bb, -1); + status = h2_io_in_read(io, bb, -1, trailers); } H2_MPLX_IO_IN(APLOG_TRACE2, m, io, "h2_mplx_in_read_post"); io->input_arrived = NULL; diff --git a/modules/http2/h2_mplx.h b/modules/http2/h2_mplx.h index f2805be373a..4c577d0f768 100644 --- a/modules/http2/h2_mplx.h +++ b/modules/http2/h2_mplx.h @@ -206,6 +206,7 @@ void h2_mplx_set_consumed_cb(h2_mplx *m, h2_mplx_consumed_cb *cb, void *ctx); */ apr_status_t h2_mplx_in_read(h2_mplx *m, apr_read_type_e block, int stream_id, apr_bucket_brigade *bb, + apr_table_t *trailers, struct apr_thread_cond_t *iowait); /** diff --git a/modules/http2/h2_task_input.c b/modules/http2/h2_task_input.c index 863480c8589..921d03394e7 100644 --- a/modules/http2/h2_task_input.c +++ b/modules/http2/h2_task_input.c @@ -135,6 +135,7 @@ apr_status_t h2_task_input_read(h2_task_input *input, never calling us again. */ status = h2_mplx_in_read(input->task->mplx, APR_BLOCK_READ, input->task->stream_id, input->bb, + f->r? f->r->trailers_in : NULL, input->task->io); ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, f->c, "h2_task_input(%s): mplx in read returned",