HTTPCLIENT-988: cache module should strip 'Content-Encoding: identity' from responses

Contributed by Jonathan Moore <jonathan_moore at comcast.com>


git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@993497 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2010-09-07 19:41:09 +00:00
parent ec40554d4d
commit fb038d3500
3 changed files with 104 additions and 4 deletions

View File

@ -31,6 +31,7 @@ import java.util.Date;
import java.util.List; import java.util.List;
import org.apache.http.Header; import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest; import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
@ -83,6 +84,8 @@ class ResponseProtocolCompliance {
ensure206ContainsDateHeader(response); ensure206ContainsDateHeader(response);
identityIsNotUsedInContentEncoding(response);
warningsWithNonMatchingWarnDatesAreRemoved(response); warningsWithNonMatchingWarnDatesAreRemoved(response);
} }
@ -116,6 +119,35 @@ class ResponseProtocolCompliance {
} }
} }
private void identityIsNotUsedInContentEncoding(HttpResponse response) {
Header[] hdrs = response.getHeaders("Content-Encoding");
if (hdrs == null || hdrs.length == 0) return;
List<Header> newHeaders = new ArrayList<Header>();
boolean modified = false;
for (Header h : hdrs) {
StringBuilder buf = new StringBuilder();
boolean first = true;
for (HeaderElement elt : h.getElements()) {
if ("identity".equalsIgnoreCase(elt.getName())) {
modified = true;
} else {
if (!first) buf.append(",");
buf.append(elt.toString());
first = false;
}
}
String newHeaderValue = buf.toString();
if (!"".equals(newHeaderValue)) {
newHeaders.add(new BasicHeader("Content-Encoding", newHeaderValue));
}
}
if (!modified) return;
response.removeHeaders("Content-Encoding");
for (Header h : newHeaders) {
response.addHeader(h);
}
}
private void authenticationRequiredDidNotHaveAProxyAuthenticationHeader(HttpRequest request, private void authenticationRequiredDidNotHaveAProxyAuthenticationHeader(HttpRequest request,
HttpResponse response) throws ClientProtocolException { HttpResponse response) throws ClientProtocolException {
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) if (response.getStatusLine().getStatusCode() != HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED)

View File

@ -0,0 +1,68 @@
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.impl.client.cache;
import static org.junit.Assert.*;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpResponse;
import org.junit.Test;
/*
* This test class captures functionality required to achieve unconditional
* compliance with the HTTP/1.1 spec, i.e. all the SHOULD, SHOULD NOT,
* RECOMMENDED, and NOT RECOMMENDED behaviors.
*/
public class TestProtocolRecommendations extends AbstractProtocolTest {
/* "identity: The default (identity) encoding; the use of no
* transformation whatsoever. This content-coding is used only in the
* Accept-Encoding header, and SHOULD NOT be used in the
* Content-Encoding header."
*
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5
*/
@Test
public void testIdentityCodingIsNotUsedInContentEncodingHeader()
throws Exception {
originResponse.setHeader("Content-Encoding", "identity");
backendExpectsAnyRequest().andReturn(originResponse);
replayMocks();
HttpResponse result = impl.execute(host, request);
verifyMocks();
boolean foundIdentity = false;
for(Header h : result.getHeaders("Content-Encoding")) {
for(HeaderElement elt : h.getElements()) {
if ("identity".equalsIgnoreCase(elt.getName())) {
foundIdentity = true;
}
}
}
assertFalse(foundIdentity);
}
}

View File

@ -1354,7 +1354,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
originResponse.addHeader("Allow", "GET,HEAD"); originResponse.addHeader("Allow", "GET,HEAD");
originResponse.addHeader("Cache-Control", "max-age=3600"); originResponse.addHeader("Cache-Control", "max-age=3600");
originResponse.addHeader("Content-Language", "en"); originResponse.addHeader("Content-Language", "en");
originResponse.addHeader("Content-Encoding", "identity"); originResponse.addHeader("Content-Encoding", "x-coding");
originResponse.addHeader("Content-MD5", "Q2hlY2sgSW50ZWdyaXR5IQ=="); originResponse.addHeader("Content-MD5", "Q2hlY2sgSW50ZWdyaXR5IQ==");
originResponse.addHeader("Content-Length", "128"); originResponse.addHeader("Content-Length", "128");
originResponse.addHeader("Content-Type", "application/octet-stream"); originResponse.addHeader("Content-Type", "application/octet-stream");
@ -1401,7 +1401,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
originResponse.addHeader("Allow", "GET,HEAD"); originResponse.addHeader("Allow", "GET,HEAD");
originResponse.addHeader("Cache-Control", "max-age=3600"); originResponse.addHeader("Cache-Control", "max-age=3600");
originResponse.addHeader("Content-Language", "en"); originResponse.addHeader("Content-Language", "en");
originResponse.addHeader("Content-Encoding", "identity"); originResponse.addHeader("Content-Encoding", "x-coding");
originResponse.addHeader("Content-MD5", "Q2hlY2sgSW50ZWdyaXR5IQ=="); originResponse.addHeader("Content-MD5", "Q2hlY2sgSW50ZWdyaXR5IQ==");
originResponse.addHeader("Content-Length", "128"); originResponse.addHeader("Content-Length", "128");
originResponse.addHeader("Content-Type", "application/octet-stream"); originResponse.addHeader("Content-Type", "application/octet-stream");
@ -1425,7 +1425,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
Assert.assertEquals("GET,HEAD", result.getFirstHeader("Allow").getValue()); Assert.assertEquals("GET,HEAD", result.getFirstHeader("Allow").getValue());
Assert.assertEquals("max-age=3600", result.getFirstHeader("Cache-Control").getValue()); Assert.assertEquals("max-age=3600", result.getFirstHeader("Cache-Control").getValue());
Assert.assertEquals("en", result.getFirstHeader("Content-Language").getValue()); Assert.assertEquals("en", result.getFirstHeader("Content-Language").getValue());
Assert.assertEquals("identity", result.getFirstHeader("Content-Encoding").getValue()); Assert.assertEquals("x-coding", result.getFirstHeader("Content-Encoding").getValue());
Assert.assertEquals("Q2hlY2sgSW50ZWdyaXR5IQ==", result.getFirstHeader("Content-MD5") Assert.assertEquals("Q2hlY2sgSW50ZWdyaXR5IQ==", result.getFirstHeader("Content-MD5")
.getValue()); .getValue());
Assert.assertEquals(originResponse.getFirstHeader("Last-Modified").getValue(), result Assert.assertEquals(originResponse.getFirstHeader("Last-Modified").getValue(), result
@ -1873,7 +1873,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
HttpResponse resp1 = make200Response(); HttpResponse resp1 = make200Response();
resp1.setHeader("ETag", "W/\"v1\""); resp1.setHeader("ETag", "W/\"v1\"");
resp1.setHeader("Allow", "GET,HEAD"); resp1.setHeader("Allow", "GET,HEAD");
resp1.setHeader("Content-Encoding", "identity"); resp1.setHeader("Content-Encoding", "x-coding");
resp1.setHeader("Content-Language", "en"); resp1.setHeader("Content-Language", "en");
resp1.setHeader("Content-Length", "128"); resp1.setHeader("Content-Length", "128");
resp1.setHeader("Content-MD5", "Q2hlY2sgSW50ZWdyaXR5IQ=="); resp1.setHeader("Content-MD5", "Q2hlY2sgSW50ZWdyaXR5IQ==");