diff options
author | Joe Orton <jorton@apache.org> | 2023-12-20 16:56:15 +0100 |
---|---|---|
committer | Joe Orton <jorton@apache.org> | 2023-12-20 16:56:15 +0100 |
commit | b5b2ca3f3e6e95257c6d2a31278bf1f58e83c1bb (patch) | |
tree | 310ddd521e8722f81e81028572f5f2d4c41e7920 | |
parent | mod_deflate: remove filter after seeing EOS (diff) | |
download | apache2-b5b2ca3f3e6e95257c6d2a31278bf1f58e83c1bb.tar.xz apache2-b5b2ca3f3e6e95257c6d2a31278bf1f58e83c1bb.zip |
* modules/http/chunk_filter.c (ap_http_chunk_filter): For a brigade
containing [FLUSH EOS], insert the last-chunk terminator before the
FLUSH rather than between the FLUSH and the EOS.
Github: closes #400
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1914804 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | changes-entries/flushing-chunks.txt | 2 | ||||
-rw-r--r-- | modules/http/chunk_filter.c | 24 |
2 files changed, 20 insertions, 6 deletions
diff --git a/changes-entries/flushing-chunks.txt b/changes-entries/flushing-chunks.txt new file mode 100644 index 0000000000..7e9519f118 --- /dev/null +++ b/changes-entries/flushing-chunks.txt @@ -0,0 +1,2 @@ + *) http/1.1: For a chunked response body, ensure the last-chunk + terminator is flushed if necessary. [Joe Orton] diff --git a/modules/http/chunk_filter.c b/modules/http/chunk_filter.c index f44543a765..1fa3fa9352 100644 --- a/modules/http/chunk_filter.c +++ b/modules/http/chunk_filter.c @@ -64,7 +64,7 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b) for (more = tmp = NULL; b; b = more, more = NULL) { apr_off_t bytes = 0; - apr_bucket *eos = NULL; + apr_bucket *eos = NULL; /* EOS bucket, or FLUSH preceding EOS */ apr_bucket *flush = NULL; /* XXX: chunk_hdr must remain at this scope since it is used in a * transient bucket. @@ -99,8 +99,20 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b) } if (APR_BUCKET_IS_FLUSH(e)) { flush = e; + + /* Special case to catch common brigade ending of + * [FLUSH] [EOS] - insert the last_chunk before + * the FLUSH rather than between the FLUSH and the + * EOS. */ if (e != APR_BRIGADE_LAST(b)) { - more = apr_brigade_split_ex(b, APR_BUCKET_NEXT(e), tmp); + if (APR_BUCKET_IS_EOS(APR_BUCKET_NEXT(e))) { + eos = e; + /* anything after EOS is dropped, no need + * to split. */ + } + else { + more = apr_brigade_split_ex(b, APR_BUCKET_NEXT(e), tmp); + } } break; } @@ -173,12 +185,12 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b) * FLUSH bucket, or appended to the brigade */ e = apr_bucket_immortal_create(CRLF_ASCII, 2, c->bucket_alloc); - if (eos != NULL) { - APR_BUCKET_INSERT_BEFORE(eos, e); - } - else if (flush != NULL) { + if (flush != NULL) { APR_BUCKET_INSERT_BEFORE(flush, e); } + else if (eos != NULL) { + APR_BUCKET_INSERT_BEFORE(eos, e); + } else { APR_BRIGADE_INSERT_TAIL(b, e); } |