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 2017/11/19 16:38:24 UTC

httpcomponents-core git commit: Consistent handling of exceptions by HTTP/1.1 and HTTP/2 non-blocking stream handlers [Forced Update!]

Repository: httpcomponents-core
Updated Branches:
  refs/heads/master 6b22427d5 -> ed5e82160 (forced update)


Consistent handling of exceptions by HTTP/1.1 and HTTP/2 non-blocking stream handlers


Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/commit/ed5e8216
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/tree/ed5e8216
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/diff/ed5e8216

Branch: refs/heads/master
Commit: ed5e8216032bfb0b282c0c5a966dac012da41d72
Parents: 502f9d9
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Sun Nov 19 17:02:56 2017 +0100
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Sun Nov 19 17:36:07 2017 +0100

----------------------------------------------------------------------
 .../impl/nio/ServerHttp2StreamHandler.java      | 28 +++++--
 .../http/impl/nio/ServerHttp1StreamHandler.java | 44 +----------
 .../hc/core5/http/impl/nio/ServerSupport.java   | 82 ++++++++++++++++++++
 3 files changed, 106 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed5e8216/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java
index 8349c9c..0aaf570 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java
@@ -42,11 +42,14 @@ import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
 import org.apache.hc.core5.http.impl.IncomingEntityDetails;
 import org.apache.hc.core5.http.impl.nio.MessageState;
+import org.apache.hc.core5.http.impl.nio.ServerSupport;
 import org.apache.hc.core5.http.nio.AsyncPushProducer;
+import org.apache.hc.core5.http.nio.AsyncResponseProducer;
 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
 import org.apache.hc.core5.http.nio.DataStreamChannel;
 import org.apache.hc.core5.http.nio.HandlerFactory;
 import org.apache.hc.core5.http.nio.ResponseChannel;
+import org.apache.hc.core5.http.nio.support.ImmediateResponseExchangeHandler;
 import org.apache.hc.core5.http.protocol.HttpCoreContext;
 import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2ConnectionException;
@@ -198,11 +201,7 @@ public class ServerHttp2StreamHandler implements Http2StreamHandler {
                 context.setProtocolVersion(HttpVersion.HTTP_2);
                 context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
 
-                httpProcessor.process(request, requestEntityDetails, context);
-                connMetrics.incrementRequestCount();
-                receivedRequest = request;
-
-                exchangeHandler.handleRequest(request, requestEntityDetails, new ResponseChannel() {
+                final ResponseChannel responseChannel = new ResponseChannel() {
 
                     @Override
                     public void sendInformation(final HttpResponse response) throws HttpException, IOException {
@@ -212,6 +211,7 @@ public class ServerHttp2StreamHandler implements Http2StreamHandler {
                     @Override
                     public void sendResponse(
                             final HttpResponse response, final EntityDetails responseEntityDetails) throws HttpException, IOException {
+                        ServerSupport.validateResponse(response, responseEntityDetails);
                         commitResponse(response, responseEntityDetails);
                     }
 
@@ -221,7 +221,23 @@ public class ServerHttp2StreamHandler implements Http2StreamHandler {
                         commitPromise(promise, pushProducer);
                     }
 
-                }, context);
+                };
+
+                try {
+                    httpProcessor.process(request, requestEntityDetails, context);
+                    connMetrics.incrementRequestCount();
+                    receivedRequest = request;
+
+                    exchangeHandler.handleRequest(request, requestEntityDetails, responseChannel, context);
+                } catch (final HttpException ex) {
+                    if (!responseCommitted.get()) {
+                        final AsyncResponseProducer responseProducer = ServerSupport.handleException(ex);
+                        exchangeHandler = new ImmediateResponseExchangeHandler(responseProducer);
+                        exchangeHandler.handleRequest(request, requestEntityDetails, responseChannel, context);
+                    } else {
+                        throw ex;
+                    }
+                }
                 break;
             case BODY:
                 responseState = MessageState.COMPLETE;

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed5e8216/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamHandler.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamHandler.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamHandler.java
index 413e8b9..c66a376 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamHandler.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1StreamHandler.java
@@ -39,16 +39,13 @@ 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.MethodNotSupportedException;
 import org.apache.hc.core5.http.MisdirectedRequestException;
-import org.apache.hc.core5.http.NotImplementedException;
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.ProtocolVersion;
 import org.apache.hc.core5.http.UnsupportedHttpVersionException;
 import org.apache.hc.core5.http.nio.AsyncPushProducer;
 import org.apache.hc.core5.http.nio.AsyncResponseProducer;
 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
-import org.apache.hc.core5.http.nio.BasicResponseProducer;
 import org.apache.hc.core5.http.nio.CapacityChannel;
 import org.apache.hc.core5.http.nio.DataStreamChannel;
 import org.apache.hc.core5.http.nio.HandlerFactory;
@@ -122,19 +119,6 @@ class ServerHttp1StreamHandler implements ResourceHolder {
         this.responseState = MessageState.IDLE;
     }
 
-    private void validateResponse(
-            final HttpResponse response,
-            final EntityDetails responseEntityDetails) throws HttpException {
-        final int status = response.getCode();
-        switch (status) {
-            case HttpStatus.SC_NO_CONTENT:
-            case HttpStatus.SC_NOT_MODIFIED:
-                if (responseEntityDetails != null) {
-                    throw new HttpException("Response " + status + " must not enclose an entity");
-                }
-        }
-    }
-
     private void commitResponse(
             final HttpResponse response,
             final EntityDetails responseEntityDetails) throws HttpException, IOException {
@@ -203,30 +187,6 @@ class ServerHttp1StreamHandler implements ResourceHolder {
         return requestState == MessageState.COMPLETE && responseState == MessageState.COMPLETE;
     }
 
-    AsyncResponseProducer handleException(final Exception ex) {
-        String message = ex.getMessage();
-        if (message == null) {
-            message = ex.toString();
-        }
-        return new BasicResponseProducer(toStatusCode(ex), message);
-    }
-
-    protected int toStatusCode(final Exception ex) {
-        final int code;
-        if (ex instanceof MethodNotSupportedException) {
-            code = HttpStatus.SC_NOT_IMPLEMENTED;
-        } else if (ex instanceof UnsupportedHttpVersionException) {
-            code = HttpStatus.SC_HTTP_VERSION_NOT_SUPPORTED;
-        } else if (ex instanceof NotImplementedException) {
-            code = HttpStatus.SC_NOT_IMPLEMENTED;
-        } else if (ex instanceof ProtocolException) {
-            code = HttpStatus.SC_BAD_REQUEST;
-        } else {
-            code = HttpStatus.SC_INTERNAL_SERVER_ERROR;
-        }
-        return code;
-    }
-
     void consumeHeader(final HttpRequest request, final EntityDetails requestEntityDetails) throws HttpException, IOException {
         if (done.get() || requestState != MessageState.HEADERS) {
             throw new ProtocolException("Unexpected message head");
@@ -265,7 +225,7 @@ class ServerHttp1StreamHandler implements ResourceHolder {
             @Override
             public void sendResponse(
                     final HttpResponse response, final EntityDetails responseEntityDetails) throws HttpException, IOException {
-                validateResponse(response, responseEntityDetails);
+                ServerSupport.validateResponse(response, responseEntityDetails);
                 commitResponse(response, responseEntityDetails);
             }
 
@@ -281,7 +241,7 @@ class ServerHttp1StreamHandler implements ResourceHolder {
             exchangeHandler.handleRequest(request, requestEntityDetails, responseChannel, context);
         } catch (final HttpException ex) {
             if (!responseCommitted.get()) {
-                final AsyncResponseProducer responseProducer = handleException(ex);
+                final AsyncResponseProducer responseProducer = ServerSupport.handleException(ex);
                 exchangeHandler = new ImmediateResponseExchangeHandler(responseProducer);
                 exchangeHandler.handleRequest(request, requestEntityDetails, responseChannel, context);
             } else {

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed5e8216/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerSupport.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerSupport.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerSupport.java
new file mode 100644
index 0000000..5cf9f78
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerSupport.java
@@ -0,0 +1,82 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.core5.http.impl.nio;
+
+import org.apache.hc.core5.annotation.Internal;
+import org.apache.hc.core5.http.EntityDetails;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.MethodNotSupportedException;
+import org.apache.hc.core5.http.NotImplementedException;
+import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.UnsupportedHttpVersionException;
+import org.apache.hc.core5.http.nio.AsyncResponseProducer;
+import org.apache.hc.core5.http.nio.BasicResponseProducer;
+
+@Internal
+public class ServerSupport {
+
+    public static void validateResponse(
+            final HttpResponse response,
+            final EntityDetails responseEntityDetails) throws HttpException {
+        final int status = response.getCode();
+        switch (status) {
+            case HttpStatus.SC_NO_CONTENT:
+            case HttpStatus.SC_NOT_MODIFIED:
+                if (responseEntityDetails != null) {
+                    throw new HttpException("Response " + status + " must not enclose an entity");
+                }
+        }
+    }
+
+    public static AsyncResponseProducer handleException(final Exception ex) {
+        String message = ex.getMessage();
+        if (message == null) {
+            message = ex.toString();
+        }
+        return new BasicResponseProducer(toStatusCode(ex), message);
+    }
+
+    public static int toStatusCode(final Exception ex) {
+        final int code;
+        if (ex instanceof MethodNotSupportedException) {
+            code = HttpStatus.SC_NOT_IMPLEMENTED;
+        } else if (ex instanceof UnsupportedHttpVersionException) {
+            code = HttpStatus.SC_HTTP_VERSION_NOT_SUPPORTED;
+        } else if (ex instanceof NotImplementedException) {
+            code = HttpStatus.SC_NOT_IMPLEMENTED;
+        } else if (ex instanceof ProtocolException) {
+            code = HttpStatus.SC_BAD_REQUEST;
+        } else {
+            code = HttpStatus.SC_INTERNAL_SERVER_ERROR;
+        }
+        return code;
+    }
+
+}
+