hc-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject svn commit: r1762527 [1/3] - in /httpcomponents/httpcore/trunk: httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/ httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ httpcore...
Date Tue, 27 Sep 2016 17:49:46 GMT
Author: olegk
Date: Tue Sep 27 17:49:46 2016
New Revision: 1762527

URL: http://svn.apache.org/viewvc?rev=1762527&view=rev
Log:
RFC 7540: HTTP protocol processing for HTTP/2 stream multiplexer

Added:
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/IncomingEntityDetails.java   (contents, props changed)
      - copied, changed from r1762526, httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/TrailerNameFormatter.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/protocol/
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/protocol/H2RequestConnControl.java
      - copied, changed from r1762526, httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ResponseChannel.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/protocol/H2RequestContent.java
      - copied, changed from r1762526, httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ResponseChannel.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/protocol/H2RequestTargetHost.java
      - copied, changed from r1762526, httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ResponseChannel.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/protocol/H2RequestValidateHost.java
      - copied, changed from r1762526, httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ResponseChannel.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/protocol/H2ResponseConnControl.java
      - copied, changed from r1762526, httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ResponseChannel.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/protocol/H2ResponseContent.java
      - copied, changed from r1762526, httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ResponseChannel.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/BasicHttpConnectionMetrics.java   (with props)
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/AbstractMessageWrapper.java   (with props)
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/HttpRequestWrapper.java
      - copied, changed from r1762526, httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/ByteArrayAsyncEntityProducer.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/HttpResponseWrapper.java
      - copied, changed from r1762526, httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/BasicHttpTransportMetrics.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/MessageSupport.java   (with props)
    httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/message/TestMessageSupport.java   (with props)
Removed:
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/HttpConnectionMetricsImpl.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/TrailerNameFormatter.java
    httpcomponents/httpcore/trunk/httpcore5/src/test/java/org/apache/hc/core5/http/protocol/TestTrailerNameFormatter.java
Modified:
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/BasicH2TransportMetrics.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2IOEventHandler.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientPushHttp2StreamHandler.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncExchangeHandler.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncPushHandler.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractClassicExchangeHandler.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncEntityConsumer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncEntityProducer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncPushConsumer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncRequestConsumer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncRequestProducer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncResponseConsumer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncResponseProducer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/BasicPushProducer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/BasicRequestConsumer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/BasicRequestProducer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/BasicResponseConsumer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/BasicResponseProducer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ResponseChannel.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/command/ClientCommandEndpoint.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/command/ExecutionCommand.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/AbstractBinAsyncEntityConsumer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/AbstractBinAsyncEntityProducer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/AbstractCharAsyncEntityConsumer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/AbstractCharAsyncEntityProducer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/AbstractClassicEntityConsumer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/AbstractClassicEntityProducer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/ByteArrayAsyncEntityProducer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/NoopEntityConsumer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/StringAsyncEntityProducer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/integration/Http2IntegrationTest.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/integration/Http2TestClient.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/integration/Http2TestServer.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/integration/InternalClientHttp2EventHandlerFactory.java
    httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/integration/InternalServerHttp2EventHandlerFactory.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/annotation/ThreadingBehavior.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ConnectionReuseStrategy.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/ContentLengthStrategy.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HttpConnection.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HttpConnectionMetrics.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HttpRequestInterceptor.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/HttpResponseInterceptor.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/BasicHttpTransportMetrics.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/BHttpConnectionBase.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/NHttpConnectionBase.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/io/HttpTransportMetrics.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/HttpProcessor.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/RequestContent.java
    httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/ResponseContent.java

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/BasicH2TransportMetrics.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/BasicH2TransportMetrics.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/BasicH2TransportMetrics.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/BasicH2TransportMetrics.java Tue Sep 27 17:49:46 2016
@@ -27,6 +27,8 @@
 
 package org.apache.hc.core5.http2.impl;
 
+import java.util.concurrent.atomic.AtomicLong;
+
 import org.apache.hc.core5.http.impl.BasicHttpTransportMetrics;
 import org.apache.hc.core5.http2.H2TransportMetrics;
 
@@ -37,21 +39,19 @@ import org.apache.hc.core5.http2.H2Trans
  */
 public class BasicH2TransportMetrics extends BasicHttpTransportMetrics implements H2TransportMetrics {
 
-    private long framesTransferred;
+    private final AtomicLong framesTransferred;
+
+    public BasicH2TransportMetrics() {
+        this.framesTransferred = new AtomicLong(0);
+    }
 
     @Override
     public long getFramesTransferred() {
-        return framesTransferred;
+        return framesTransferred.get();
     }
 
     public void incrementFramesTransferred() {
-        framesTransferred++;
-    }
-
-    @Override
-    public void reset() {
-        super.reset();
-        this.framesTransferred = 0;
+        framesTransferred.incrementAndGet();
     }
 
 }

Copied: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/IncomingEntityDetails.java (from r1762526, httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/TrailerNameFormatter.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/IncomingEntityDetails.java?p2=httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/IncomingEntityDetails.java&p1=httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/TrailerNameFormatter.java&r1=1762526&r2=1762527&rev=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/protocol/TrailerNameFormatter.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/IncomingEntityDetails.java Tue Sep 27 17:49:46 2016
@@ -25,51 +25,60 @@
  *
  */
 
-package org.apache.hc.core5.http.protocol;
+package org.apache.hc.core5.http2.impl;
 
-import java.util.ArrayList;
 import java.util.Collections;
-import java.util.List;
 import java.util.Set;
 
 import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpHeaders;
-import org.apache.hc.core5.http.message.BufferedHeader;
-import org.apache.hc.core5.util.CharArrayBuffer;
+import org.apache.hc.core5.http.MessageHeaders;
+import org.apache.hc.core5.http.message.MessageSupport;
+import org.apache.hc.core5.util.Args;
 
 /**
- * Utility class to generate Trailer header.
+ * HTTP/2 message entity details.
  *
  * @since 5.0
  */
-public class TrailerNameFormatter {
+public class IncomingEntityDetails implements EntityDetails {
 
-    private TrailerNameFormatter() {
-        // Do not allow utility class to be instantiated.
+    private final MessageHeaders message;
+
+    public IncomingEntityDetails(final MessageHeaders message) {
+        this.message = Args.notNull(message, "Message");
     }
 
-    public static Header format(final EntityDetails entity) {
-        if (entity == null) {
-            return null;
-        }
-        final Set<String> trailerNames = entity.getTrailerNames();
-        if (trailerNames != null && !trailerNames.isEmpty()) {
-            final List<String> elements = new ArrayList<>(trailerNames);
-            Collections.sort(elements);
-            final CharArrayBuffer buffer = new CharArrayBuffer(trailerNames.size() + 20);
-            buffer.append(HttpHeaders.TRAILER);
-            buffer.append(": ");
-            for (int i = 0; i < elements.size(); i++) {
-                final String element = elements.get(i);
-                if (i > 0) {
-                    buffer.append(", ");
-                }
-                buffer.append(element);
-            }
-            return BufferedHeader.create(buffer);
+    @Override
+    public long getContentLength() {
+        return -1;
+    }
+
+    @Override
+    public String getContentType() {
+        final Header h = message.getFirstHeader(HttpHeaders.CONTENT_TYPE);
+        return h != null ? h.getValue() : null;
+    }
+
+    @Override
+    public String getContentEncoding() {
+        final Header h = message.getFirstHeader(HttpHeaders.CONTENT_TYPE);
+        return h != null ? h.getValue() : null;
+    }
+
+    @Override
+    public boolean isChunked() {
+        return false;
+    }
+
+    @Override
+    public Set<String> getTrailerNames() {
+        final Header h = message.getFirstHeader(HttpHeaders.TRAILER);
+        if (h == null) {
+            return Collections.emptySet();
         }
-        return null;
+        return MessageSupport.parseTokens(h);
     }
 
 }

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/IncomingEntityDetails.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/IncomingEntityDetails.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/IncomingEntityDetails.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2IOEventHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2IOEventHandler.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2IOEventHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2IOEventHandler.java Tue Sep 27 17:49:46 2016
@@ -93,8 +93,4 @@ class AbstractHttp2IOEventHandler implem
     public void disconnected(final IOSession session) {
     }
 
-    public void requestGracefulShutdown() {
-        streamMultiplexer.requestGracefulShutdown();
-    }
-
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java Tue Sep 27 17:49:46 2016
@@ -45,8 +45,14 @@ import java.util.concurrent.locks.Reentr
 
 import org.apache.hc.core5.http.ConnectionClosedException;
 import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpConnection;
+import org.apache.hc.core5.http.HttpConnectionMetrics;
 import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2ConnectionException;
 import org.apache.hc.core5.http2.H2Error;
 import org.apache.hc.core5.http2.H2StreamResetException;
@@ -71,7 +77,7 @@ import org.apache.hc.core5.util.Args;
 import org.apache.hc.core5.util.ByteArrayBuffer;
 import org.apache.hc.core5.util.NetUtils;
 
-abstract class AbstractHttp2StreamMultiplexer {
+abstract class AbstractHttp2StreamMultiplexer implements HttpConnection {
 
     private static final long LINGER_TIME = 1000; // 1 second
 
@@ -83,8 +89,11 @@ abstract class AbstractHttp2StreamMultip
     private final IOSession ioSession;
     private final FrameFactory frameFactory;
     private final StreamIdGenerator idGenerator;
+    private final HttpProcessor httpProcessor;
     private final H2Config localConfig;
-    private final BasicH2TransportMetrics metrics;
+    private final BasicH2TransportMetrics inputMetrics;
+    private final BasicH2TransportMetrics outputMetrics;
+    private final BasicHttpConnectionMetrics connMetrics;
     private final FrameInputBuffer inputBuffer;
     private final FrameOutputBuffer outputBuffer;
     private final Deque<RawFrame> outputQueue;
@@ -113,6 +122,7 @@ abstract class AbstractHttp2StreamMultip
             final IOSession ioSession,
             final FrameFactory frameFactory,
             final StreamIdGenerator idGenerator,
+            final HttpProcessor httpProcessor,
             final Charset charset,
             final H2Config h2Config,
             final Http2StreamListener callback) {
@@ -120,10 +130,13 @@ abstract class AbstractHttp2StreamMultip
         this.ioSession = Args.notNull(ioSession, "IO session");
         this.frameFactory = Args.notNull(frameFactory, "Frame factory");
         this.idGenerator = Args.notNull(idGenerator, "Stream id generator");
+        this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
         this.localConfig = h2Config != null ? h2Config : H2Config.DEFAULT;
-        this.metrics = new BasicH2TransportMetrics();
-        this.inputBuffer = new FrameInputBuffer(this.metrics, this.localConfig.getMaxFrameSize());
-        this.outputBuffer = new FrameOutputBuffer(this.metrics, this.localConfig.getMaxFrameSize());
+        this.inputMetrics = new BasicH2TransportMetrics();
+        this.outputMetrics = new BasicH2TransportMetrics();
+        this.connMetrics = new BasicHttpConnectionMetrics(inputMetrics, outputMetrics);
+        this.inputBuffer = new FrameInputBuffer(this.inputMetrics, this.localConfig.getMaxFrameSize());
+        this.outputBuffer = new FrameOutputBuffer(this.outputMetrics, this.localConfig.getMaxFrameSize());
         this.outputQueue = new ConcurrentLinkedDeque<>();
         this.outputLock = new ReentrantLock();
         this.outputRequests = new AtomicInteger(0);
@@ -142,7 +155,8 @@ abstract class AbstractHttp2StreamMultip
         this.callback = callback;
     }
 
-    abstract Http2StreamHandler createRemotelyInitiatedStream(Http2StreamChannel channel) throws IOException;
+    abstract Http2StreamHandler createRemotelyInitiatedStream(
+            Http2StreamChannel channel, HttpProcessor httpProcessor, BasicHttpConnectionMetrics connMetrics) throws IOException;
 
     private int updateWindow(final AtomicInteger window, final int delta) throws ArithmeticException {
         for (;;) {
@@ -519,8 +533,11 @@ abstract class AbstractHttp2StreamMultip
                         remoteConfig.getInitialWindowSize());
                 final Http2StreamHandler streamHandler = new ClientHttp2StreamHandler<>(
                         channel,
+                        httpProcessor,
+                        connMetrics,
                         executionCommand.getRequestProducer(),
                         executionCommand.getResponseConsumer(),
+                        executionCommand.getContext(),
                         executionCommand.getCallback());
                 final Http2Stream stream = new Http2Stream(channel, streamHandler, false);
                 if (stream.isOutputReady()) {
@@ -629,7 +646,8 @@ abstract class AbstractHttp2StreamMultip
                             streamId,
                             localConfig.getInitialWindowSize(),
                             remoteConfig.getInitialWindowSize());
-                    final Http2StreamHandler streamHandler = createRemotelyInitiatedStream(channel);
+                    final Http2StreamHandler streamHandler = createRemotelyInitiatedStream(
+                            channel, httpProcessor, connMetrics);
                     stream = new Http2Stream(channel, streamHandler, true);
                     if (stream.isOutputReady()) {
                         stream.produceOutput();
@@ -790,7 +808,8 @@ abstract class AbstractHttp2StreamMultip
                         promisedStreamId,
                         localConfig.getInitialWindowSize(),
                         remoteConfig.getInitialWindowSize());
-                final Http2StreamHandler streamHandler = createRemotelyInitiatedStream(channel);
+                final Http2StreamHandler streamHandler = createRemotelyInitiatedStream(
+                        channel, httpProcessor, connMetrics);
                 final Http2Stream promisedStream = new Http2Stream(channel, streamHandler, true);
                 streamMap.put(promisedStreamId, promisedStream);
 
@@ -1031,14 +1050,51 @@ abstract class AbstractHttp2StreamMultip
         }
     }
 
-    public void requestGracefulShutdown() {
-        try {
-            final RawFrame goAway = frameFactory.createGoAway(processedRemoteStreamId, H2Error.NO_ERROR, "Graceful shutdown");
-            commitFrame(goAway);
-            connState = streamMap.isEmpty() ? ConnectionHandshake.SHUTDOWN : ConnectionHandshake.GRACEFUL_SHUTDOWN;
-        } catch (IOException ex) {
-            onException(ex);
-        }
+    @Override
+    public void close() throws IOException {
+        ioSession.getCommandQueue().addFirst(new ShutdownCommand(ShutdownType.GRACEFUL));
+        ioSession.setEvent(SelectionKey.OP_WRITE);
+    }
+
+    @Override
+    public void shutdown() throws IOException {
+        ioSession.getCommandQueue().addFirst(new ShutdownCommand(ShutdownType.IMMEDIATE));
+        ioSession.setEvent(SelectionKey.OP_WRITE);
+    }
+
+    @Override
+    public boolean isOpen() {
+        return connState == ConnectionHandshake.ACTIVE;
+    }
+
+    @Override
+    public void setSocketTimeout(final int timeout) {
+        ioSession.setSocketTimeout(timeout);
+    }
+
+    @Override
+    public HttpConnectionMetrics getMetrics() {
+        return connMetrics;
+    }
+
+    @Override
+    public int getSocketTimeout() {
+        return ioSession.getSocketTimeout();
+    }
+
+    @Override
+    public ProtocolVersion getProtocolVersion() {
+        return HttpVersion.HTTP_2;
+    }
+
+    @Override
+    public SocketAddress getRemoteAddress() {
+        return ioSession.getRemoteAddress();
+    }
+
+    @Override
+    public SocketAddress getLocalAddress() {
+        return ioSession.getLocalAddress();
     }
 
     @Override
@@ -1135,7 +1191,8 @@ abstract class AbstractHttp2StreamMultip
                     promisedStreamId,
                     localConfig.getInitialWindowSize(),
                     remoteConfig.getInitialWindowSize());
-            final Http2StreamHandler streamHandler = new ServerPushHttp2StreamHandler(channel, pushProducer);
+            final Http2StreamHandler streamHandler = new ServerPushHttp2StreamHandler(
+                    channel, httpProcessor, connMetrics, pushProducer);
             final Http2Stream stream = new Http2Stream(channel, streamHandler, false);
             streamMap.put(promisedStreamId, stream);
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java Tue Sep 27 17:49:46 2016
@@ -32,34 +32,47 @@ import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.http.protocol.HttpCoreContext;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2ConnectionException;
 import org.apache.hc.core5.http2.H2Error;
 import org.apache.hc.core5.http2.impl.DefaultH2RequestConverter;
 import org.apache.hc.core5.http2.impl.DefaultH2ResponseConverter;
+import org.apache.hc.core5.http2.impl.IncomingEntityDetails;
 import org.apache.hc.core5.http2.nio.AsyncPushProducer;
 import org.apache.hc.core5.http2.nio.AsyncRequestProducer;
 import org.apache.hc.core5.http2.nio.AsyncResponseConsumer;
 
 class ClientHttp2StreamHandler<T> implements Http2StreamHandler {
 
+    private final Http2StreamChannel internalOutputChannel;
+    private final HttpProcessor httpProcessor;
+    private final BasicHttpConnectionMetrics connMetrics;
     private final AsyncRequestProducer requestProducer;
     private final AsyncResponseConsumer<T> responseConsumer;
+    private final HttpCoreContext context;
     private final FutureCallback<T> resultCallback;
     private final AtomicBoolean done;
 
     private volatile MessageState requestState;
     private volatile MessageState responseState;
-    private volatile Http2StreamChannel internalOutputChannel;
 
     ClientHttp2StreamHandler(
             final Http2StreamChannel outputChannel,
+            final HttpProcessor httpProcessor,
+            final BasicHttpConnectionMetrics connMetrics,
             final AsyncRequestProducer requestProducer,
             final AsyncResponseConsumer<T> responseConsumer,
+            final HttpContext context,
             final FutureCallback<T> resultCallback) {
         this.internalOutputChannel = new Http2StreamChannel() {
 
@@ -102,9 +115,12 @@ class ClientHttp2StreamHandler<T> implem
             }
 
         };
+        this.httpProcessor = httpProcessor;
+        this.connMetrics = connMetrics;
         this.requestProducer = requestProducer;
         this.responseConsumer = responseConsumer;
         this.resultCallback = resultCallback;
+        this.context = HttpCoreContext.adapt(context);
         this.done = new AtomicBoolean(false);
         this.requestState = MessageState.HEADERS;
         this.responseState = MessageState.HEADERS;
@@ -127,10 +143,17 @@ class ClientHttp2StreamHandler<T> implem
         switch (requestState) {
             case HEADERS:
                 final HttpRequest request = requestProducer.produceRequest();
+                final EntityDetails entityDetails = requestProducer.getEntityDetails();
+
+                context.setProtocolVersion(HttpVersion.HTTP_2);
+                context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
+                context.setAttribute(HttpCoreContext.HTTP_CONNECTION, this);
+                httpProcessor.process(request, entityDetails, context);
+
                 final List<Header> headers = DefaultH2RequestConverter.INSTANCE.convert(request);
-                final boolean endStream = !requestProducer.isEnclosingEntity();
-                internalOutputChannel.submit(headers, endStream);
-                if (!endStream) {
+                internalOutputChannel.submit(headers, entityDetails == null);
+                connMetrics.incrementRequestCount();
+                if (entityDetails != null) {
                     requestProducer.dataStart(internalOutputChannel);
                 }
                 break;
@@ -151,7 +174,13 @@ class ClientHttp2StreamHandler<T> implem
             throw new ProtocolException("Unexpected message headers");
         }
         final HttpResponse response = DefaultH2ResponseConverter.INSTANCE.convert(headers);
-        responseConsumer.consumeResponse(response, new FutureCallback<T>() {
+        final EntityDetails entityDetails = endStream ? null : new IncomingEntityDetails(response);
+
+        context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
+        httpProcessor.process(response, entityDetails, context);
+        connMetrics.incrementResponseCount();
+
+        responseConsumer.consumeResponse(response, entityDetails, new FutureCallback<T>() {
 
             @Override
             public void completed(final T result) {

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java Tue Sep 27 17:49:46 2016
@@ -29,6 +29,8 @@ package org.apache.hc.core5.http2.impl.n
 import java.io.IOException;
 import java.nio.charset.Charset;
 
+import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.config.H2Config;
 import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
 import org.apache.hc.core5.http2.frame.FrameFactory;
@@ -49,32 +51,38 @@ public class ClientHttp2StreamMultiplexe
     public ClientHttp2StreamMultiplexer(
             final IOSession ioSession,
             final FrameFactory frameFactory,
+            final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
             final Http2StreamListener streamListener) {
-        super(Mode.CLIENT, ioSession, frameFactory, StreamIdGenerator.ODD, charset, h2Config, streamListener);
+        super(Mode.CLIENT, ioSession, frameFactory, StreamIdGenerator.ODD, httpProcessor, charset, h2Config, streamListener);
         this.pushHandlerFactory = pushHandlerFactory;
     }
 
     public ClientHttp2StreamMultiplexer(
             final IOSession ioSession,
+            final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
             final Charset charset,
             final H2Config h2Config) {
-        this(ioSession, DefaultFrameFactory.INSTANCE, pushHandlerFactory, charset, h2Config, null);
+        this(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor, pushHandlerFactory, charset, h2Config, null);
     }
 
     public ClientHttp2StreamMultiplexer(
             final IOSession ioSession,
+            final HttpProcessor httpProcessor,
             final Charset charset,
             final H2Config h2Config) {
-        this(ioSession, null, charset, h2Config);
+        this(ioSession, httpProcessor, null, charset, h2Config);
     }
 
     @Override
-    Http2StreamHandler createRemotelyInitiatedStream(final Http2StreamChannel channel) throws IOException {
-        return new ClientPushHttp2StreamHandler(channel, pushHandlerFactory);
+    Http2StreamHandler createRemotelyInitiatedStream(
+            final Http2StreamChannel channel,
+            final HttpProcessor httpProcessor,
+            final BasicHttpConnectionMetrics connMetrics) throws IOException {
+        return new ClientPushHttp2StreamHandler(channel, httpProcessor, connMetrics, pushHandlerFactory);
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java Tue Sep 27 17:49:46 2016
@@ -35,6 +35,7 @@ import java.nio.charset.StandardCharsets
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2ConnectionException;
 import org.apache.hc.core5.http2.H2Error;
 import org.apache.hc.core5.http2.config.H2Config;
@@ -43,6 +44,7 @@ import org.apache.hc.core5.http2.nio.Asy
 import org.apache.hc.core5.http2.nio.HandlerFactory;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOSession;
+import org.apache.hc.core5.util.Args;
 
 /**
  * @since 5.0
@@ -56,6 +58,7 @@ public class ClientHttpProtocolNegotiato
             0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x53, 0x4d,
             0x0d, 0x0a, 0x0d, 0x0a};
 
+    private final HttpProcessor httpProcessor;
     private final Charset charset;
     private final H2Config h2Config;
     private final HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
@@ -63,11 +66,13 @@ public class ClientHttpProtocolNegotiato
     private final HttpErrorListener errorListener;
 
     public ClientHttpProtocolNegotiator(
+            final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
             final Http2StreamListener streamListener,
             final HttpErrorListener errorListener) {
+        this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
         this.pushHandlerFactory = pushHandlerFactory;
         this.charset = charset != null ? charset : StandardCharsets.US_ASCII;
         this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
@@ -76,7 +81,7 @@ public class ClientHttpProtocolNegotiato
     }
 
     protected ClientHttp2StreamMultiplexer createStreamMultiplexer(final IOSession ioSession) {
-        return new ClientHttp2StreamMultiplexer(ioSession, DefaultFrameFactory.INSTANCE,
+        return new ClientHttp2StreamMultiplexer(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor,
                 pushHandlerFactory, charset, h2Config, streamListener);
     }
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java Tue Sep 27 17:49:46 2016
@@ -32,11 +32,13 @@ import java.nio.charset.StandardCharsets
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.config.H2Config;
 import org.apache.hc.core5.http2.nio.AsyncPushConsumer;
 import org.apache.hc.core5.http2.nio.HandlerFactory;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.IOSession;
+import org.apache.hc.core5.util.Args;
 
 /**
  * @since 5.0
@@ -44,6 +46,7 @@ import org.apache.hc.core5.reactor.IOSes
 @Contract(threading = ThreadingBehavior.IMMUTABLE)
 public class ClientHttpProtocolNegotiatorFactory implements IOEventHandlerFactory {
 
+    private final HttpProcessor httpProcessor;
     private final HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
     private final Charset charset;
     private final H2Config h2Config;
@@ -51,11 +54,13 @@ public class ClientHttpProtocolNegotiato
     private final HttpErrorListener errorListener;
 
     public ClientHttpProtocolNegotiatorFactory(
+            final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
             final Http2StreamListener streamListener,
             final HttpErrorListener errorListener) {
+        this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
         this.pushHandlerFactory = pushHandlerFactory;
         this.charset = charset != null ? charset : StandardCharsets.US_ASCII;
         this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
@@ -64,21 +69,23 @@ public class ClientHttpProtocolNegotiato
     }
 
     public ClientHttpProtocolNegotiatorFactory(
+            final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
             final Http2StreamListener streamListener,
             final HttpErrorListener errorListener) {
-        this(pushHandlerFactory, null, null, streamListener, errorListener);
+        this(httpProcessor, pushHandlerFactory, null, null, streamListener, errorListener);
     }
 
     public ClientHttpProtocolNegotiatorFactory(
+            final HttpProcessor httpProcessor,
             final Http2StreamListener streamListener,
             final HttpErrorListener errorListener) {
-        this(null, streamListener, errorListener);
+        this(httpProcessor, null, streamListener, errorListener);
     }
 
     @Override
     public ClientHttpProtocolNegotiator createHandler(final IOSession ioSession) {
-        return new ClientHttpProtocolNegotiator(pushHandlerFactory, charset, h2Config, streamListener, errorListener);
+        return new ClientHttpProtocolNegotiator(httpProcessor, pushHandlerFactory, charset, h2Config, streamListener, errorListener);
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientPushHttp2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientPushHttp2StreamHandler.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientPushHttp2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientPushHttp2StreamHandler.java Tue Sep 27 17:49:46 2016
@@ -31,33 +31,49 @@ import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.protocol.HttpCoreContext;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2Error;
 import org.apache.hc.core5.http2.H2StreamResetException;
 import org.apache.hc.core5.http2.impl.DefaultH2RequestConverter;
 import org.apache.hc.core5.http2.impl.DefaultH2ResponseConverter;
+import org.apache.hc.core5.http2.impl.IncomingEntityDetails;
 import org.apache.hc.core5.http2.nio.AsyncPushConsumer;
 import org.apache.hc.core5.http2.nio.HandlerFactory;
 import org.apache.hc.core5.util.Asserts;
 
 class ClientPushHttp2StreamHandler implements Http2StreamHandler {
 
+    private final Http2StreamChannel internalOutputChannel;
+    private final HttpProcessor httpProcessor;
+    private final BasicHttpConnectionMetrics connMetrics;
     private final HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
+    private final HttpCoreContext context;
     private final AtomicBoolean done;
 
-    private volatile Http2StreamChannel internalOutputChannel;
     private volatile HttpRequest request;
     private volatile AsyncPushConsumer exchangeHandler;
     private volatile MessageState requestState;
     private volatile MessageState responseState;
 
-    ClientPushHttp2StreamHandler(final Http2StreamChannel outputChannel, final HandlerFactory<AsyncPushConsumer> pushHandlerFactory) {
+    ClientPushHttp2StreamHandler(
+            final Http2StreamChannel outputChannel,
+            final HttpProcessor httpProcessor,
+            final BasicHttpConnectionMetrics connMetrics,
+            final HandlerFactory<AsyncPushConsumer> pushHandlerFactory) {
         this.internalOutputChannel = outputChannel;
+        this.httpProcessor = httpProcessor;
+        this.connMetrics = connMetrics;
         this.pushHandlerFactory = pushHandlerFactory;
+        this.context = HttpCoreContext.create();
         this.done = new AtomicBoolean(false);
         this.requestState = MessageState.HEADERS;
         this.responseState = MessageState.HEADERS;
@@ -75,8 +91,16 @@ class ClientPushHttp2StreamHandler imple
     @Override
     public void consumePromise(final List<Header> headers) throws HttpException, IOException {
         if (requestState == MessageState.HEADERS) {
+
             request = DefaultH2RequestConverter.INSTANCE.convert(headers);
-            exchangeHandler = pushHandlerFactory != null ? pushHandlerFactory.create(request, null) : null;
+
+            context.setProtocolVersion(HttpVersion.HTTP_2);
+            context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
+            context.setAttribute(HttpCoreContext.HTTP_CONNECTION, this);
+            httpProcessor.process(request, null, context);
+            connMetrics.incrementRequestCount();
+
+            exchangeHandler = pushHandlerFactory != null ? pushHandlerFactory.create(request, context) : null;
             if (exchangeHandler == null) {
                 releaseResources();
                 throw new H2StreamResetException(H2Error.REFUSED_STREAM, "Stream refused");
@@ -91,8 +115,15 @@ class ClientPushHttp2StreamHandler imple
         if (responseState == MessageState.HEADERS) {
             Asserts.notNull(request, "Request");
             Asserts.notNull(exchangeHandler, "Exchange handler");
+
             final HttpResponse response = DefaultH2ResponseConverter.INSTANCE.convert(headers);
-            exchangeHandler.consumePromise(request, response);
+            final EntityDetails entityDetails = endStream ? null : new IncomingEntityDetails(request);
+
+            context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
+            httpProcessor.process(response, entityDetails, context);
+            connMetrics.incrementResponseCount();
+
+            exchangeHandler.consumePromise(request, response, entityDetails);
             if (endStream) {
                 responseState = MessageState.COMPLETE;
                 exchangeHandler.streamEnd(null);

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java Tue Sep 27 17:49:46 2016
@@ -31,15 +31,21 @@ import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.protocol.HttpCoreContext;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2ConnectionException;
 import org.apache.hc.core5.http2.H2Error;
 import org.apache.hc.core5.http2.impl.DefaultH2RequestConverter;
 import org.apache.hc.core5.http2.impl.DefaultH2ResponseConverter;
+import org.apache.hc.core5.http2.impl.IncomingEntityDetails;
 import org.apache.hc.core5.http2.nio.AsyncExchangeHandler;
 import org.apache.hc.core5.http2.nio.AsyncPushProducer;
 import org.apache.hc.core5.http2.nio.HandlerFactory;
@@ -48,15 +54,22 @@ import org.apache.hc.core5.util.Asserts;
 
 public class ServerHttp2StreamHandler implements Http2StreamHandler {
 
+    private final Http2StreamChannel internalOutputChannel;
+    private final HttpProcessor httpProcessor;
+    private final BasicHttpConnectionMetrics connMetrics;
     private final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory;
+    private final HttpCoreContext context;
     private final AtomicBoolean done;
 
-    private volatile Http2StreamChannel internalOutputChannel;
     private volatile AsyncExchangeHandler exchangeHandler;
     private volatile MessageState requestState;
     private volatile MessageState responseState;
 
-    ServerHttp2StreamHandler(final Http2StreamChannel outputChannel, final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory) {
+    ServerHttp2StreamHandler(
+            final Http2StreamChannel outputChannel,
+            final HttpProcessor httpProcessor,
+            final BasicHttpConnectionMetrics connMetrics,
+            final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory) {
         this.internalOutputChannel = new Http2StreamChannel() {
 
             @Override
@@ -98,7 +111,10 @@ public class ServerHttp2StreamHandler im
             }
 
         };
+        this.httpProcessor = httpProcessor;
+        this.connMetrics = connMetrics;
         this.exchangeHandlerFactory = exchangeHandlerFactory;
+        this.context = HttpCoreContext.create();
         this.done = new AtomicBoolean(false);
         this.requestState = MessageState.HEADERS;
         this.responseState = MessageState.IDLE;
@@ -117,23 +133,36 @@ public class ServerHttp2StreamHandler im
         requestState = requestEndStream ? MessageState.COMPLETE : MessageState.BODY;
 
         final HttpRequest request = DefaultH2RequestConverter.INSTANCE.convert(requestHeaders);
+        final EntityDetails requestEntityDetails = requestEndStream ? null : new IncomingEntityDetails(request);
 
-        exchangeHandler = exchangeHandlerFactory.create(request, null);
+        context.setProtocolVersion(HttpVersion.HTTP_2);
+        context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
+        context.setAttribute(HttpCoreContext.HTTP_CONNECTION, this);
+        httpProcessor.process(request, requestEntityDetails, context);
+        connMetrics.incrementRequestCount();
+
+        exchangeHandler = exchangeHandlerFactory.create(request, context);
         if (exchangeHandler == null) {
             throw new H2ConnectionException(H2Error.INTERNAL_ERROR,
                     "Unable to handle " + request.getMethod() + " " + request.getPath());
         }
-        exchangeHandler.handleRequest(request, requestEndStream, new ResponseChannel() {
+        exchangeHandler.handleRequest(request, requestEntityDetails, new ResponseChannel() {
 
             private final AtomicBoolean responseCommitted = new AtomicBoolean(false);
 
             @Override
             public void sendResponse(
-                    final HttpResponse response, final boolean responseEndStream) throws HttpException, IOException {
+                    final HttpResponse response, final EntityDetails responseEntityDetails) throws HttpException, IOException {
                 if (responseCommitted.compareAndSet(false, true)) {
+
+                    context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
+                    httpProcessor.process(response, responseEntityDetails, context);
+
                     final List<Header> responseHeaders = DefaultH2ResponseConverter.INSTANCE.convert(response);
-                    internalOutputChannel.submit(responseHeaders, responseEndStream);
-                    if (!responseEndStream) {
+
+                    internalOutputChannel.submit(responseHeaders, responseEntityDetails == null);
+                    connMetrics.incrementResponseCount();
+                    if (responseEntityDetails != null) {
                         exchangeHandler.produce(internalOutputChannel);
                     }
                 } else {
@@ -143,8 +172,12 @@ public class ServerHttp2StreamHandler im
 
             @Override
             public void pushPromise(final HttpRequest promise, final AsyncPushProducer pushProducer) throws HttpException, IOException {
+
+                httpProcessor.process(promise, null, context);
+
                 final List<Header> promiseHeaders = DefaultH2RequestConverter.INSTANCE.convert(promise);
                 internalOutputChannel.push(promiseHeaders, pushProducer);
+                connMetrics.incrementRequestCount();
             }
 
             @Override

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexer.java Tue Sep 27 17:49:46 2016
@@ -29,6 +29,8 @@ package org.apache.hc.core5.http2.impl.n
 import java.io.IOException;
 import java.nio.charset.Charset;
 
+import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.config.H2Config;
 import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
 import org.apache.hc.core5.http2.frame.FrameFactory;
@@ -50,25 +52,30 @@ public class ServerHttp2StreamMultiplexe
     public ServerHttp2StreamMultiplexer(
             final IOSession ioSession,
             final FrameFactory frameFactory,
+            final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
             final Http2StreamListener callback) {
-        super(Mode.SERVER, ioSession, frameFactory, StreamIdGenerator.EVEN, charset, h2Config, callback);
+        super(Mode.SERVER, ioSession, frameFactory, StreamIdGenerator.EVEN, httpProcessor, charset, h2Config, callback);
         this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Handler factory");
     }
 
     public ServerHttp2StreamMultiplexer(
             final IOSession ioSession,
+            final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory,
             final Charset charset,
             final H2Config h2Config) {
-        this(ioSession, DefaultFrameFactory.INSTANCE, exchangeHandlerFactory, charset, h2Config, null);
+        this(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor, exchangeHandlerFactory, charset, h2Config, null);
     }
 
     @Override
-    Http2StreamHandler createRemotelyInitiatedStream(final Http2StreamChannel channel) throws IOException {
-        return new ServerHttp2StreamHandler(channel, exchangeHandlerFactory);
+    Http2StreamHandler createRemotelyInitiatedStream(
+            final Http2StreamChannel channel,
+            final HttpProcessor httpProcessor,
+            final BasicHttpConnectionMetrics connMetrics) throws IOException {
+        return new ServerHttp2StreamHandler(channel, httpProcessor, connMetrics, exchangeHandlerFactory);
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java Tue Sep 27 17:49:46 2016
@@ -34,6 +34,7 @@ import java.nio.charset.StandardCharsets
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2ConnectionException;
 import org.apache.hc.core5.http2.H2Error;
 import org.apache.hc.core5.http2.config.H2Config;
@@ -52,6 +53,7 @@ public class ServerHttpProtocolNegotiato
 
     final static byte[] PREFACE = ClientHttpProtocolNegotiator.PREFACE;
 
+    private final HttpProcessor httpProcessor;
     private final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory;
     private final Charset charset;
     private final H2Config h2Config;
@@ -60,21 +62,23 @@ public class ServerHttpProtocolNegotiato
     private final ByteBuffer bytebuf;
 
     public ServerHttpProtocolNegotiator(
+            final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
             final Http2StreamListener streamListener,
             final HttpErrorListener errorListener) {
+        this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
+        this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Exchange handler factory");
         this.charset = charset != null ? charset : StandardCharsets.US_ASCII;
         this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
-        this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Exchchange handler factory");
         this.streamListener = streamListener;
         this.errorListener = errorListener;
         this.bytebuf = ByteBuffer.allocate(1024);
     }
 
     protected ServerHttp2StreamMultiplexer createStreamMultiplexer(final IOSession ioSession) {
-        return new ServerHttp2StreamMultiplexer(ioSession, DefaultFrameFactory.INSTANCE,
+        return new ServerHttp2StreamMultiplexer(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor,
                 exchangeHandlerFactory, charset, h2Config, streamListener);
     }
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java Tue Sep 27 17:49:46 2016
@@ -32,6 +32,7 @@ import java.nio.charset.StandardCharsets
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.config.H2Config;
 import org.apache.hc.core5.http2.nio.AsyncExchangeHandler;
 import org.apache.hc.core5.http2.nio.HandlerFactory;
@@ -45,6 +46,7 @@ import org.apache.hc.core5.util.Args;
 @Contract(threading = ThreadingBehavior.IMMUTABLE)
 public class ServerHttpProtocolNegotiatorFactory implements IOEventHandlerFactory {
 
+    private final HttpProcessor httpProcessor;
     private final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory;
     private final Charset charset;
     private final H2Config h2Config;
@@ -52,11 +54,13 @@ public class ServerHttpProtocolNegotiato
     private final HttpErrorListener errorListener;
 
     public ServerHttpProtocolNegotiatorFactory(
+            final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory,
             final Charset charset,
             final H2Config h2Config,
             final Http2StreamListener streamListener,
             final HttpErrorListener errorListener) {
+        this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
         this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Exchange handler factory");
         this.charset = charset != null ? charset : StandardCharsets.US_ASCII;
         this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
@@ -65,15 +69,16 @@ public class ServerHttpProtocolNegotiato
     }
 
     public ServerHttpProtocolNegotiatorFactory(
+            final HttpProcessor httpProcessor,
             final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory,
             final Http2StreamListener streamListener,
             final HttpErrorListener errorListener) {
-        this(exchangeHandlerFactory, null, null, streamListener, errorListener);
+        this(httpProcessor, exchangeHandlerFactory, null, null, streamListener, errorListener);
     }
 
     @Override
     public ServerHttpProtocolNegotiator createHandler(final IOSession ioSession) {
-        return new ServerHttpProtocolNegotiator(exchangeHandlerFactory, charset, h2Config, streamListener, errorListener);
+        return new ServerHttpProtocolNegotiator(httpProcessor, exchangeHandlerFactory, charset, h2Config, streamListener, errorListener);
     }
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java Tue Sep 27 17:49:46 2016
@@ -31,11 +31,16 @@ import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.protocol.HttpCoreContext;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
 import org.apache.hc.core5.http2.H2ConnectionException;
 import org.apache.hc.core5.http2.H2Error;
 import org.apache.hc.core5.http2.impl.DefaultH2RequestConverter;
@@ -45,18 +50,21 @@ import org.apache.hc.core5.http2.nio.Res
 
 class ServerPushHttp2StreamHandler implements Http2StreamHandler {
 
+    private final Http2StreamChannel internalOutputChannel;
+    private final HttpProcessor httpProcessor;
+    private final BasicHttpConnectionMetrics connMetrics;
     private final AsyncPushProducer pushProducer;
+    private final HttpCoreContext context;
     private final AtomicBoolean done;
 
-    private volatile Http2StreamChannel internalOutputChannel;
     private volatile MessageState requestState;
     private volatile MessageState responseState;
 
-    ServerPushHttp2StreamHandler(final Http2StreamChannel outputChannel, final AsyncPushProducer pushProducer) {
-        this.pushProducer = pushProducer;
-        this.done = new AtomicBoolean(false);
-        this.requestState = MessageState.COMPLETE;
-        this.responseState = MessageState.IDLE;
+    ServerPushHttp2StreamHandler(
+            final Http2StreamChannel outputChannel,
+            final HttpProcessor httpProcessor,
+            final BasicHttpConnectionMetrics connMetrics,
+            final AsyncPushProducer pushProducer) {
         this.internalOutputChannel = new Http2StreamChannel() {
 
             @Override
@@ -98,6 +106,13 @@ class ServerPushHttp2StreamHandler imple
             }
 
         };
+        this.httpProcessor = httpProcessor;
+        this.connMetrics = connMetrics;
+        this.pushProducer = pushProducer;
+        this.context = HttpCoreContext.create();
+        this.done = new AtomicBoolean(false);
+        this.requestState = MessageState.COMPLETE;
+        this.responseState = MessageState.IDLE;
     }
 
     @Override
@@ -142,18 +157,33 @@ class ServerPushHttp2StreamHandler imple
 
                     @Override
                     public void sendResponse(
-                            final HttpResponse response, final boolean endStream) throws HttpException, IOException {
+                            final HttpResponse response, final EntityDetails entityDetails) throws HttpException, IOException {
                         if (responseCommitted.compareAndSet(false, true)) {
+
+                            context.setProtocolVersion(HttpVersion.HTTP_2);
+                            context.setAttribute(HttpCoreContext.HTTP_CONNECTION, this);
+                            context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
+                            httpProcessor.process(response, entityDetails, context);
+
                             final List<Header> headers = DefaultH2ResponseConverter.INSTANCE.convert(response);
-                            internalOutputChannel.submit(headers, endStream);
+                            internalOutputChannel.submit(headers, entityDetails == null);
+                            connMetrics.incrementResponseCount();
                         }
                     }
 
                     @Override
                     public void pushPromise(
                             final HttpRequest promise, final AsyncPushProducer pushProducer) throws HttpException, IOException {
+
+                        context.setProtocolVersion(HttpVersion.HTTP_2);
+                        context.setAttribute(HttpCoreContext.HTTP_REQUEST, promise);
+                        context.setAttribute(HttpCoreContext.HTTP_CONNECTION, this);
+                        httpProcessor.process(promise, null, context);
+
                         final List<Header> headers = DefaultH2RequestConverter.INSTANCE.convert(promise);
+
                         internalOutputChannel.push(headers, pushProducer);
+                        connMetrics.incrementRequestCount();
                     }
 
                 });

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncExchangeHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncExchangeHandler.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncExchangeHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncExchangeHandler.java Tue Sep 27 17:49:46 2016
@@ -33,6 +33,7 @@ import java.util.concurrent.atomic.Atomi
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
@@ -73,7 +74,7 @@ public abstract class AbstractAsyncExcha
     @Override
     public final void handleRequest(
             final HttpRequest request,
-            final boolean endStream,
+            final EntityDetails entityDetails,
             final ResponseChannel responseChannel) throws HttpException, IOException {
 
         final AsyncResponseTrigger responseTrigger = new AsyncResponseTrigger() {
@@ -83,7 +84,7 @@ public abstract class AbstractAsyncExcha
                     final AsyncResponseProducer producer) throws HttpException, IOException {
                 try {
                     if (responseProducer.compareAndSet(null, producer)) {
-                        responseChannel.sendResponse(producer.produceResponse(), !producer.isEnclosingEntity());
+                        responseChannel.sendResponse(producer.produceResponse(), producer.getEntityDetails());
                     }
                 } finally {
                     requestConsumer.releaseResources();
@@ -102,7 +103,7 @@ public abstract class AbstractAsyncExcha
             }
 
         };
-        requestConsumer.consumeRequest(request, !endStream, new FutureCallback<Message<HttpRequest, T>>() {
+        requestConsumer.consumeRequest(request, entityDetails, new FutureCallback<Message<HttpRequest, T>>() {
 
             @Override
             public void completed(final Message<HttpRequest, T> message) {

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncPushHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncPushHandler.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncPushHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncPushHandler.java Tue Sep 27 17:49:46 2016
@@ -32,6 +32,7 @@ import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
@@ -57,8 +58,9 @@ public abstract class AbstractAsyncPushH
     @Override
     public void consumePromise(
             final HttpRequest promise,
-            final HttpResponse response) throws HttpException, IOException {
-        responseConsumer.consumeResponse(response, new FutureCallback<Message<HttpResponse, T>>() {
+            final HttpResponse response,
+            final EntityDetails entityDetails) throws HttpException, IOException {
+        responseConsumer.consumeResponse(response, entityDetails, new FutureCallback<Message<HttpResponse, T>>() {
 
             @Override
             public void completed(final Message<HttpResponse, T> result) {

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractClassicExchangeHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractClassicExchangeHandler.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractClassicExchangeHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractClassicExchangeHandler.java Tue Sep 27 17:49:46 2016
@@ -32,17 +32,21 @@ import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.Header;
 import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHeaders;
 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.ProtocolVersion;
 import org.apache.hc.core5.http.message.BasicHttpResponse;
+import org.apache.hc.core5.http.message.HttpResponseWrapper;
 import org.apache.hc.core5.http.nio.entity.ContentInputStream;
 import org.apache.hc.core5.http.nio.entity.ContentOutputStream;
 import org.apache.hc.core5.http2.nio.entity.SharedInputBuffer;
@@ -83,12 +87,13 @@ public abstract class AbstractClassicExc
     @Override
     public final void handleRequest(
             final HttpRequest request,
-            final boolean endStream,
+            final EntityDetails entityDetails,
             final ResponseChannel responseChannel) throws HttpException, IOException {
 
         final AtomicBoolean responseCommitted = new AtomicBoolean(false);
 
-        final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK) {
+        final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
+        final HttpResponse responseWrapper = new HttpResponseWrapper(response){
 
             private void ensureNotCommitted() {
                 Asserts.check(!responseCommitted.get(), "Response already committed");
@@ -133,7 +138,7 @@ public abstract class AbstractClassicExc
         };
 
         final InputStream inputStream;
-        if (!endStream) {
+        if (entityDetails != null) {
             inputBuffer = new SharedInputBuffer(initialBufferSize);
             inputStream = new ContentInputStream(inputBuffer);
         } else {
@@ -146,7 +151,36 @@ public abstract class AbstractClassicExc
             private void triggerResponse() throws IOException {
                 try {
                     if (responseCommitted.compareAndSet(false, true)) {
-                        responseChannel.sendResponse(response, false);
+                        responseChannel.sendResponse(response, new EntityDetails() {
+
+                            @Override
+                            public long getContentLength() {
+                                return -1;
+                            }
+
+                            @Override
+                            public String getContentType() {
+                                final Header h = response.getFirstHeader(HttpHeaders.CONTENT_TYPE);
+                                return h != null ? h.getValue() : null;
+                            }
+
+                            @Override
+                            public String getContentEncoding() {
+                                final Header h = response.getFirstHeader(HttpHeaders.CONTENT_ENCODING);
+                                return h != null ? h.getValue() : null;
+                            }
+
+                            @Override
+                            public boolean isChunked() {
+                                return false;
+                            }
+
+                            @Override
+                            public Set<String> getTrailerNames() {
+                                return null;
+                            }
+
+                        });
                     }
                 } catch (HttpException ex) {
                     throw new IOException(ex.getMessage(), ex);
@@ -185,12 +219,13 @@ public abstract class AbstractClassicExc
                 @Override
                 public void run() {
                     try {
-                        handle(request, inputStream, response, outputStream);
+                        handle(request, inputStream, responseWrapper, outputStream);
                         if (inputStream != null) {
                             inputStream.close();
                         }
                         outputStream.close();
                     } catch (Exception ex) {
+                        exception.compareAndSet(null, ex);
                         if (inputBuffer != null) {
                             inputBuffer.abort();
                         }
@@ -242,7 +277,7 @@ public abstract class AbstractClassicExc
 
     @Override
     public void failed(final Exception cause) {
-        exception.set(cause);
+        exception.compareAndSet(null, cause);
         releaseResources();
     }
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncEntityConsumer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncEntityConsumer.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncEntityConsumer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncEntityConsumer.java Tue Sep 27 17:49:46 2016
@@ -29,6 +29,7 @@ package org.apache.hc.core5.http2.nio;
 import java.io.IOException;
 
 import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.HttpException;
 
 /**
@@ -38,6 +39,6 @@ import org.apache.hc.core5.http.HttpExce
  */
 public interface AsyncEntityConsumer<T> extends AsyncDataConsumer {
 
-    void streamStart(String contentType, FutureCallback<T> resultCallback) throws HttpException, IOException;
+    void streamStart(EntityDetails entityDetails, FutureCallback<T> resultCallback) throws HttpException, IOException;
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncEntityProducer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncEntityProducer.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncEntityProducer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncEntityProducer.java Tue Sep 27 17:49:46 2016
@@ -28,14 +28,14 @@ package org.apache.hc.core5.http2.nio;
 
 import java.io.IOException;
 
+import org.apache.hc.core5.http.EntityDetails;
+
 /**
  * Abstract asynchronous message entity producer.
  *
  * @since 5.0
  */
-public interface AsyncEntityProducer extends AsyncDataProducer {
-
-    String getContentType();
+public interface AsyncEntityProducer extends AsyncDataProducer, EntityDetails {
 
     void streamStart(final DataStreamChannel channel) throws IOException;
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java Tue Sep 27 17:49:46 2016
@@ -28,6 +28,7 @@ package org.apache.hc.core5.http2.nio;
 
 import java.io.IOException;
 
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 
@@ -38,7 +39,7 @@ import org.apache.hc.core5.http.HttpRequ
  */
 public interface AsyncExchangeHandler extends AsyncDataConsumer, AsyncDataProducer {
 
-    void handleRequest(HttpRequest request, boolean enclosedBody, ResponseChannel responseChannel) throws HttpException, IOException;
+    void handleRequest(HttpRequest request, EntityDetails entityDetails, ResponseChannel responseChannel) throws HttpException, IOException;
 
     void failed(Exception cause);
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncPushConsumer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncPushConsumer.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncPushConsumer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncPushConsumer.java Tue Sep 27 17:49:46 2016
@@ -28,6 +28,7 @@ package org.apache.hc.core5.http2.nio;
 
 import java.io.IOException;
 
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
@@ -39,7 +40,7 @@ import org.apache.hc.core5.http.HttpResp
  */
 public interface AsyncPushConsumer extends AsyncDataConsumer {
 
-    void consumePromise(HttpRequest promise, HttpResponse response) throws HttpException, IOException;
+    void consumePromise(HttpRequest promise, HttpResponse response, EntityDetails entityDetails) throws HttpException, IOException;
 
     void failed(Exception cause);
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncRequestConsumer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncRequestConsumer.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncRequestConsumer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncRequestConsumer.java Tue Sep 27 17:49:46 2016
@@ -29,6 +29,7 @@ package org.apache.hc.core5.http2.nio;
 import java.io.IOException;
 
 import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 
@@ -39,6 +40,6 @@ import org.apache.hc.core5.http.HttpRequ
  */
 public interface AsyncRequestConsumer<T> extends AsyncDataConsumer {
 
-    void consumeRequest(HttpRequest request, boolean endStream, FutureCallback<T> resultCallback) throws HttpException, IOException;
+    void consumeRequest(HttpRequest request, EntityDetails entityDetails, FutureCallback<T> resultCallback) throws HttpException, IOException;
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncRequestProducer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncRequestProducer.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncRequestProducer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncRequestProducer.java Tue Sep 27 17:49:46 2016
@@ -28,6 +28,7 @@ package org.apache.hc.core5.http2.nio;
 
 import java.io.IOException;
 
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.HttpRequest;
 
 /**
@@ -39,7 +40,7 @@ public interface AsyncRequestProducer ex
 
     HttpRequest produceRequest();
 
-    boolean isEnclosingEntity();
+    EntityDetails getEntityDetails();
 
     void dataStart(final DataStreamChannel channel) throws IOException;
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncResponseConsumer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncResponseConsumer.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncResponseConsumer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncResponseConsumer.java Tue Sep 27 17:49:46 2016
@@ -29,6 +29,7 @@ package org.apache.hc.core5.http2.nio;
 import java.io.IOException;
 
 import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpResponse;
 
@@ -39,6 +40,6 @@ import org.apache.hc.core5.http.HttpResp
  */
 public interface AsyncResponseConsumer<T> extends AsyncDataConsumer {
 
-    void consumeResponse(HttpResponse response, FutureCallback<T> resultCallback) throws HttpException, IOException;
+    void consumeResponse(HttpResponse response, EntityDetails entityDetails, FutureCallback<T> resultCallback) throws HttpException, IOException;
 
 }

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncResponseProducer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncResponseProducer.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncResponseProducer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncResponseProducer.java Tue Sep 27 17:49:46 2016
@@ -28,6 +28,7 @@ package org.apache.hc.core5.http2.nio;
 
 import java.io.IOException;
 
+import org.apache.hc.core5.http.EntityDetails;
 import org.apache.hc.core5.http.HttpResponse;
 
 /**
@@ -39,7 +40,7 @@ public interface AsyncResponseProducer e
 
     HttpResponse produceResponse();
 
-    boolean isEnclosingEntity();
+    EntityDetails getEntityDetails();
 
     void dataStart(final DataStreamChannel channel) throws IOException;
 

Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/BasicPushProducer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/BasicPushProducer.java?rev=1762527&r1=1762526&r2=1762527&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/BasicPushProducer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/BasicPushProducer.java Tue Sep 27 17:49:46 2016
@@ -30,7 +30,6 @@ import java.io.IOException;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.hc.core5.http.HttpException;
-import org.apache.hc.core5.http.HttpHeaders;
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.message.BasicHttpResponse;
@@ -61,15 +60,7 @@ public class BasicPushProducer implement
 
     @Override
     public void produceResponse(final ResponseChannel channel) throws HttpException, IOException {
-        if (!response.containsHeader(HttpHeaders.CONTENT_TYPE)) {
-            if (dataProducer != null) {
-                final String contentType = dataProducer.getContentType();
-                if (contentType != null) {
-                    response.addHeader(HttpHeaders.CONTENT_TYPE, contentType);
-                }
-            }
-        }
-        channel.sendResponse(response, dataProducer != null);
+        channel.sendResponse(response, dataProducer);
     }
 
     @Override




Mime
View raw message