You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by jo...@apache.org on 2011/01/12 20:14:37 UTC
svn commit: r1058280 - in
/httpcomponents/httpclient/trunk/httpclient-cache/src:
main/java/org/apache/http/impl/client/cache/
test/java/org/apache/http/impl/client/cache/
Author: jonm
Date: Wed Jan 12 19:14:37 2011
New Revision: 1058280
URL: http://svn.apache.org/viewvc?rev=1058280&view=rev
Log:
Support the following protocol recommendation:
"If a request includes the no-cache directive, it SHOULD NOT
include min-fresh, max-stale, or max-age."
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4
We address this by looking for no-cache and then filtering the
above directives out if present.
Added:
httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRequestProtocolCompliance.java (with props)
Modified:
httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java
httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java
Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java?rev=1058280&r1=1058279&r2=1058280&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java Wed Jan 12 19:14:37 2011
@@ -27,6 +27,7 @@
package org.apache.http.impl.client.cache;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.apache.http.Header;
@@ -54,6 +55,9 @@ import org.apache.http.protocol.HTTP;
@Immutable
class RequestProtocolCompliance {
+ private static final List<String> disallowedWithNoCache =
+ Arrays.asList("min-fresh", "max-stale", "max-age");
+
/**
* Test to see if the {@link HttpRequest} is HTTP1.1 compliant or not
* and if not, we can not continue.
@@ -64,11 +68,6 @@ class RequestProtocolCompliance {
public List<RequestProtocolError> requestIsFatallyNonCompliant(HttpRequest request) {
List<RequestProtocolError> theErrors = new ArrayList<RequestProtocolError>();
- //RequestProtocolError anError = requestContainsBodyButNoLength(request);
- //if (anError != null) {
- // theErrors.add(anError);
- //}
-
RequestProtocolError anError = requestHasWeakETagAndRange(request);
if (anError != null) {
theErrors.add(anError);
@@ -105,6 +104,7 @@ class RequestProtocolCompliance {
verifyRequestWithExpectContinueFlagHas100continueHeader(request);
verifyOPTIONSRequestWithBodyHasContentType(request);
decrementOPTIONSMaxForwardsIfGreaterThen0(request);
+ stripOtherFreshnessDirectivesWithNoCache(request);
if (requestVersionIsTooLow(request)) {
return upgradeRequestTo(request, HttpVersion.HTTP_1_1);
@@ -116,6 +116,38 @@ class RequestProtocolCompliance {
return request;
}
+
+ private void stripOtherFreshnessDirectivesWithNoCache(HttpRequest request) {
+ List<HeaderElement> outElts = new ArrayList<HeaderElement>();
+ boolean shouldStrip = false;
+ for(Header h : request.getHeaders("Cache-Control")) {
+ for(HeaderElement elt : h.getElements()) {
+ if (!disallowedWithNoCache.contains(elt.getName())) {
+ outElts.add(elt);
+ }
+ if ("no-cache".equals(elt.getName())) {
+ shouldStrip = true;
+ }
+ }
+ }
+ if (!shouldStrip) return;
+ request.removeHeaders("Cache-Control");
+ request.setHeader("Cache-Control", buildHeaderFromElements(outElts));
+ }
+
+ private String buildHeaderFromElements(List<HeaderElement> outElts) {
+ StringBuilder newHdr = new StringBuilder("");
+ boolean first = true;
+ for(HeaderElement elt : outElts) {
+ if (!first) {
+ newHdr.append(",");
+ } else {
+ first = false;
+ }
+ newHdr.append(elt.toString());
+ }
+ return newHdr.toString();
+ }
private boolean requestMustNotHaveEntity(HttpRequest request) {
return HeaderConstants.TRACE_METHOD.equals(request.getRequestLine().getMethod())
Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java?rev=1058280&r1=1058279&r2=1058280&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRecommendations.java Wed Jan 12 19:14:37 2011
@@ -30,7 +30,9 @@ import static org.easymock.classextensio
import static org.junit.Assert.*;
import java.io.IOException;
+import java.util.Arrays;
import java.util.Date;
+import java.util.List;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
@@ -1333,4 +1335,43 @@ public class TestProtocolRecommendations
assertTrue(HttpTestUtils.semanticallyTransparent(resp2, result));
}
+ /*
+ * "If a request includes the no-cache directive, it SHOULD NOT
+ * include min-fresh, max-stale, or max-age."
+ *
+ * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4
+ */
+ @Test
+ public void otherFreshnessRequestDirectivesNotAllowedWithNoCache()
+ throws Exception {
+ HttpRequest req1 = HttpTestUtils.makeDefaultRequest();
+ req1.setHeader("Cache-Control", "min-fresh=10, no-cache");
+ req1.addHeader("Cache-Control", "max-stale=0, max-age=0");
+
+ Capture<HttpRequest> cap = new Capture<HttpRequest>();
+ expect(mockBackend.execute(same(host), capture(cap), (HttpContext)isNull()))
+ .andReturn(HttpTestUtils.make200Response());
+
+ replayMocks();
+ impl.execute(host, req1);
+ verifyMocks();
+
+ HttpRequest captured = cap.getValue();
+ boolean foundNoCache = false;
+ boolean foundDisallowedDirective = false;
+ List<String> disallowed =
+ Arrays.asList("min-fresh", "max-stale", "max-age");
+ for(Header h : captured.getHeaders("Cache-Control")) {
+ for(HeaderElement elt : h.getElements()) {
+ if (disallowed.contains(elt.getName())) {
+ foundDisallowedDirective = true;
+ }
+ if ("no-cache".equals(elt.getName())) {
+ foundNoCache = true;
+ }
+ }
+ }
+ assertTrue(foundNoCache);
+ assertFalse(foundDisallowedDirective);
+ }
}
Added: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRequestProtocolCompliance.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRequestProtocolCompliance.java?rev=1058280&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRequestProtocolCompliance.java (added)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRequestProtocolCompliance.java Wed Jan 12 19:14:37 2011
@@ -0,0 +1,103 @@
+package org.apache.http.impl.client.cache;
+
+import static org.junit.Assert.*;
+
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpVersion;
+import org.apache.http.ProtocolVersion;
+import org.apache.http.message.BasicHttpEntityEnclosingRequest;
+import org.apache.http.message.BasicHttpRequest;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestRequestProtocolCompliance {
+
+ private RequestProtocolCompliance impl;
+ private HttpRequest req;
+ private HttpRequest result;
+
+ @Before
+ public void setUp() {
+ req = HttpTestUtils.makeDefaultRequest();
+ impl = new RequestProtocolCompliance();
+ }
+
+ @Test
+ public void doesNotModifyACompliantRequest() throws Exception {
+ result = impl.makeRequestCompliant(req);
+ assertTrue(HttpTestUtils.equivalent(req, result));
+ }
+
+ @Test
+ public void removesEntityFromTRACERequest() throws Exception {
+ HttpEntityEnclosingRequest req =
+ new BasicHttpEntityEnclosingRequest("TRACE", "/", HttpVersion.HTTP_1_1);
+ req.setEntity(HttpTestUtils.makeBody(50));
+ result = impl.makeRequestCompliant(req);
+ if (result instanceof HttpEntityEnclosingRequest) {
+ assertNull(((HttpEntityEnclosingRequest)result).getEntity());
+ }
+ }
+
+ @Test
+ public void upgrades1_0RequestTo1_1() throws Exception {
+ req = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_0);
+ result = impl.makeRequestCompliant(req);
+ assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion());
+ }
+
+ @Test
+ public void downgrades1_2RequestTo1_1() throws Exception {
+ ProtocolVersion HTTP_1_2 = new ProtocolVersion("HTTP", 1, 2);
+ req = new BasicHttpRequest("GET", "/", HTTP_1_2);
+ result = impl.makeRequestCompliant(req);
+ assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion());
+ }
+
+ @Test
+ public void stripsMinFreshFromRequestIfNoCachePresent()
+ throws Exception {
+ req.setHeader("Cache-Control", "no-cache, min-fresh=10");
+ result = impl.makeRequestCompliant(req);
+ assertEquals("no-cache",
+ result.getFirstHeader("Cache-Control").getValue());
+ }
+
+ @Test
+ public void stripsMaxFreshFromRequestIfNoCachePresent()
+ throws Exception {
+ req.setHeader("Cache-Control", "no-cache, max-stale=10");
+ result = impl.makeRequestCompliant(req);
+ assertEquals("no-cache",
+ result.getFirstHeader("Cache-Control").getValue());
+ }
+
+ @Test
+ public void stripsMaxAgeFromRequestIfNoCachePresent()
+ throws Exception {
+ req.setHeader("Cache-Control", "no-cache, max-age=10");
+ result = impl.makeRequestCompliant(req);
+ assertEquals("no-cache",
+ result.getFirstHeader("Cache-Control").getValue());
+ }
+
+ @Test
+ public void doesNotStripMinFreshFromRequestWithoutNoCache()
+ throws Exception {
+ req.setHeader("Cache-Control", "min-fresh=10");
+ result = impl.makeRequestCompliant(req);
+ assertEquals("min-fresh=10",
+ result.getFirstHeader("Cache-Control").getValue());
+ }
+
+ @Test
+ public void correctlyStripsMinFreshFromMiddleIfNoCache()
+ throws Exception {
+ req.setHeader("Cache-Control", "no-cache,min-fresh=10,no-store");
+ result = impl.makeRequestCompliant(req);
+ assertEquals("no-cache,no-store",
+ result.getFirstHeader("Cache-Control").getValue());
+ }
+
+}
Propchange: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRequestProtocolCompliance.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRequestProtocolCompliance.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestRequestProtocolCompliance.java
------------------------------------------------------------------------------
svn:mime-type = text/plain