You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2016/12/27 19:48:10 UTC

svn commit: r1776187 [9/21] - in /httpcomponents/httpclient/trunk: ./ httpclient5-cache/src/main/java/org/apache/hc/client5/http/cache/ httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ httpclient5-cache/src/test/java/org/apache/hc...

Modified: httpcomponents/httpclient/trunk/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java?rev=1776187&r1=1776186&r2=1776187&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java (original)
+++ httpcomponents/httpclient/trunk/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestProtocolRequirements.java Tue Dec 27 19:48:07 2016
@@ -30,33 +30,34 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.SocketTimeoutException;
 import java.util.Date;
+import java.util.Iterator;
 import java.util.Random;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.hc.client5.http.HttpRoute;
 import org.apache.hc.client5.http.cache.HttpCacheEntry;
-import org.apache.hc.client5.http.methods.CloseableHttpResponse;
 import org.apache.hc.client5.http.methods.HttpExecutionAware;
-import org.apache.hc.client5.http.methods.HttpRequestWrapper;
+import org.apache.hc.client5.http.methods.RoutedHttpRequest;
 import org.apache.hc.client5.http.protocol.ClientProtocolException;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
 import org.apache.hc.client5.http.utils.DateUtils;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HeaderElement;
 import org.apache.hc.core5.http.HeaderElements;
 import org.apache.hc.core5.http.HttpHeaders;
 import org.apache.hc.core5.http.HttpHost;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.ProtocolVersion;
-import org.apache.hc.core5.http.entity.BasicHttpEntity;
-import org.apache.hc.core5.http.entity.ByteArrayEntity;
+import org.apache.hc.core5.http.io.entity.BasicHttpEntity;
+import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
+import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
+import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
 import org.apache.hc.core5.http.message.BasicHeader;
-import org.apache.hc.core5.http.message.BasicHttpRequest;
-import org.apache.hc.core5.http.message.BasicHttpResponse;
+import org.apache.hc.core5.http.message.MessageSupport;
 import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.junit.Assert;
@@ -78,13 +79,12 @@ public class TestProtocolRequirements ex
     public void testCacheMissOnGETUsesOriginResponse() throws Exception {
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         eqRequest(request),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
         Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result));
@@ -106,18 +106,17 @@ public class TestProtocolRequirements ex
 
         // tunnel behavior: I don't muck with request or response in
         // any way
-        request = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 2, 13)), host);
+        request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("GET", "/foo"), route);
+        request.setVersion(new ProtocolVersion("HTTP", 2, 13));
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         eqRequest(request),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
         Assert.assertSame(originResponse, result);
@@ -126,21 +125,22 @@ public class TestProtocolRequirements ex
     @Test
     public void testHigher1_XProtocolVersionsDowngradeTo1_1() throws Exception {
 
-        request = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 2)), host);
-
-        final HttpRequestWrapper downgraded = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1), host);
+        request = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/foo"), route);
+        request.setVersion(new ProtocolVersion("HTTP", 1, 2));
+
+        final RoutedHttpRequest downgraded = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/foo"), route);
+        downgraded.setVersion(HttpVersion.HTTP_1_1);
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         eqRequest(downgraded),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
         Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result));
@@ -158,20 +158,21 @@ public class TestProtocolRequirements ex
     @Test
     public void testRequestsWithLowerProtocolVersionsGetUpgradedTo1_1() throws Exception {
 
-        request = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 0)), host);
-        final HttpRequestWrapper upgraded = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1), host);
+        request = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/foo"), route);
+        request.setVersion(new ProtocolVersion("HTTP", 1, 0));
+        final RoutedHttpRequest upgraded = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/foo"), route);
+        upgraded.setVersion(HttpVersion.HTTP_1_1);
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         eqRequest(upgraded),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
         Assert.assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result));
@@ -187,8 +188,8 @@ public class TestProtocolRequirements ex
      */
     @Test
     public void testLowerOriginResponsesUpgradedToOurVersion1_1() throws Exception {
-        originResponse = Proxies.enhanceResponse(
-                new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 2), HttpStatus.SC_OK, "OK"));
+        originResponse = new BasicClassicHttpResponse(HttpStatus.SC_OK, "OK");
+        originResponse.setVersion(new ProtocolVersion("HTTP", 1, 2));
         originResponse.setHeader("Date", DateUtils.formatDate(new Date()));
         originResponse.setHeader("Server", "MockOrigin/1.0");
         originResponse.setEntity(body);
@@ -197,35 +198,34 @@ public class TestProtocolRequirements ex
         // to check the protocol version that comes out the other end
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
-        Assert.assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion());
+        Assert.assertEquals(HttpVersion.HTTP_1_1, result.getVersion());
     }
 
     @Test
     public void testResponseToA1_0RequestShouldUse1_1() throws Exception {
-        request = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 0)), host);
+        request = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/foo"), route);
+        request.setVersion(new ProtocolVersion("HTTP", 1, 0));
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
-        Assert.assertEquals(HttpVersion.HTTP_1_1, result.getProtocolVersion());
+        Assert.assertEquals(HttpVersion.HTTP_1_1, result.getVersion());
     }
 
     /*
@@ -234,25 +234,26 @@ public class TestProtocolRequirements ex
      */
     @Test
     public void testForwardsUnknownHeadersOnRequestsFromHigherProtocolVersions() throws Exception {
-        request = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 2)), host);
+        request = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/foo"), route);
+        request.setVersion(new ProtocolVersion("HTTP", 1, 2));
         request.removeHeaders("Connection");
         request.addHeader("X-Unknown-Header", "some-value");
 
-        final HttpRequestWrapper downgraded = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest downgraded = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/foo"), route);
+        downgraded.setVersion(HttpVersion.HTTP_1_1);
         downgraded.removeHeaders("Connection");
         downgraded.addHeader("X-Unknown-Header", "some-value");
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
                         eqRequest(downgraded),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
 
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
 
         verifyMocks();
     }
@@ -266,18 +267,18 @@ public class TestProtocolRequirements ex
 
         originResponse.setHeader("Transfer-Encoding", "identity");
 
-        request = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/foo", new ProtocolVersion("HTTP", 1, 0)), host);
+        final ClassicHttpRequest originalRequest = new BasicClassicHttpRequest("GET", "/foo");
+        originalRequest.setVersion(new ProtocolVersion("HTTP", 1, 0));
+        request = RoutedHttpRequest.adapt(originalRequest, route);
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
 
@@ -298,23 +299,22 @@ public class TestProtocolRequirements ex
      * these field values when a message is forwarded."
      * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
      */
-    private void testOrderOfMultipleHeadersIsPreservedOnRequests(final String h, final HttpRequestWrapper request)
+    private void testOrderOfMultipleHeadersIsPreservedOnRequests(final String h, final RoutedHttpRequest request)
             throws Exception {
-        final Capture<HttpRequestWrapper> reqCapture = new Capture<>();
+        final Capture<RoutedHttpRequest> reqCapture = new Capture<>();
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
                         EasyMock.capture(reqCapture),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
 
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
 
         verifyMocks();
 
-        final HttpRequest forwarded = reqCapture.getValue();
+        final ClassicHttpRequest forwarded = reqCapture.getValue();
         Assert.assertNotNull(forwarded);
         final String expected = HttpTestUtils.getCanonicalHeaderValue(request, h);
         final String actual = HttpTestUtils.getCanonicalHeaderValue(forwarded, h);
@@ -354,13 +354,12 @@ public class TestProtocolRequirements ex
 
     @Test
     public void testOrderOfMultipleAllowHeadersIsPreservedOnRequests() throws Exception {
-        final BasicHttpRequest put = new BasicHttpRequest("PUT", "/",
-                HttpVersion.HTTP_1_1);
+        final BasicClassicHttpRequest put = new BasicClassicHttpRequest("PUT", "/");
         put.setEntity(body);
         put.addHeader("Allow", "GET, HEAD");
         put.addHeader("Allow", "DELETE");
         put.addHeader("Content-Length", "128");
-        testOrderOfMultipleHeadersIsPreservedOnRequests("Allow", HttpRequestWrapper.wrap(put, host));
+        testOrderOfMultipleHeadersIsPreservedOnRequests("Allow", RoutedHttpRequest.adapt(put, route));
     }
 
     @Test
@@ -372,35 +371,32 @@ public class TestProtocolRequirements ex
 
     @Test
     public void testOrderOfMultipleContentEncodingHeadersIsPreservedOnRequests() throws Exception {
-        final BasicHttpRequest post = new BasicHttpRequest("POST", "/",
-                HttpVersion.HTTP_1_1);
+        final BasicClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/");
         post.setEntity(body);
         post.addHeader("Content-Encoding", "gzip");
         post.addHeader("Content-Encoding", "compress");
         post.addHeader("Content-Length", "128");
-        testOrderOfMultipleHeadersIsPreservedOnRequests("Content-Encoding", HttpRequestWrapper.wrap(post, host));
+        testOrderOfMultipleHeadersIsPreservedOnRequests("Content-Encoding", RoutedHttpRequest.adapt(post, route));
     }
 
     @Test
     public void testOrderOfMultipleContentLanguageHeadersIsPreservedOnRequests() throws Exception {
-        final BasicHttpRequest post = new BasicHttpRequest("POST", "/",
-                HttpVersion.HTTP_1_1);
+        final BasicClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/");
         post.setEntity(body);
         post.addHeader("Content-Language", "mi");
         post.addHeader("Content-Language", "en");
         post.addHeader("Content-Length", "128");
-        testOrderOfMultipleHeadersIsPreservedOnRequests("Content-Language", HttpRequestWrapper.wrap(post, host));
+        testOrderOfMultipleHeadersIsPreservedOnRequests("Content-Language", RoutedHttpRequest.adapt(post, route));
     }
 
     @Test
     public void testOrderOfMultipleExpectHeadersIsPreservedOnRequests() throws Exception {
-        final BasicHttpRequest post = new BasicHttpRequest("POST", "/",
-                HttpVersion.HTTP_1_1);
+        final BasicClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/");
         post.setEntity(body);
         post.addHeader("Expect", "100-continue");
         post.addHeader("Expect", "x-expect=true");
         post.addHeader("Content-Length", "128");
-        testOrderOfMultipleHeadersIsPreservedOnRequests("Expect", HttpRequestWrapper.wrap(post, host));
+        testOrderOfMultipleHeadersIsPreservedOnRequests("Expect", RoutedHttpRequest.adapt(post, route));
     }
 
     @Test
@@ -427,13 +423,12 @@ public class TestProtocolRequirements ex
     private void testOrderOfMultipleHeadersIsPreservedOnResponses(final String h) throws Exception {
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
 
@@ -445,8 +440,7 @@ public class TestProtocolRequirements ex
 
     @Test
     public void testOrderOfMultipleAllowHeadersIsPreservedOnResponses() throws Exception {
-        originResponse = Proxies.enhanceResponse(
-                new BasicHttpResponse(HttpVersion.HTTP_1_1, 405, "Method Not Allowed"));
+        originResponse = new BasicClassicHttpResponse(405, "Method Not Allowed");
         originResponse.addHeader("Allow", "HEAD");
         originResponse.addHeader("Allow", "DELETE");
         testOrderOfMultipleHeadersIsPreservedOnResponses("Allow");
@@ -506,8 +500,7 @@ public class TestProtocolRequirements ex
 
         emptyMockCacheExpectsNoPuts();
 
-        originResponse = Proxies.enhanceResponse(
-                new BasicHttpResponse(HttpVersion.HTTP_1_1, code, "Moo"));
+        originResponse = new BasicClassicHttpResponse(code, "Moo");
         originResponse.setHeader("Date", DateUtils.formatDate(new Date()));
         originResponse.setHeader("Server", "MockOrigin/1.0");
         originResponse.setHeader("Cache-Control", "max-age=3600");
@@ -515,14 +508,13 @@ public class TestProtocolRequirements ex
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
 
         // in particular, there were no storage calls on the cache
         verifyMocks();
@@ -556,20 +548,19 @@ public class TestProtocolRequirements ex
     @Test
     public void testUnknownHeadersOnRequestsAreForwarded() throws Exception {
         request.addHeader("X-Unknown-Header", "blahblah");
-        final Capture<HttpRequestWrapper> reqCap = new Capture<>();
+        final Capture<RoutedHttpRequest> reqCap = new Capture<>();
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
                         EasyMock.capture(reqCap),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
 
         verifyMocks();
-        final HttpRequest forwarded = reqCap.getValue();
+        final ClassicHttpRequest forwarded = reqCap.getValue();
         final Header[] hdrs = forwarded.getHeaders("X-Unknown-Header");
         Assert.assertEquals(1, hdrs.length);
         Assert.assertEquals("blahblah", hdrs[0].getValue());
@@ -580,14 +571,13 @@ public class TestProtocolRequirements ex
         originResponse.addHeader("X-Unknown-Header", "blahblah");
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
         final Header[] hdrs = result.getHeaders("X-Unknown-Header");
@@ -604,35 +594,33 @@ public class TestProtocolRequirements ex
      */
     @Test
     public void testRequestsExpecting100ContinueBehaviorShouldSetExpectHeader() throws Exception {
-        final BasicHttpRequest post = new BasicHttpRequest(
-                "POST", "/", HttpVersion.HTTP_1_1);
+        final BasicClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/");
         post.setHeader(HttpHeaders.EXPECT, HeaderElements.CONTINUE);
         post.setHeader("Content-Length", "128");
         post.setEntity(new BasicHttpEntity());
 
-        final Capture<HttpRequestWrapper> reqCap = new Capture<>();
+        final Capture<RoutedHttpRequest> reqCap = new Capture<>();
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         EasyMock.capture(reqCap),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        impl.execute(route, HttpRequestWrapper.wrap(post, host), context, null);
+        impl.execute(RoutedHttpRequest.adapt(post, route), context, null);
 
         verifyMocks();
 
-        final HttpRequestWrapper forwarded = reqCap.getValue();
+        final RoutedHttpRequest forwarded = reqCap.getValue();
         boolean foundExpect = false;
-        for (final Header h : forwarded.getHeaders("Expect")) {
-            for (final HeaderElement elt : h.getElements()) {
-                if ("100-continue".equalsIgnoreCase(elt.getName())) {
-                    foundExpect = true;
-                    break;
-                }
+        final Iterator<HeaderElement> it = MessageSupport.iterate(forwarded, HttpHeaders.EXPECT);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if ("100-continue".equalsIgnoreCase(elt.getName())) {
+                foundExpect = true;
+                break;
             }
         }
         Assert.assertTrue(foundExpect);
@@ -648,34 +636,32 @@ public class TestProtocolRequirements ex
     @Test
     public void testRequestsNotExpecting100ContinueBehaviorShouldNotSetExpectContinueHeader()
             throws Exception {
-        final BasicHttpRequest post = new BasicHttpRequest(
-                "POST", "/", HttpVersion.HTTP_1_1);
+        final BasicClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/");
         post.setHeader("Content-Length", "128");
         post.setEntity(new BasicHttpEntity());
 
-        final Capture<HttpRequestWrapper> reqCap = new Capture<>();
+        final Capture<RoutedHttpRequest> reqCap = new Capture<>();
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         EasyMock.capture(reqCap),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        impl.execute(route, HttpRequestWrapper.wrap(post, host), context, null);
+        impl.execute(RoutedHttpRequest.adapt(post, route), context, null);
 
         verifyMocks();
 
-        final HttpRequestWrapper forwarded = reqCap.getValue();
+        final RoutedHttpRequest forwarded = reqCap.getValue();
         boolean foundExpect = false;
-        for (final Header h : forwarded.getHeaders("Expect")) {
-            for (final HeaderElement elt : h.getElements()) {
-                if ("100-continue".equalsIgnoreCase(elt.getName())) {
-                    foundExpect = true;
-                    break;
-                }
+        final Iterator<HeaderElement> it = MessageSupport.iterate(forwarded, HttpHeaders.EXPECT);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if ("100-continue".equalsIgnoreCase(elt.getName())) {
+                foundExpect = true;
+                break;
             }
         }
         Assert.assertFalse(foundExpect);
@@ -691,26 +677,25 @@ public class TestProtocolRequirements ex
     @Test
     public void testExpect100ContinueIsNotSentIfThereIsNoRequestBody() throws Exception {
         request.addHeader("Expect", "100-continue");
-        final Capture<HttpRequestWrapper> reqCap = new Capture<>();
+        final Capture<RoutedHttpRequest> reqCap = new Capture<>();
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         EasyMock.capture(reqCap),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
         verifyMocks();
-        final HttpRequest forwarded = reqCap.getValue();
+        final ClassicHttpRequest forwarded = reqCap.getValue();
         boolean foundExpectContinue = false;
 
-        for (final Header h : forwarded.getHeaders("Expect")) {
-            for (final HeaderElement elt : h.getElements()) {
-                if ("100-continue".equalsIgnoreCase(elt.getName())) {
-                    foundExpectContinue = true;
-                    break;
-                }
+        final Iterator<HeaderElement> it = MessageSupport.iterate(forwarded, HttpHeaders.EXPECT);
+        while (it.hasNext()) {
+            final HeaderElement elt = it.next();
+            if ("100-continue".equalsIgnoreCase(elt.getName())) {
+                foundExpectContinue = true;
+                break;
             }
         }
         Assert.assertFalse(foundExpectContinue);
@@ -749,17 +734,15 @@ public class TestProtocolRequirements ex
     public void test100ContinueResponsesAreNotForwardedTo1_0ClientsWhoDidNotAskForThem()
             throws Exception {
 
-        final BasicHttpRequest post = new BasicHttpRequest("POST", "/",
-                new ProtocolVersion("HTTP", 1, 0));
+        final BasicClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/");
+        post.setVersion(new ProtocolVersion("HTTP", 1, 0));
         post.setEntity(body);
         post.setHeader("Content-Length", "128");
 
-        originResponse = Proxies.enhanceResponse(
-                new BasicHttpResponse(HttpVersion.HTTP_1_1, 100, "Continue"));
+        originResponse = new BasicClassicHttpResponse(100, "Continue");
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
@@ -767,7 +750,7 @@ public class TestProtocolRequirements ex
         try {
             // if a 100 response gets up to us from the HttpClient
             // backend, we can't really handle it at that point
-            impl.execute(route, HttpRequestWrapper.wrap(post, host), context, null);
+            impl.execute(RoutedHttpRequest.adapt(post, route), context, null);
             Assert.fail("should have thrown an exception");
         } catch (final ClientProtocolException expected) {
         }
@@ -783,19 +766,18 @@ public class TestProtocolRequirements ex
     @Test
     public void testResponsesToOPTIONSAreNotCacheable() throws Exception {
         emptyMockCacheExpectsNoPuts();
-        request = HttpRequestWrapper.wrap(new BasicHttpRequest("OPTIONS", "/", HttpVersion.HTTP_1_1), host);
+        request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("OPTIONS", "/"), route);
         originResponse.addHeader("Cache-Control", "max-age=3600");
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
 
         verifyMocks();
     }
@@ -809,19 +791,18 @@ public class TestProtocolRequirements ex
     @Test
     public void test200ResponseToOPTIONSWithNoBodyShouldIncludeContentLengthZero() throws Exception {
 
-        request = HttpRequestWrapper.wrap(new BasicHttpRequest("OPTIONS", "/", HttpVersion.HTTP_1_1), host);
+        request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("OPTIONS", "/"), route);
         originResponse.setEntity(null);
         originResponse.setHeader("Content-Length", "0");
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
         final Header contentLength = result.getFirstHeader("Content-Length");
@@ -841,11 +822,11 @@ public class TestProtocolRequirements ex
     @Test
     public void testDoesNotForwardOPTIONSWhenMaxForwardsIsZeroOnAbsoluteURIRequest()
             throws Exception {
-        request = HttpRequestWrapper.wrap(new BasicHttpRequest("OPTIONS", "*", HttpVersion.HTTP_1_1), host);
+        request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("OPTIONS", "*"), route);
         request.setHeader("Max-Forwards", "0");
 
         replayMocks();
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
         verifyMocks();
     }
 
@@ -858,23 +839,22 @@ public class TestProtocolRequirements ex
     @Test
     public void testDecrementsMaxForwardsWhenForwardingOPTIONSRequest() throws Exception {
 
-        request = HttpRequestWrapper.wrap(new BasicHttpRequest("OPTIONS", "*", HttpVersion.HTTP_1_1), host);
+        request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("OPTIONS", "*"), route);
         request.setHeader("Max-Forwards", "7");
 
-        final Capture<HttpRequestWrapper> cap = new Capture<>();
+        final Capture<RoutedHttpRequest> cap = new Capture<>();
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         EasyMock.capture(cap),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
         verifyMocks();
 
-        final HttpRequest captured = cap.getValue();
+        final ClassicHttpRequest captured = cap.getValue();
         Assert.assertEquals("6", captured.getFirstHeader("Max-Forwards").getValue());
     }
 
@@ -886,20 +866,19 @@ public class TestProtocolRequirements ex
      */
     @Test
     public void testDoesNotAddAMaxForwardsHeaderToForwardedOPTIONSRequests() throws Exception {
-        request = HttpRequestWrapper.wrap(new BasicHttpRequest("OPTIONS", "/", HttpVersion.HTTP_1_1), host);
-        final Capture<HttpRequestWrapper> reqCap = new Capture<>();
+        request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("OPTIONS", "/"), route);
+        final Capture<RoutedHttpRequest> reqCap = new Capture<>();
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         EasyMock.capture(reqCap),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
         verifyMocks();
 
-        final HttpRequest forwarded = reqCap.getValue();
+        final ClassicHttpRequest forwarded = reqCap.getValue();
         Assert.assertNull(forwarded.getFirstHeader("Max-Forwards"));
     }
 
@@ -911,17 +890,16 @@ public class TestProtocolRequirements ex
      */
     @Test
     public void testResponseToAHEADRequestMustNotHaveABody() throws Exception {
-        request = HttpRequestWrapper.wrap(new BasicHttpRequest("HEAD", "/", HttpVersion.HTTP_1_1), host);
+        request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("HEAD", "/"), route);
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
 
@@ -940,52 +918,48 @@ public class TestProtocolRequirements ex
             final String oldVal, final String newVal) throws Exception {
 
         // put something cacheable in the cache
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
-        final HttpResponse resp1 = HttpTestUtils.make200Response();
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
+        final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
         resp1.addHeader("Cache-Control", "max-age=3600");
         resp1.setHeader(eHeader, oldVal);
 
         // get a head that penetrates the cache
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("HEAD", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("HEAD", "/"), route);
         req2.addHeader("Cache-Control", "no-cache");
-        final HttpResponse resp2 = HttpTestUtils.make200Response();
+        final ClassicHttpResponse resp2 = HttpTestUtils.make200Response();
         resp2.setEntity(null);
         resp2.setHeader(eHeader, newVal);
 
         // next request doesn't tolerate stale entry
-        final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req3 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req3.addHeader("Cache-Control", "max-stale=0");
-        final HttpResponse resp3 = HttpTestUtils.make200Response();
+        final ClassicHttpResponse resp3 = HttpTestUtils.make200Response();
         resp3.setHeader(eHeader, newVal);
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         eqRequest(req1),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         eqRequest(req2),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
-                        EasyMock.<HttpExecutionAware>isNull())).andReturn(
-                                Proxies.enhanceResponse(resp3));
+                        EasyMock.<HttpExecutionAware>isNull())).andReturn(resp3);
 
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        impl.execute(route, req2, context, null);
-        impl.execute(route, req3, context, null);
+        impl.execute(req1, context, null);
+        impl.execute(req2, context, null);
+        impl.execute(req3, context, null);
 
         verifyMocks();
     }
@@ -1028,8 +1002,7 @@ public class TestProtocolRequirements ex
     public void testResponsesToPOSTWithoutCacheControlOrExpiresAreNotCached() throws Exception {
         emptyMockCacheExpectsNoPuts();
 
-        final BasicHttpRequest post = new BasicHttpRequest("POST", "/",
-                HttpVersion.HTTP_1_1);
+        final BasicClassicHttpRequest post = new BasicClassicHttpRequest("POST", "/");
         post.setHeader("Content-Length", "128");
         post.setEntity(HttpTestUtils.makeBody(128));
 
@@ -1038,14 +1011,13 @@ public class TestProtocolRequirements ex
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        impl.execute(route, HttpRequestWrapper.wrap(post, host), context, null);
+        impl.execute(RoutedHttpRequest.adapt(post, route), context, null);
 
         verifyMocks();
     }
@@ -1059,8 +1031,7 @@ public class TestProtocolRequirements ex
     public void testResponsesToPUTsAreNotCached() throws Exception {
         emptyMockCacheExpectsNoPuts();
 
-        final BasicHttpRequest put = new BasicHttpRequest("PUT", "/",
-                HttpVersion.HTTP_1_1);
+        final BasicClassicHttpRequest put = new BasicClassicHttpRequest("PUT", "/");
         put.setEntity(HttpTestUtils.makeBody(128));
         put.addHeader("Content-Length", "128");
 
@@ -1068,14 +1039,13 @@ public class TestProtocolRequirements ex
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        impl.execute(route, HttpRequestWrapper.wrap(put, host), context, null);
+        impl.execute(RoutedHttpRequest.adapt(put, route), context, null);
 
         verifyMocks();
     }
@@ -1089,19 +1059,18 @@ public class TestProtocolRequirements ex
     public void testResponsesToDELETEsAreNotCached() throws Exception {
         emptyMockCacheExpectsNoPuts();
 
-        request = HttpRequestWrapper.wrap(new BasicHttpRequest("DELETE", "/", HttpVersion.HTTP_1_1), host);
+        request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("DELETE", "/"), route);
         originResponse.setHeader("Cache-Control", "max-age=3600");
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
 
         verifyMocks();
     }
@@ -1113,25 +1082,23 @@ public class TestProtocolRequirements ex
      */
     @Test
     public void testForwardedTRACERequestsDoNotIncludeAnEntity() throws Exception {
-        final BasicHttpRequest trace = new BasicHttpRequest("TRACE", "/",
-                HttpVersion.HTTP_1_1);
+        final BasicClassicHttpRequest trace = new BasicClassicHttpRequest("TRACE", "/");
         trace.setEntity(HttpTestUtils.makeBody(entityLength));
         trace.setHeader("Content-Length", Integer.toString(entityLength));
 
-        final Capture<HttpRequestWrapper> reqCap = new Capture<>();
+        final Capture<RoutedHttpRequest> reqCap = new Capture<>();
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.eq(route),
                         EasyMock.capture(reqCap),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
-        impl.execute(route, HttpRequestWrapper.wrap(trace, host), context, null);
+        impl.execute(RoutedHttpRequest.adapt(trace, route), context, null);
         verifyMocks();
 
-        final HttpRequest bodyReq = reqCap.getValue();
+        final ClassicHttpRequest bodyReq = reqCap.getValue();
         Assert.assertTrue(bodyReq.getEntity() == null || bodyReq.getEntity().getContentLength() == 0);
     }
 
@@ -1144,19 +1111,18 @@ public class TestProtocolRequirements ex
     public void testResponsesToTRACEsAreNotCached() throws Exception {
         emptyMockCacheExpectsNoPuts();
 
-        request = HttpRequestWrapper.wrap(new BasicHttpRequest("TRACE", "/", HttpVersion.HTTP_1_1), host);
+        request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("TRACE", "/"), route);
         originResponse.setHeader("Cache-Control", "max-age=3600");
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
 
         verifyMocks();
     }
@@ -1169,20 +1135,18 @@ public class TestProtocolRequirements ex
      */
     @Test
     public void test204ResponsesDoNotContainMessageBodies() throws Exception {
-        originResponse = Proxies.enhanceResponse(
-                new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NO_CONTENT, "No Content"));
+        originResponse = new BasicClassicHttpResponse(HttpStatus.SC_NO_CONTENT, "No Content");
         originResponse.setEntity(HttpTestUtils.makeBody(entityLength));
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
 
@@ -1196,20 +1160,18 @@ public class TestProtocolRequirements ex
      */
     @Test
     public void test205ResponsesDoNotContainMessageBodies() throws Exception {
-        originResponse = Proxies.enhanceResponse(
-                new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_RESET_CONTENT, "Reset Content"));
+        originResponse = new BasicClassicHttpResponse(HttpStatus.SC_RESET_CONTENT, "Reset Content");
         originResponse.setEntity(HttpTestUtils.makeBody(entityLength));
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
 
@@ -1239,26 +1201,26 @@ public class TestProtocolRequirements ex
     public void test206ResponseGeneratedFromCacheMustHaveContentRangeOrMultipartByteRangesContentType()
             throws Exception {
 
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
-        final HttpResponse resp1 = HttpTestUtils.make200Response();
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
+        final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
         resp1.setHeader("ETag", "\"etag\"");
         resp1.setHeader("Cache-Control", "max-age=3600");
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.setHeader("Range", "bytes=0-50");
 
         backendExpectsAnyRequestAndReturn(resp1).times(1, 2);
 
         replayMocks();
-        impl.execute(route, req1, context, null);
-        final HttpResponse result = impl.execute(route, req2, context, null);
+        impl.execute(req1, context, null);
+        final ClassicHttpResponse result = impl.execute(req2, context, null);
         verifyMocks();
 
-        if (HttpStatus.SC_PARTIAL_CONTENT == result.getStatusLine().getStatusCode()) {
+        if (HttpStatus.SC_PARTIAL_CONTENT == result.getCode()) {
             if (result.getFirstHeader("Content-Range") == null) {
-                final HeaderElement elt = result.getFirstHeader("Content-Type").getElements()[0];
+                final HeaderElement elt = MessageSupport.parse(result.getFirstHeader("Content-Type"))[0];
                 Assert.assertTrue("multipart/byteranges".equalsIgnoreCase(elt.getName()));
                 Assert.assertNotNull(elt.getParameterByName("boundary"));
                 Assert.assertNotNull(elt.getParameterByName("boundary").getValue());
@@ -1271,24 +1233,24 @@ public class TestProtocolRequirements ex
     public void test206ResponseGeneratedFromCacheMustHaveABodyThatMatchesContentLengthHeaderIfPresent()
             throws Exception {
 
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
-        final HttpResponse resp1 = HttpTestUtils.make200Response();
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
+        final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
         resp1.setHeader("ETag", "\"etag\"");
         resp1.setHeader("Cache-Control", "max-age=3600");
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.setHeader("Range", "bytes=0-50");
 
         backendExpectsAnyRequestAndReturn(resp1).times(1, 2);
 
         replayMocks();
-        impl.execute(route, req1, context, null);
-        final HttpResponse result = impl.execute(route, req2, context, null);
+        impl.execute(req1, context, null);
+        final ClassicHttpResponse result = impl.execute(req2, context, null);
         verifyMocks();
 
-        if (HttpStatus.SC_PARTIAL_CONTENT == result.getStatusLine().getStatusCode()) {
+        if (HttpStatus.SC_PARTIAL_CONTENT == result.getCode()) {
             final Header h = result.getFirstHeader("Content-Length");
             if (h != null) {
                 final int contentLength = Integer.parseInt(h.getValue());
@@ -1305,24 +1267,24 @@ public class TestProtocolRequirements ex
 
     @Test
     public void test206ResponseGeneratedFromCacheMustHaveDateHeader() throws Exception {
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
-        final HttpResponse resp1 = HttpTestUtils.make200Response();
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
+        final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
         resp1.setHeader("ETag", "\"etag\"");
         resp1.setHeader("Cache-Control", "max-age=3600");
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.setHeader("Range", "bytes=0-50");
 
         backendExpectsAnyRequestAndReturn(resp1).times(1, 2);
 
         replayMocks();
-        impl.execute(route, req1, context, null);
-        final HttpResponse result = impl.execute(route, req2, context, null);
+        impl.execute(req1, context, null);
+        final ClassicHttpResponse result = impl.execute(req2, context, null);
         verifyMocks();
 
-        if (HttpStatus.SC_PARTIAL_CONTENT == result.getStatusLine().getStatusCode()) {
+        if (HttpStatus.SC_PARTIAL_CONTENT == result.getCode()) {
             Assert.assertNotNull(result.getFirstHeader("Date"));
         }
     }
@@ -1330,8 +1292,7 @@ public class TestProtocolRequirements ex
     @Test
     public void test206ResponseReturnedToClientMustHaveDateHeader() throws Exception {
         request.addHeader("Range", "bytes=0-50");
-        originResponse = Proxies.enhanceResponse(
-                new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content"));
+        originResponse = new BasicClassicHttpResponse(HttpStatus.SC_PARTIAL_CONTENT, "Partial Content");
         originResponse.setHeader("Date", DateUtils.formatDate(new Date()));
         originResponse.setHeader("Server", "MockOrigin/1.0");
         originResponse.setEntity(HttpTestUtils.makeBody(500));
@@ -1340,15 +1301,14 @@ public class TestProtocolRequirements ex
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
-        Assert.assertTrue(result.getStatusLine().getStatusCode() != HttpStatus.SC_PARTIAL_CONTENT
+        final ClassicHttpResponse result = impl.execute(request, context, null);
+        Assert.assertTrue(result.getCode() != HttpStatus.SC_PARTIAL_CONTENT
                 || result.getFirstHeader("Date") != null);
 
         verifyMocks();
@@ -1356,52 +1316,52 @@ public class TestProtocolRequirements ex
 
     @Test
     public void test206ContainsETagIfA200ResponseWouldHaveIncludedIt() throws Exception {
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
 
         originResponse.addHeader("Cache-Control", "max-age=3600");
         originResponse.addHeader("ETag", "\"etag1\"");
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.addHeader("Range", "bytes=0-50");
 
         backendExpectsAnyRequest().andReturn(originResponse).times(1, 2);
 
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        final HttpResponse result = impl.execute(route, req2, context, null);
+        impl.execute(req1, context, null);
+        final ClassicHttpResponse result = impl.execute(req2, context, null);
 
         verifyMocks();
 
-        if (result.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT) {
+        if (result.getCode() == HttpStatus.SC_PARTIAL_CONTENT) {
             Assert.assertNotNull(result.getFirstHeader("ETag"));
         }
     }
 
     @Test
     public void test206ContainsContentLocationIfA200ResponseWouldHaveIncludedIt() throws Exception {
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
 
         originResponse.addHeader("Cache-Control", "max-age=3600");
         originResponse.addHeader("Content-Location", "http://foo.example.com/other/url");
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.addHeader("Range", "bytes=0-50");
 
         backendExpectsAnyRequest().andReturn(originResponse).times(1, 2);
 
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        final HttpResponse result = impl.execute(route, req2, context, null);
+        impl.execute(req1, context, null);
+        final ClassicHttpResponse result = impl.execute(req2, context, null);
 
         verifyMocks();
 
-        if (result.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT) {
+        if (result.getCode() == HttpStatus.SC_PARTIAL_CONTENT) {
             Assert.assertNotNull(result.getFirstHeader("Content-Location"));
         }
     }
@@ -1409,8 +1369,8 @@ public class TestProtocolRequirements ex
     @Test
     public void test206ResponseIncludesVariantHeadersIfValueMightDiffer() throws Exception {
 
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req1.addHeader("Accept-Encoding", "gzip");
 
         final Date now = new Date();
@@ -1419,21 +1379,21 @@ public class TestProtocolRequirements ex
         originResponse.addHeader("Expires", DateUtils.formatDate(inOneHour));
         originResponse.addHeader("Vary", "Accept-Encoding");
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.addHeader("Cache-Control", "no-cache");
         req2.addHeader("Accept-Encoding", "gzip");
         final Date nextSecond = new Date(now.getTime() + 1000L);
         final Date inTwoHoursPlusASec = new Date(now.getTime() + 2 * 3600 * 1000L + 1000L);
 
-        final HttpResponse originResponse2 = HttpTestUtils.make200Response();
+        final ClassicHttpResponse originResponse2 = HttpTestUtils.make200Response();
         originResponse2.setHeader("Date", DateUtils.formatDate(nextSecond));
         originResponse2.setHeader("Cache-Control", "max-age=7200");
         originResponse2.setHeader("Expires", DateUtils.formatDate(inTwoHoursPlusASec));
         originResponse2.setHeader("Vary", "Accept-Encoding");
 
-        final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req3 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req3.addHeader("Range", "bytes=0-50");
         req3.addHeader("Accept-Encoding", "gzip");
 
@@ -1442,13 +1402,13 @@ public class TestProtocolRequirements ex
 
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        impl.execute(route, req2, context, null);
-        final HttpResponse result = impl.execute(route, req3, context, null);
+        impl.execute(req1, context, null);
+        impl.execute(req2, context, null);
+        final ClassicHttpResponse result = impl.execute(req3, context, null);
 
         verifyMocks();
 
-        if (result.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT) {
+        if (result.getCode() == HttpStatus.SC_PARTIAL_CONTENT) {
             Assert.assertNotNull(result.getFirstHeader("Expires"));
             Assert.assertNotNull(result.getFirstHeader("Cache-Control"));
             Assert.assertNotNull(result.getFirstHeader("Vary"));
@@ -1467,12 +1427,12 @@ public class TestProtocolRequirements ex
     public void test206ResponseToConditionalRangeRequestDoesNotIncludeOtherEntityHeaders()
             throws Exception {
 
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
 
         final Date now = new Date();
         final Date oneHourAgo = new Date(now.getTime() - 3600 * 1000L);
-        originResponse = Proxies.enhanceResponse(HttpTestUtils.make200Response());
+        originResponse = HttpTestUtils.make200Response();
         originResponse.addHeader("Allow", "GET,HEAD");
         originResponse.addHeader("Cache-Control", "max-age=3600");
         originResponse.addHeader("Content-Language", "en");
@@ -1483,8 +1443,8 @@ public class TestProtocolRequirements ex
         originResponse.addHeader("Last-Modified", DateUtils.formatDate(oneHourAgo));
         originResponse.addHeader("ETag", "W/\"weak-tag\"");
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.addHeader("If-Range", "W/\"weak-tag\"");
         req2.addHeader("Range", "bytes=0-50");
 
@@ -1492,12 +1452,12 @@ public class TestProtocolRequirements ex
 
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        final HttpResponse result = impl.execute(route, req2, context, null);
+        impl.execute(req1, context, null);
+        final ClassicHttpResponse result = impl.execute(req2, context, null);
 
         verifyMocks();
 
-        if (result.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT) {
+        if (result.getCode() == HttpStatus.SC_PARTIAL_CONTENT) {
             Assert.assertNull(result.getFirstHeader("Allow"));
             Assert.assertNull(result.getFirstHeader("Content-Encoding"));
             Assert.assertNull(result.getFirstHeader("Content-Language"));
@@ -1517,8 +1477,8 @@ public class TestProtocolRequirements ex
     public void test206ResponseToIfRangeWithStrongValidatorReturnsAllEntityHeaders()
             throws Exception {
 
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
 
         final Date now = new Date();
         final Date oneHourAgo = new Date(now.getTime() - 3600 * 1000L);
@@ -1532,8 +1492,8 @@ public class TestProtocolRequirements ex
         originResponse.addHeader("Last-Modified", DateUtils.formatDate(oneHourAgo));
         originResponse.addHeader("ETag", "\"strong-tag\"");
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.addHeader("If-Range", "\"strong-tag\"");
         req2.addHeader("Range", "bytes=0-50");
 
@@ -1541,12 +1501,12 @@ public class TestProtocolRequirements ex
 
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        final HttpResponse result = impl.execute(route, req2, context, null);
+        impl.execute(req1, context, null);
+        final ClassicHttpResponse result = impl.execute(req2, context, null);
 
         verifyMocks();
 
-        if (result.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT) {
+        if (result.getCode() == HttpStatus.SC_PARTIAL_CONTENT) {
             Assert.assertEquals("GET,HEAD", result.getFirstHeader("Allow").getValue());
             Assert.assertEquals("max-age=3600", result.getFirstHeader("Cache-Control").getValue());
             Assert.assertEquals("en", result.getFirstHeader("Content-Language").getValue());
@@ -1571,9 +1531,9 @@ public class TestProtocolRequirements ex
 
         final Date now = new Date();
 
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
-        final HttpResponse resp1 = HttpTestUtils.make200Response();
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
+        final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
         resp1.setHeader("Cache-Control", "max-age=3600");
         resp1.setHeader("ETag", "\"etag1\"");
         final byte[] bytes1 = new byte[128];
@@ -1582,13 +1542,13 @@ public class TestProtocolRequirements ex
         }
         resp1.setEntity(new ByteArrayEntity(bytes1));
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.setHeader("Cache-Control", "no-cache");
         req2.setHeader("Range", "bytes=0-50");
 
         final Date inOneSecond = new Date(now.getTime() + 1000L);
-        final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT,
+        final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_PARTIAL_CONTENT,
                 "Partial Content");
         resp2.setHeader("Date", DateUtils.formatDate(inOneSecond));
         resp2.setHeader("Server", resp1.getFirstHeader("Server").getValue());
@@ -1601,9 +1561,9 @@ public class TestProtocolRequirements ex
         resp2.setEntity(new ByteArrayEntity(bytes2));
 
         final Date inTwoSeconds = new Date(now.getTime() + 2000L);
-        final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
-        final HttpResponse resp3 = HttpTestUtils.make200Response();
+        final RoutedHttpRequest req3 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
+        final ClassicHttpResponse resp3 = HttpTestUtils.make200Response();
         resp3.setHeader("Date", DateUtils.formatDate(inTwoSeconds));
         resp3.setHeader("Cache-Control", "max-age=3600");
         resp3.setHeader("ETag", "\"etag2\"");
@@ -1615,30 +1575,24 @@ public class TestProtocolRequirements ex
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
-                        EasyMock.<HttpExecutionAware>isNull())).andReturn(
-                                Proxies.enhanceResponse(resp1));
+                        EasyMock.<HttpExecutionAware>isNull())).andReturn(resp1);
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
-                        EasyMock.<HttpExecutionAware>isNull())).andReturn(
-                                Proxies.enhanceResponse(resp2));
+                        EasyMock.<HttpExecutionAware>isNull())).andReturn(resp2);
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
-                        EasyMock.<HttpExecutionAware>isNull())).andReturn(
-                                Proxies.enhanceResponse(resp3)).times(0, 1);
+                        EasyMock.<HttpExecutionAware>isNull())).andReturn(resp3).times(0, 1);
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        impl.execute(route, req2, context, null);
-        final HttpResponse result = impl.execute(route, req3, context, null);
+        impl.execute(req1, context, null);
+        impl.execute(req2, context, null);
+        final ClassicHttpResponse result = impl.execute(req3, context, null);
 
         verifyMocks();
 
@@ -1664,9 +1618,9 @@ public class TestProtocolRequirements ex
 
         final Date now = new Date();
 
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
-        final HttpResponse resp1 = HttpTestUtils.make200Response();
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
+        final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
         final Date oneHourAgo = new Date(now.getTime() - 3600L);
         resp1.setHeader("Cache-Control", "max-age=3600");
         resp1.setHeader("Last-Modified", DateUtils.formatDate(oneHourAgo));
@@ -1676,13 +1630,13 @@ public class TestProtocolRequirements ex
         }
         resp1.setEntity(new ByteArrayEntity(bytes1));
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.setHeader("Cache-Control", "no-cache");
         req2.setHeader("Range", "bytes=0-50");
 
         final Date inOneSecond = new Date(now.getTime() + 1000L);
-        final HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT,
+        final ClassicHttpResponse resp2 = new BasicClassicHttpResponse(HttpStatus.SC_PARTIAL_CONTENT,
                 "Partial Content");
         resp2.setHeader("Date", DateUtils.formatDate(inOneSecond));
         resp2.setHeader("Server", resp1.getFirstHeader("Server").getValue());
@@ -1695,9 +1649,9 @@ public class TestProtocolRequirements ex
         resp2.setEntity(new ByteArrayEntity(bytes2));
 
         final Date inTwoSeconds = new Date(now.getTime() + 2000L);
-        final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
-        final HttpResponse resp3 = HttpTestUtils.make200Response();
+        final RoutedHttpRequest req3 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
+        final ClassicHttpResponse resp3 = HttpTestUtils.make200Response();
         resp3.setHeader("Date", DateUtils.formatDate(inTwoSeconds));
         resp3.setHeader("Cache-Control", "max-age=3600");
         resp3.setHeader("ETag", "\"etag2\"");
@@ -1709,30 +1663,24 @@ public class TestProtocolRequirements ex
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
-                        EasyMock.<HttpExecutionAware>isNull())).andReturn(
-                                Proxies.enhanceResponse(resp1));
+                        EasyMock.<HttpExecutionAware>isNull())).andReturn(resp1);
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
-                        EasyMock.<HttpExecutionAware>isNull())).andReturn(
-                                Proxies.enhanceResponse(resp2));
+                        EasyMock.<HttpExecutionAware>isNull())).andReturn(resp2);
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
-                        EasyMock.<HttpExecutionAware>isNull())).andReturn(
-                                Proxies.enhanceResponse(resp3)).times(0, 1);
+                        EasyMock.<HttpExecutionAware>isNull())).andReturn(resp3).times(0, 1);
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        impl.execute(route, req2, context, null);
-        final HttpResponse result = impl.execute(route, req3, context, null);
+        impl.execute(req1, context, null);
+        impl.execute(req2, context, null);
+        final ClassicHttpResponse result = impl.execute(req3, context, null);
 
         verifyMocks();
 
@@ -1765,13 +1713,11 @@ public class TestProtocolRequirements ex
         if (!supportsRangeAndContentRangeHeaders(impl)) {
             emptyMockCacheExpectsNoPuts();
 
-            request = HttpRequestWrapper.wrap(
-                    new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+            request = RoutedHttpRequest.adapt(
+                    new BasicClassicHttpRequest("GET", "/"), route);
             request.addHeader("Range", "bytes=0-50");
 
-            originResponse = Proxies.enhanceResponse(
-                    new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT,
-                    "Partial Content"));
+            originResponse = new BasicClassicHttpResponse(HttpStatus.SC_PARTIAL_CONTENT,"Partial Content");
             originResponse.setHeader("Content-Range", "bytes 0-50/128");
             originResponse.setHeader("Cache-Control", "max-age=3600");
             final byte[] bytes = new byte[51];
@@ -1780,14 +1726,12 @@ public class TestProtocolRequirements ex
 
             EasyMock.expect(
                     mockBackend.execute(
-                            EasyMock.isA(HttpRoute.class),
-                            EasyMock.isA(HttpRequestWrapper.class),
+                            EasyMock.isA(RoutedHttpRequest.class),
                             EasyMock.isA(HttpClientContext.class),
-                            EasyMock.<HttpExecutionAware>isNull())).andReturn(
-                                    originResponse);
+                            EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
             replayMocks();
-            impl.execute(route, request, context, null);
+            impl.execute(request, context, null);
             verifyMocks();
         }
     }
@@ -1802,10 +1746,9 @@ public class TestProtocolRequirements ex
     public void test303ResponsesAreNotCached() throws Exception {
         emptyMockCacheExpectsNoPuts();
 
-        request = HttpRequestWrapper.wrap(new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        request = RoutedHttpRequest.adapt(new BasicClassicHttpRequest("GET", "/"), route);
 
-        originResponse = Proxies.enhanceResponse(
-                new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_SEE_OTHER, "See Other"));
+        originResponse = new BasicClassicHttpResponse(HttpStatus.SC_SEE_OTHER, "See Other");
         originResponse.setHeader("Date", DateUtils.formatDate(new Date()));
         originResponse.setHeader("Server", "MockServer/1.0");
         originResponse.setHeader("Cache-Control", "max-age=3600");
@@ -1815,13 +1758,12 @@ public class TestProtocolRequirements ex
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
-        impl.execute(route, request, context, null);
+        impl.execute(request, context, null);
         verifyMocks();
     }
 
@@ -1835,9 +1777,7 @@ public class TestProtocolRequirements ex
     public void test304ResponseDoesNotContainABody() throws Exception {
         request.setHeader("If-None-Match", "\"etag\"");
 
-        originResponse = Proxies.enhanceResponse(
-                new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED,
-                        "Not Modified"));
+        originResponse = new BasicClassicHttpResponse(HttpStatus.SC_NOT_MODIFIED,"Not Modified");
         originResponse.setHeader("Date", DateUtils.formatDate(new Date()));
         originResponse.setHeader("Server", "MockServer/1.0");
         originResponse.setHeader("Content-Length", "128");
@@ -1845,14 +1785,13 @@ public class TestProtocolRequirements ex
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
 
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
 
@@ -1872,22 +1811,19 @@ public class TestProtocolRequirements ex
 
         request.setHeader("If-None-Match", "\"etag\"");
 
-        originResponse = Proxies.enhanceResponse(
-                new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_NOT_MODIFIED,
-                        "Not Modified"));
+        originResponse = new BasicClassicHttpResponse(HttpStatus.SC_NOT_MODIFIED,"Not Modified");
         originResponse.setHeader("Date", DateUtils.formatDate(new Date()));
         originResponse.setHeader("Server", "MockServer/1.0");
         originResponse.setHeader("ETag", "\"etag\"");
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse);
         replayMocks();
 
-        final HttpResponse result = impl.execute(route, request, context, null);
+        final ClassicHttpResponse result = impl.execute(request, context, null);
 
         verifyMocks();
         Assert.assertNotNull(result.getFirstHeader("Date"));
@@ -1896,28 +1832,27 @@ public class TestProtocolRequirements ex
     @Test
     public void test304ResponseGeneratedFromCacheIncludesDateHeader() throws Exception {
 
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         originResponse.setHeader("Cache-Control", "max-age=3600");
         originResponse.setHeader("ETag", "\"etag\"");
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.setHeader("If-None-Match", "\"etag\"");
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse).times(1, 2);
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        final HttpResponse result = impl.execute(route, req2, context, null);
+        impl.execute(req1, context, null);
+        final ClassicHttpResponse result = impl.execute(req2, context, null);
 
         verifyMocks();
-        if (result.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
+        if (result.getCode() == HttpStatus.SC_NOT_MODIFIED) {
             Assert.assertNotNull(result.getFirstHeader("Date"));
         }
     }
@@ -1931,28 +1866,27 @@ public class TestProtocolRequirements ex
      */
     @Test
     public void test304ResponseGeneratedFromCacheIncludesEtagIfOriginResponseDid() throws Exception {
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         originResponse.setHeader("Cache-Control", "max-age=3600");
         originResponse.setHeader("ETag", "\"etag\"");
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.setHeader("If-None-Match", "\"etag\"");
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse).times(1, 2);
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        final HttpResponse result = impl.execute(route, req2, context, null);
+        impl.execute(req1, context, null);
+        final ClassicHttpResponse result = impl.execute(req2, context, null);
 
         verifyMocks();
-        if (result.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
+        if (result.getCode() == HttpStatus.SC_NOT_MODIFIED) {
             Assert.assertNotNull(result.getFirstHeader("ETag"));
         }
     }
@@ -1960,29 +1894,28 @@ public class TestProtocolRequirements ex
     @Test
     public void test304ResponseGeneratedFromCacheIncludesContentLocationIfOriginResponseDid()
             throws Exception {
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         originResponse.setHeader("Cache-Control", "max-age=3600");
         originResponse.setHeader("Content-Location", "http://foo.example.com/other");
         originResponse.setHeader("ETag", "\"etag\"");
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req2.setHeader("If-None-Match", "\"etag\"");
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
                         EasyMock.<HttpExecutionAware>isNull())).andReturn(originResponse).times(1, 2);
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        final HttpResponse result = impl.execute(route, req2, context, null);
+        impl.execute(req1, context, null);
+        final ClassicHttpResponse result = impl.execute(req2, context, null);
 
         verifyMocks();
-        if (result.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
+        if (result.getCode() == HttpStatus.SC_NOT_MODIFIED) {
             Assert.assertNotNull(result.getFirstHeader("Content-Location"));
         }
     }
@@ -2001,57 +1934,53 @@ public class TestProtocolRequirements ex
         final Date now = new Date();
         final Date inTwoHours = new Date(now.getTime() + 2 * 3600 * 1000L);
 
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req1.setHeader("Accept-Encoding", "gzip");
 
-        final HttpResponse resp1 = HttpTestUtils.make200Response();
+        final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
         resp1.setHeader("ETag", "\"v1\"");
         resp1.setHeader("Cache-Control", "max-age=7200");
         resp1.setHeader("Expires", DateUtils.formatDate(inTwoHours));
         resp1.setHeader("Vary", "Accept-Encoding");
         resp1.setEntity(HttpTestUtils.makeBody(entityLength));
 
-        final HttpRequestWrapper req2 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req2 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req1.setHeader("Accept-Encoding", "gzip");
         req1.setHeader("Cache-Control", "no-cache");
 
-        final HttpResponse resp2 = HttpTestUtils.make200Response();
+        final ClassicHttpResponse resp2 = HttpTestUtils.make200Response();
         resp2.setHeader("ETag", "\"v2\"");
         resp2.setHeader("Cache-Control", "max-age=3600");
         resp2.setHeader("Expires", DateUtils.formatDate(inTwoHours));
         resp2.setHeader("Vary", "Accept-Encoding");
         resp2.setEntity(HttpTestUtils.makeBody(entityLength));
 
-        final HttpRequestWrapper req3 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req3 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
         req3.setHeader("Accept-Encoding", "gzip");
         req3.setHeader("If-None-Match", "\"v2\"");
 
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
-                        EasyMock.<HttpExecutionAware>isNull())).andReturn(
-                                Proxies.enhanceResponse(resp1));
+                        EasyMock.<HttpExecutionAware>isNull())).andReturn(resp1);
         EasyMock.expect(
                 mockBackend.execute(
-                        EasyMock.isA(HttpRoute.class),
-                        EasyMock.isA(HttpRequestWrapper.class),
+                        EasyMock.isA(RoutedHttpRequest.class),
                         EasyMock.isA(HttpClientContext.class),
-                        EasyMock.<HttpExecutionAware>isNull())).andReturn(
-                                Proxies.enhanceResponse(resp2)).times(1, 2);
+                        EasyMock.<HttpExecutionAware>isNull())).andReturn(resp2).times(1, 2);
         replayMocks();
 
-        impl.execute(route, req1, context, null);
-        impl.execute(route, req2, context, null);
-        final HttpResponse result = impl.execute(route, req3, context, null);
+        impl.execute(req1, context, null);
+        impl.execute(req2, context, null);
+        final ClassicHttpResponse result = impl.execute(req3, context, null);
 
         verifyMocks();
 
-        if (result.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
+        if (result.getCode() == HttpStatus.SC_NOT_MODIFIED) {
             Assert.assertNotNull(result.getFirstHeader("Expires"));
             Assert.assertNotNull(result.getFirstHeader("Cache-Control"));
             Assert.assertNotNull(result.getFirstHeader("Vary"));
@@ -2072,10 +2001,10 @@ public class TestProtocolRequirements ex
         final Date now = new Date();
         final Date oneHourAgo = new Date(now.getTime() - 3600 * 1000L);
 
-        final HttpRequestWrapper req1 = HttpRequestWrapper.wrap(
-                new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1), host);
+        final RoutedHttpRequest req1 = RoutedHttpRequest.adapt(
+                new BasicClassicHttpRequest("GET", "/"), route);
 
-        final HttpResponse resp1 = HttpTestUtils.make200Response();
+        final ClassicHttpResponse resp1 = HttpTestUtils.make200Response();
         resp1.setHeader("ETag", "W/\"v1\"");
         resp1.setHeader("Allow", "GET,HEAD");
         resp1.setHeader("Content-Encoding", "x-coding");
@@ -2086,25 +2015,23 @@ public class TestProtocolRequirements ex

[... 3657 lines stripped ...]