Skip to content

Commit

Permalink
Avoid updating Content-Length header in a 304 response.
Browse files Browse the repository at this point in the history
I observed the following problem: `Transfer-Encoding` and
`Content-Length` headers should be mutually exclusive and because I use
chunked transfer, the `Transfer-Encoding` header is set in the response
while the `Content-Length` header is not. In case of a 304 during a
revalidation, the header contains Content-Length=0. Probably a proxy is
responsible for this, just like the comment "Some well-known proxies
respond with Content-Length=0, when returning 304" in the method
CachedHttpResponseGenerator::addMissingContentLengthHeader is saying. In
CacheEntryUpdater::mergeHeaders the Content-Length=0 is merged into the
cached entry, but the cached entry contains also a `Transfer-Encoding`
header, so in the cached entry these headers aren't mutually exclusive
anymore. Because of the `Transfer-Encoding` header the method
CachedHttpResponseGenerator::addMissingContentLengthHeader isn't fixing
the `Content-Length` header and Content-Length=0 causes returning null
instead of the cached content. IMHO the `Content-Length` header should
not be merged into the cached response in case of a 304, at least if the
cached entry contains a `Transfer-Encoding` header.
  • Loading branch information
dirkhenselin authored and ok2c committed Oct 3, 2020
1 parent f024a58 commit 8151d9e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ && entryDateHeaderNewerThenResponse(entry, response)) {
// Remove cache headers that match response
for (final HeaderIterator it = response.headerIterator(); it.hasNext(); ) {
final Header responseHeader = it.nextHeader();
// Since we do not expect a content in a 304 response, should retain the original Content-Encoding header
if (HTTP.CONTENT_ENCODING.equals(responseHeader.getName())) {
// Since we do not expect a content in a 304 response, should retain the original Content-Encoding and Content-Length header
if (HTTP.CONTENT_ENCODING.equals(responseHeader.getName())
|| HTTP.CONTENT_LEN.equals(responseHeader.getName())) {
continue;
}
final Header[] matchingHeaders = headerGroup.getHeaders(responseHeader.getName());
Expand All @@ -133,8 +134,9 @@ && entryDateHeaderNewerThenResponse(entry, response)) {
}
for (final HeaderIterator it = response.headerIterator(); it.hasNext(); ) {
final Header responseHeader = it.nextHeader();
// Since we do not expect a content in a 304 response, should avoid updating Content-Encoding header
if (HTTP.CONTENT_ENCODING.equals(responseHeader.getName())) {
// Since we do not expect a content in a 304 response, should avoid updating Content-Encoding and Content-Length header
if (HTTP.CONTENT_ENCODING.equals(responseHeader.getName())
|| HTTP.CONTENT_LEN.equals(responseHeader.getName())) {
continue;
}
headerGroup.addHeader(responseHeader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,27 @@ public void testContentEncodingHeaderIsNotUpdatedByMerge() throws IOException {
headersNotContain(updatedHeaders, "Content-Encoding", "gzip");
}

@Test
public void testContentLengthIsNotAddedWhenTransferEncodingIsPresent() throws IOException {
final Header[] headers = {
new BasicHeader("Date", DateUtils.formatDate(requestDate)),
new BasicHeader("ETag", "\"etag\""),
new BasicHeader("Transfer-Encoding", "chunked")};

entry = HttpTestUtils.makeCacheEntry(headers);
response.setHeaders(new Header[]{
new BasicHeader("Last-Modified", DateUtils.formatDate(responseDate)),
new BasicHeader("Cache-Control", "public"),
new BasicHeader("Content-Length", "0")});

final HttpCacheEntry updatedEntry = impl.updateCacheEntry(null, entry,
new Date(), new Date(), response);

final Header[] updatedHeaders = updatedEntry.getAllHeaders();
headersContain(updatedHeaders, "Transfer-Encoding", "chunked");
headersNotContain(updatedHeaders, "Content-Length", "0");
}

private void headersContain(final Header[] headers, final String name, final String value) {
for (final Header header : headers) {
if (header.getName().equals(name)) {
Expand Down

0 comments on commit 8151d9e

Please sign in to comment.