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/13 19:27:53 UTC

svn commit: r1774084 - in /httpcomponents/httpcore/trunk/httpcore5/src: main/java/org/apache/hc/core5/http/ main/java/org/apache/hc/core5/http/impl/nio/ main/java/org/apache/hc/core5/http/protocol/ test/java/org/apache/hc/core5/http/protocol/

Author: olegk
Date: Tue Dec 13 19:27:53 2016
New Revision: 1774084

URL: http://svn.apache.org/viewvc?rev=1774084&view=rev
Log:
RFC 7230, HTTPCORE-158: support for HTTP/1.1 protocol upgrade

Modified:
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HeaderElements.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/UpgradeableHttpConnection.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/RequestConnControl.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/ResponseConnControl.java
    httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/protocol/TestStandardInterceptors.java

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HeaderElements.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HeaderElements.java?rev=1774084&r1=1774083&r2=1774084&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HeaderElements.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HeaderElements.java Tue Dec 13 19:27:53 2016
@@ -40,6 +40,7 @@ public final class HeaderElements {
     public static final String CHUNKED_ENCODING = "chunked";
     public static final String CLOSE = "close";
     public static final String KEEP_ALIVE = "keep-alive";
+    public static final String UPGRADE = "upgrade";
     public static final String CONTINUE = "100-continue";
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/UpgradeableHttpConnection.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/UpgradeableHttpConnection.java?rev=1774084&r1=1774083&r2=1774084&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/UpgradeableHttpConnection.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/UpgradeableHttpConnection.java Tue Dec 13 19:27:53 2016
@@ -32,7 +32,11 @@ import org.apache.hc.core5.reactor.IOEve
 import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
 
 /**
- * HTTP connection capable of upgrading its transport security and protocol.
+ * Represents an HTTP/1.1 connection capable of upgrading its transport security
+ * and communication protocol.
+ *
+ * @see TransportSecurityLayer
+ * @see IOEventHandler
  *
  * @since 5.0
  */

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/RequestConnControl.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/RequestConnControl.java?rev=1774084&r1=1774083&r2=1774084&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/RequestConnControl.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/RequestConnControl.java Tue Dec 13 19:27:53 2016
@@ -67,7 +67,11 @@ public class RequestConnControl implemen
         if (!request.containsHeader(HttpHeaders.CONNECTION)) {
             // Default policy is to keep connection alive
             // whenever possible
-            request.addHeader(HttpHeaders.CONNECTION, HeaderElements.KEEP_ALIVE);
+            if (request.containsHeader(HttpHeaders.UPGRADE)) {
+                request.addHeader(HttpHeaders.CONNECTION, HeaderElements.UPGRADE);
+            } else {
+                request.addHeader(HttpHeaders.CONNECTION, HeaderElements.KEEP_ALIVE);
+            }
         }
     }
 

Modified: httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/ResponseConnControl.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/ResponseConnControl.java?rev=1774084&r1=1774083&r2=1774084&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/ResponseConnControl.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/ResponseConnControl.java Tue Dec 13 19:27:53 2016
@@ -28,11 +28,12 @@
 package org.apache.hc.core5.http.protocol;
 
 import java.io.IOException;
+import java.util.Iterator;
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.EntityDetails;
-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.HttpException;
 import org.apache.hc.core5.http.HttpHeaders;
@@ -42,6 +43,7 @@ import org.apache.hc.core5.http.HttpResp
 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.message.MessageSupport;
 import org.apache.hc.core5.util.Args;
 
 /**
@@ -86,13 +88,29 @@ public class ResponseConnControl impleme
             } else {
                 final HttpCoreContext coreContext = HttpCoreContext.adapt(context);
                 final HttpRequest request = coreContext.getRequest();
-                // Drop connection if requested by the client or request was <= 1.0
+                boolean closeRequested = false;
+                boolean keepAliveRequested = false;
                 if (request != null) {
-                    final Header header = request.getFirstHeader(HttpHeaders.CONNECTION);
-                    if (header != null) {
-                        response.setHeader(HttpHeaders.CONNECTION, header.getValue());
-                    } else if (ver.lessEquals(HttpVersion.HTTP_1_0)) {
-                        response.setHeader(HttpHeaders.CONNECTION, HeaderElements.CLOSE);
+                    final Iterator<HeaderElement> it = MessageSupport.iterate(request, HttpHeaders.CONNECTION);
+                    while (it.hasNext()) {
+                        final HeaderElement he = it.next();
+                        if (he.getName().equalsIgnoreCase(HeaderElements.CLOSE)) {
+                            closeRequested = true;
+                            break;
+                        } else if (he.getName().equalsIgnoreCase(HeaderElements.KEEP_ALIVE)) {
+                            keepAliveRequested = true;
+                        }
+                    }
+                }
+                if (closeRequested) {
+                    response.addHeader(HttpHeaders.CONNECTION, HeaderElements.CLOSE);
+                } else {
+                    if (response.containsHeader(HttpHeaders.UPGRADE)) {
+                        response.addHeader(HttpHeaders.CONNECTION, HeaderElements.UPGRADE);
+                    } else {
+                        if (keepAliveRequested || ver.lessEquals(HttpVersion.HTTP_1_0)) {
+                            response.addHeader(HttpHeaders.CONNECTION, HeaderElements.KEEP_ALIVE);
+                        }
                     }
                 }
             }

Modified: httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/protocol/TestStandardInterceptors.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/protocol/TestStandardInterceptors.java?rev=1774084&r1=1774083&r2=1774084&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/protocol/TestStandardInterceptors.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/protocol/TestStandardInterceptors.java Tue Dec 13 19:27:53 2016
@@ -88,6 +88,18 @@ public class TestStandardInterceptors {
     }
 
     @Test
+    public void testRequestConnControlUpgrade() throws Exception {
+        final HttpContext context = new BasicHttpContext(null);
+        final BasicClassicHttpRequest request = new BasicClassicHttpRequest("GET", "/");
+        request.addHeader(HttpHeaders.UPGRADE, "HTTP/2");
+        final RequestConnControl interceptor = new RequestConnControl();
+        interceptor.process(request, request.getEntity(), context);
+        final Header header = request.getFirstHeader(HttpHeaders.CONNECTION);
+        Assert.assertNotNull(header);
+        Assert.assertEquals("upgrade", header.getValue());
+    }
+
+    @Test
     public void testRequestConnControlInvalidInput() throws Exception {
         final RequestConnControl interceptor = new RequestConnControl();
         try {
@@ -656,7 +668,7 @@ public class TestStandardInterceptors {
         interceptor.process(response, response.getEntity(), context);
         final Header header = response.getFirstHeader(HttpHeaders.CONNECTION);
         Assert.assertNotNull(header);
-        Assert.assertEquals("close", header.getValue());
+        Assert.assertEquals("keep-alive", header.getValue());
     }
 
     @Test
@@ -705,6 +717,36 @@ public class TestStandardInterceptors {
     }
 
     @Test
+    public void testResponseConnControlClientRequestMixUp() throws Exception {
+        final HttpContext context = new BasicHttpContext(null);
+        final BasicClassicHttpRequest request = new BasicClassicHttpRequest("GET", "/");
+        request.addHeader(new BasicHeader(HttpHeaders.CONNECTION, "blah, keep-alive, close"));
+        context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
+
+        final ResponseConnControl interceptor = new ResponseConnControl();
+
+        final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
+        interceptor.process(response, response.getEntity(), context);
+        final Header header = response.getFirstHeader(HttpHeaders.CONNECTION);
+        Assert.assertNotNull(header);
+        Assert.assertEquals("close", header.getValue());
+    }
+
+    @Test
+    public void testResponseConnControlUpgrade() throws Exception {
+        final HttpContext context = new BasicHttpContext(null);
+
+        final ResponseConnControl interceptor = new ResponseConnControl();
+
+        final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
+        response.addHeader(HttpHeaders.UPGRADE, "HTTP/2");
+        interceptor.process(response, response.getEntity(), context);
+        final Header header = response.getFirstHeader(HttpHeaders.CONNECTION);
+        Assert.assertNotNull(header);
+        Assert.assertEquals("upgrade", header.getValue());
+    }
+
+    @Test
     public void testResponseConnControlHostInvalidInput() throws Exception {
         final ResponseConnControl interceptor = new ResponseConnControl();
         try {