summaryrefslogtreecommitdiff
path: root/modules/http
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2022-04-04 11:08:58 +0000
committerStefan Eissing <icing@apache.org>2022-04-04 11:08:58 +0000
commitdc18031936ae3c7b98ea1305ce24dc537aecb596 (patch)
tree9efeeface0c982ac9b59f98424c16a7385381713 /modules/http
parentcc232ba4549b1c47b5e4c944e6040e11563bafad (diff)
downloadhttpd-dc18031936ae3c7b98ea1305ce24dc537aecb596.tar.gz
*) mod_http: genereate HEADERS buckets for trailers
mod_proxy: forward trailers on chunked request encoding test: add http/1.x test cases in pytest git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1899552 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/http')
-rw-r--r--modules/http/http_filters.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c
index 9bcf2297d0..0a9ff425ea 100644
--- a/modules/http/http_filters.c
+++ b/modules/http/http_filters.c
@@ -1312,6 +1312,15 @@ AP_DECLARE_NONSTD(int) ap_send_http_trace(request_rec *r)
return DONE;
}
+static apr_bucket *create_trailers_bucket(request_rec *r, apr_bucket_alloc_t *bucket_alloc)
+{
+ if (r->trailers_out && !apr_is_empty_table(r->trailers_out)) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "sending trailers");
+ return ap_bucket_headers_create(r->trailers_out, r->pool, bucket_alloc);
+ }
+ return NULL;
+}
+
typedef struct header_filter_ctx {
int headers_sent;
} header_filter_ctx;
@@ -1323,7 +1332,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
conn_rec *c = r->connection;
int header_only = (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status));
const char *protocol = NULL;
- apr_bucket *e;
+ apr_bucket *e, *eos = NULL;
apr_bucket_brigade *b2;
header_struct h;
header_filter_ctx *ctx = f->ctx;
@@ -1364,6 +1373,10 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
eb = e->data;
continue;
}
+ if (APR_BUCKET_IS_EOS(e)) {
+ if (!eos) eos = e;
+ continue;
+ }
/*
* If we see an EOC bucket it is a signal that we should get out
* of the way doing nothing.
@@ -1416,6 +1429,22 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
goto out;
}
+ if (eos) {
+ /* on having seen EOS and added possible trailers, we
+ * can remove this filter.
+ */
+ e = create_trailers_bucket(r, b->bucket_alloc);
+ if (e) {
+ APR_BUCKET_INSERT_BEFORE(eos, e);
+ }
+ ap_remove_output_filter(f);
+ }
+
+ if (ctx->headers_sent) {
+ /* we did already the stuff below, just pass on */
+ return ap_pass_brigade(f->next, b);
+ }
+
/*
* Now that we are ready to send a response, we need to combine the two
* header field tables into a single table. If we don't do this, our
@@ -1545,11 +1574,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
ap_add_output_filter("CHUNK", NULL, r, r->connection);
}
- /* Don't remove this filter until after we have added the CHUNK filter.
- * Otherwise, f->next won't be the CHUNK filter and thus the first
- * brigade won't be chunked properly.
- */
- ap_remove_output_filter(f);
rv = ap_pass_brigade(f->next, b);
out:
if (recursive_error) {