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/08/09 18:15:14 UTC

[05/10] httpcomponents-core git commit: Request filters for classic and asynchronous server side protocol handlers

Request filters for classic and asynchronous server side protocol 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/52b0d269
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/tree/52b0d269
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/diff/52b0d269

Branch: refs/heads/master
Commit: 52b0d2695dc0c4259bc1ab1a6fc709312d8d63e1
Parents: ee32600
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Tue Aug 1 18:55:34 2017 +0200
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Wed Aug 9 15:00:27 2017 +0200

----------------------------------------------------------------------
 .../hc/core5/testing/nio/EchoHandler.java       |   7 -
 .../hc/core5/http/io/HttpFilterChain.java       |  57 +++++++
 .../hc/core5/http/io/HttpFilterHandler.java     |  49 ++++++
 .../io/support/HttpServerExpectationFilter.java |  82 +++++++++
 .../support/HttpServerFilterChainElement.java   |  74 +++++++++
 .../HttpServerFilterChainRequestHandler.java    |  72 ++++++++
 .../http/io/support/TerminalServerFilter.java   |  75 +++++++++
 .../hc/core5/http/nio/AsyncFilterChain.java     |  61 +++++++
 .../hc/core5/http/nio/AsyncFilterHandler.java   |  51 ++++++
 .../support/AsyncServerExpectationFilter.java   |  85 ++++++++++
 .../support/AsyncServerFilterChainElement.java  |  79 +++++++++
 ...ServerFilterChainExchangeHandlerFactory.java | 165 +++++++++++++++++++
 .../nio/support/TerminalAsyncServerFilter.java  | 146 ++++++++++++++++
 13 files changed, 996 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/EchoHandler.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/EchoHandler.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/EchoHandler.java
index f7962cc..100c982 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/EchoHandler.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/EchoHandler.java
@@ -33,7 +33,6 @@ import java.util.List;
 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;
@@ -70,12 +69,6 @@ public class EchoHandler implements AsyncServerExchangeHandler {
             final EntityDetails entityDetails,
             final ResponseChannel responseChannel,
             final HttpContext context) throws HttpException, IOException {
-        if (entityDetails != null) {
-            final Header h = request.getFirstHeader(HttpHeaders.EXPECT);
-            if (h != null && "100-continue".equalsIgnoreCase(h.getValue())) {
-                responseChannel.sendInformation(new BasicHttpResponse(HttpStatus.SC_CONTINUE));
-            }
-        }
         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
         responseChannel.sendResponse(response, entityDetails);
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/io/HttpFilterChain.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/io/HttpFilterChain.java b/httpcore5/src/main/java/org/apache/hc/core5/http/io/HttpFilterChain.java
new file mode 100644
index 0000000..f863307
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/io/HttpFilterChain.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * 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.io;
+
+import java.io.IOException;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.STATELESS)
+public interface HttpFilterChain {
+
+    interface ResponseTrigger {
+
+        void sendInformation(ClassicHttpResponse response) throws HttpException, IOException;
+
+        void submitResponse(ClassicHttpResponse response) throws HttpException, IOException;
+
+    }
+
+    void proceed(
+            ClassicHttpRequest request,
+            ResponseTrigger responseTrigger,
+            HttpContext context) throws HttpException, IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/io/HttpFilterHandler.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/io/HttpFilterHandler.java b/httpcore5/src/main/java/org/apache/hc/core5/http/io/HttpFilterHandler.java
new file mode 100644
index 0000000..4409784
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/io/HttpFilterHandler.java
@@ -0,0 +1,49 @@
+/*
+ * ====================================================================
+ * 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.io;
+
+import java.io.IOException;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.STATELESS)
+public interface HttpFilterHandler {
+
+    void handle(
+            ClassicHttpRequest request,
+            HttpFilterChain.ResponseTrigger responseTrigger,
+            HttpContext context,
+            HttpFilterChain chain) throws HttpException, IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerExpectationFilter.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerExpectationFilter.java b/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerExpectationFilter.java
new file mode 100644
index 0000000..9b5aacf
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerExpectationFilter.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.io.support;
+
+import java.io.IOException;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpEntity;
+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.io.HttpFilterChain;
+import org.apache.hc.core5.http.io.HttpFilterHandler;
+import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.STATELESS)
+public class HttpServerExpectationFilter implements HttpFilterHandler {
+
+    protected boolean verify(final ClassicHttpRequest request, final HttpContext context) throws HttpException {
+        return true;
+    }
+
+    protected HttpEntity generateResponseContent(final HttpResponse expectationFailed) throws HttpException {
+        return null;
+    }
+
+    @Override
+    public final void handle(
+            final ClassicHttpRequest request,
+            final HttpFilterChain.ResponseTrigger responseTrigger,
+            final HttpContext context,
+            final HttpFilterChain chain) throws HttpException, IOException {
+        final Header expect = request.getFirstHeader(HttpHeaders.EXPECT);
+        final boolean expectContinue = expect != null && "100-continue".equalsIgnoreCase(expect.getValue());
+        if (expectContinue) {
+            final boolean verified = verify(request, context);
+            if (verified) {
+                responseTrigger.sendInformation(new BasicClassicHttpResponse(HttpStatus.SC_CONTINUE));
+            } else {
+                final ClassicHttpResponse expectationFailed = new BasicClassicHttpResponse(HttpStatus.SC_EXPECTATION_FAILED);
+                final HttpEntity responseContent = generateResponseContent(expectationFailed);
+                expectationFailed.setEntity(responseContent);
+                responseTrigger.submitResponse(expectationFailed);
+                return;
+            }
+        }
+        chain.proceed(request, responseTrigger, context);
+    }
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerFilterChainElement.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerFilterChainElement.java b/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerFilterChainElement.java
new file mode 100644
index 0000000..69d429f
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerFilterChainElement.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * 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.io.support;
+
+import java.io.IOException;
+
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.io.HttpFilterChain;
+import org.apache.hc.core5.http.io.HttpFilterHandler;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+public final class HttpServerFilterChainElement {
+
+    private final HttpFilterHandler handler;
+    private final HttpServerFilterChainElement next;
+    private final HttpFilterChain filterChain;
+
+    public HttpServerFilterChainElement(final HttpFilterHandler handler, final HttpServerFilterChainElement next) {
+        this.handler = handler;
+        this.next = next;
+        this.filterChain = new HttpFilterChain() {
+
+            @Override
+            public void proceed(
+                    final ClassicHttpRequest request,
+                    final ResponseTrigger responseTrigger,
+                    final HttpContext context) throws HttpException, IOException {
+                next.handle(request, responseTrigger, context);
+            }
+        };
+    }
+
+    public void handle(
+            final ClassicHttpRequest request,
+            final HttpFilterChain.ResponseTrigger responseTrigger,
+            final HttpContext context) throws IOException, HttpException {
+        handler.handle(request, responseTrigger, context, filterChain);
+    }
+
+    @Override
+    public String toString() {
+        return "{" +
+                "handler=" + handler.getClass() +
+                ", next=" + (next != null ? next.handler.getClass() : "null") +
+                '}';
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerFilterChainRequestHandler.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerFilterChainRequestHandler.java b/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerFilterChainRequestHandler.java
new file mode 100644
index 0000000..c6064b9
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/HttpServerFilterChainRequestHandler.java
@@ -0,0 +1,72 @@
+/*
+ * ====================================================================
+ * 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.io.support;
+
+import java.io.IOException;
+
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.io.HttpFilterChain;
+import org.apache.hc.core5.http.io.HttpServerRequestHandler;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.util.Args;
+
+/**
+ * @since 5.0
+ */
+public class HttpServerFilterChainRequestHandler implements HttpServerRequestHandler {
+
+    private final HttpServerFilterChainElement filterChain;
+
+    public HttpServerFilterChainRequestHandler(final HttpServerFilterChainElement filterChain) {
+        this.filterChain = Args.notNull(filterChain, "Filter chain");
+    }
+
+    @Override
+    public void handle(
+            final ClassicHttpRequest request,
+            final ResponseTrigger trigger,
+            final HttpContext context) throws HttpException, IOException {
+        filterChain.handle(request, new HttpFilterChain.ResponseTrigger() {
+
+            @Override
+            public void sendInformation(final ClassicHttpResponse response) throws HttpException, IOException {
+                trigger.sendInformation(response);
+            }
+
+            @Override
+            public void submitResponse(final ClassicHttpResponse response) throws HttpException, IOException {
+                trigger.submitResponse(response);
+
+            }
+
+        }, context);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/TerminalServerFilter.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/TerminalServerFilter.java b/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/TerminalServerFilter.java
new file mode 100644
index 0000000..a059f4c
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/io/support/TerminalServerFilter.java
@@ -0,0 +1,75 @@
+/*
+ * ====================================================================
+ * 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.io.support;
+
+import java.io.IOException;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpRequestMapper;
+import org.apache.hc.core5.http.HttpResponseFactory;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.impl.io.DefaultClassicHttpResponseFactory;
+import org.apache.hc.core5.http.io.HttpFilterChain;
+import org.apache.hc.core5.http.io.HttpFilterHandler;
+import org.apache.hc.core5.http.io.HttpRequestHandler;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.util.Args;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.STATELESS)
+public final class TerminalServerFilter implements HttpFilterHandler {
+
+    private final HttpRequestMapper<HttpRequestHandler> handlerMapper;
+    private final HttpResponseFactory<ClassicHttpResponse> responseFactory;
+
+    public TerminalServerFilter(final HttpRequestMapper<HttpRequestHandler> handlerMapper, final HttpResponseFactory<ClassicHttpResponse> responseFactory) {
+        this.handlerMapper = Args.notNull(handlerMapper, "Handler mapper");
+        this.responseFactory = responseFactory != null ? responseFactory : DefaultClassicHttpResponseFactory.INSTANCE;
+    }
+
+    @Override
+    public final void handle(
+            final ClassicHttpRequest request,
+            final HttpFilterChain.ResponseTrigger responseTrigger,
+            final HttpContext context,
+            final HttpFilterChain chain) throws HttpException, IOException {
+        final ClassicHttpResponse response = responseFactory.newHttpResponse(HttpStatus.SC_OK);
+        final HttpRequestHandler handler = handlerMapper.resolve(request, context);
+        if (handler != null) {
+            handler.handle(request, response, context);
+        } else {
+            response.setCode(HttpStatus.SC_NOT_IMPLEMENTED);
+        }
+        responseTrigger.submitResponse(response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncFilterChain.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncFilterChain.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncFilterChain.java
new file mode 100644
index 0000000..c2ef87d
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncFilterChain.java
@@ -0,0 +1,61 @@
+/*
+ * ====================================================================
+ * 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.nio;
+
+import java.io.IOException;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.EntityDetails;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.STATELESS)
+public interface AsyncFilterChain {
+
+    interface ResponseTrigger {
+
+        void sendInformation(HttpResponse response) throws HttpException, IOException;
+
+        void submitResponse(HttpResponse response, AsyncEntityProducer entityProducer) throws HttpException, IOException;
+
+        void pushPromise(HttpRequest promise, AsyncPushProducer responseProducer) throws HttpException, IOException;
+
+    }
+
+    AsyncDataConsumer proceed(
+            HttpRequest request,
+            EntityDetails entityDetails,
+            HttpContext context,
+            ResponseTrigger responseTrigger) throws HttpException, IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncFilterHandler.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncFilterHandler.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncFilterHandler.java
new file mode 100644
index 0000000..83f0dea
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/AsyncFilterHandler.java
@@ -0,0 +1,51 @@
+/*
+ * ====================================================================
+ * 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.nio;
+
+import java.io.IOException;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.EntityDetails;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.STATELESS)
+public interface AsyncFilterHandler {
+
+    AsyncDataConsumer handle(
+            HttpRequest request,
+            EntityDetails entityDetails,
+            HttpContext context,
+            AsyncFilterChain.ResponseTrigger responseTrigger,
+            AsyncFilterChain chain) throws HttpException, IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerExpectationFilter.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerExpectationFilter.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerExpectationFilter.java
new file mode 100644
index 0000000..67ef9a3
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerExpectationFilter.java
@@ -0,0 +1,85 @@
+/*
+ * ====================================================================
+ * 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.nio.support;
+
+import java.io.IOException;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.EntityDetails;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.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.message.BasicHttpResponse;
+import org.apache.hc.core5.http.nio.AsyncDataConsumer;
+import org.apache.hc.core5.http.nio.AsyncEntityProducer;
+import org.apache.hc.core5.http.nio.AsyncFilterChain;
+import org.apache.hc.core5.http.nio.AsyncFilterHandler;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.STATELESS)
+public abstract class AsyncServerExpectationFilter implements AsyncFilterHandler {
+
+    protected boolean verify(final HttpRequest request, final HttpContext context) throws HttpException {
+        return true;
+    }
+
+    protected AsyncEntityProducer generateResponseContent(final HttpResponse expectationFailed) throws HttpException {
+        return null;
+    }
+
+    @Override
+    public AsyncDataConsumer handle(
+            final HttpRequest request,
+            final EntityDetails entityDetails,
+            final HttpContext context,
+            final AsyncFilterChain.ResponseTrigger responseTrigger,
+            final AsyncFilterChain chain) throws HttpException, IOException {
+        if (entityDetails != null) {
+            final Header h = request.getFirstHeader(HttpHeaders.EXPECT);
+            if (h != null && "100-continue".equalsIgnoreCase(h.getValue())) {
+                final boolean verified = verify(request, context);
+                if (verified) {
+                    responseTrigger.sendInformation(new BasicHttpResponse(HttpStatus.SC_CONTINUE));
+                } else {
+                    final HttpResponse expectationFailed = new BasicHttpResponse(HttpStatus.SC_EXPECTATION_FAILED);
+                    final AsyncEntityProducer responseContentProducer = generateResponseContent(expectationFailed);
+                    responseTrigger.submitResponse(expectationFailed, responseContentProducer);
+                    return null;
+                }
+            }
+        }
+        return chain.proceed(request, entityDetails, context, responseTrigger);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerFilterChainElement.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerFilterChainElement.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerFilterChainElement.java
new file mode 100644
index 0000000..d423ecc
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerFilterChainElement.java
@@ -0,0 +1,79 @@
+/*
+ * ====================================================================
+ * 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.nio.support;
+
+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.nio.AsyncDataConsumer;
+import org.apache.hc.core5.http.nio.AsyncFilterChain;
+import org.apache.hc.core5.http.nio.AsyncFilterHandler;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+public final class AsyncServerFilterChainElement {
+
+    private final AsyncFilterHandler handler;
+    private final AsyncServerFilterChainElement next;
+    private final AsyncFilterChain filterChain;
+
+    public AsyncServerFilterChainElement(final AsyncFilterHandler handler, final AsyncServerFilterChainElement next) {
+        this.handler = handler;
+        this.next = next;
+        this.filterChain = new AsyncFilterChain() {
+
+            @Override
+            public AsyncDataConsumer proceed(
+                    final HttpRequest request,
+                    final EntityDetails entityDetails,
+                    final HttpContext context,
+                    final ResponseTrigger responseTrigger) throws HttpException, IOException {
+                return next.handle(request, entityDetails, context, responseTrigger);
+            }
+
+        };
+    }
+
+    public AsyncDataConsumer handle(
+            final HttpRequest request,
+            final EntityDetails entityDetails,
+            final HttpContext context,
+            final AsyncFilterChain.ResponseTrigger responseTrigger) throws HttpException, IOException {
+        return handler.handle(request, entityDetails, context, responseTrigger, filterChain);
+    }
+
+    @Override
+    public String toString() {
+        return "{" +
+                "handler=" + handler.getClass() +
+                ", next=" + (next != null ? next.handler.getClass() : "null") +
+                '}';
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerFilterChainExchangeHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerFilterChainExchangeHandlerFactory.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerFilterChainExchangeHandlerFactory.java
new file mode 100644
index 0000000..6c5da73
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AsyncServerFilterChainExchangeHandlerFactory.java
@@ -0,0 +1,165 @@
+/*
+ * ====================================================================
+ * 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.nio.support;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.List;
+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.HttpRequest;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.nio.AsyncDataConsumer;
+import org.apache.hc.core5.http.nio.AsyncEntityProducer;
+import org.apache.hc.core5.http.nio.AsyncFilterChain;
+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;
+import org.apache.hc.core5.http.nio.ResponseChannel;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.util.Args;
+import org.apache.hc.core5.util.Asserts;
+
+public final class AsyncServerFilterChainExchangeHandlerFactory implements HandlerFactory<AsyncServerExchangeHandler> {
+
+    private final AsyncServerFilterChainElement filterChain;
+
+    public AsyncServerFilterChainExchangeHandlerFactory(final AsyncServerFilterChainElement filterChain) {
+        this.filterChain = Args.notNull(filterChain, "Filter chain");
+    }
+
+    @Override
+    public AsyncServerExchangeHandler create(final HttpRequest request, final HttpContext context) throws HttpException {
+        return new AsyncServerExchangeHandler() {
+
+            private final AtomicReference<AsyncDataConsumer> dataConsumerRef = new AtomicReference<>();
+            private final AtomicReference<AsyncResponseProducer> responseProducerRef = new AtomicReference<>();
+
+            @Override
+            public void handleRequest(
+                    final HttpRequest request,
+                    final EntityDetails entityDetails,
+                    final ResponseChannel responseChannel,
+                    final HttpContext context) throws HttpException, IOException {
+                dataConsumerRef.set(filterChain.handle(request, entityDetails, context, new AsyncFilterChain.ResponseTrigger() {
+
+                    @Override
+                    public void sendInformation(
+                            final HttpResponse response) throws HttpException, IOException {
+                        responseChannel.sendInformation(response);
+                    }
+
+                    @Override
+                    public void submitResponse(
+                            final HttpResponse response,
+                            final AsyncEntityProducer entityProducer) throws HttpException, IOException {
+                        final AsyncResponseProducer responseProducer = new BasicResponseProducer(response, entityProducer);
+                        responseProducerRef.set(responseProducer);
+                        responseProducer.sendResponse(responseChannel);
+                    }
+
+                    @Override
+                    public void pushPromise(final HttpRequest promise, final AsyncPushProducer responseProducer) throws HttpException, IOException {
+                        responseChannel.pushPromise(promise, responseProducer);
+                    }
+
+                }));
+            }
+
+            @Override
+            public void failed(final Exception cause) {
+                final AsyncResponseProducer handler = responseProducerRef.get();
+                if (handler != null) {
+                    handler.failed(cause);
+                }
+            }
+
+            @Override
+            public void updateCapacity(final CapacityChannel capacityChannel) throws IOException {
+                final AsyncDataConsumer dataConsumer = dataConsumerRef.get();
+                if (dataConsumer != null) {
+                    dataConsumer.updateCapacity(capacityChannel);
+                } else {
+                    capacityChannel.update(Integer.MAX_VALUE);
+                }
+            }
+
+            @Override
+            public int consume(final ByteBuffer src) throws IOException {
+                final AsyncDataConsumer dataConsumer = dataConsumerRef.get();
+                if (dataConsumer != null) {
+                    return dataConsumer.consume(src);
+                } else {
+                    return Integer.MAX_VALUE;
+                }
+            }
+
+            @Override
+            public void streamEnd(final List<? extends Header> trailers) throws HttpException, IOException {
+                final AsyncDataConsumer dataConsumer = dataConsumerRef.get();
+                if (dataConsumer != null) {
+                    dataConsumer.streamEnd(trailers);
+                }
+            }
+
+            @Override
+            public int available() {
+                final AsyncResponseProducer responseProducer = responseProducerRef.get();
+                Asserts.notNull(responseProducer, "Response producer");
+                return responseProducer.available();
+            }
+
+            @Override
+            public void produce(final DataStreamChannel channel) throws IOException {
+                final AsyncResponseProducer responseProducer = responseProducerRef.get();
+                Asserts.notNull(responseProducer, "Response producer");
+                responseProducer.produce(channel);
+            }
+
+            @Override
+            public void releaseResources() {
+                final AsyncDataConsumer dataConsumer = dataConsumerRef.getAndSet(null);
+                if (dataConsumer != null) {
+                    dataConsumer.releaseResources();
+                }
+                final AsyncResponseProducer responseProducer = responseProducerRef.getAndSet(null);
+                if (responseProducer != null) {
+                    responseProducer.releaseResources();
+                }
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/52b0d269/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/TerminalAsyncServerFilter.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/TerminalAsyncServerFilter.java b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/TerminalAsyncServerFilter.java
new file mode 100644
index 0000000..50762c0
--- /dev/null
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/TerminalAsyncServerFilter.java
@@ -0,0 +1,146 @@
+/*
+ * ====================================================================
+ * 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.nio.support;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.EntityDetails;
+import org.apache.hc.core5.http.HttpException;
+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.message.BasicHttpResponse;
+import org.apache.hc.core5.http.nio.AsyncDataConsumer;
+import org.apache.hc.core5.http.nio.AsyncEntityProducer;
+import org.apache.hc.core5.http.nio.AsyncFilterChain;
+import org.apache.hc.core5.http.nio.AsyncFilterHandler;
+import org.apache.hc.core5.http.nio.AsyncPushProducer;
+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.entity.BasicAsyncEntityProducer;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.util.Args;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.STATELESS)
+public final class TerminalAsyncServerFilter implements AsyncFilterHandler {
+
+    final private HandlerFactory<AsyncServerExchangeHandler> handlerFactory;
+
+    public TerminalAsyncServerFilter(final HandlerFactory<AsyncServerExchangeHandler> handlerFactory) {
+        this.handlerFactory = Args.notNull(handlerFactory, "Handler factory");
+    }
+
+    @Override
+    public AsyncDataConsumer handle(
+            final HttpRequest request,
+            final EntityDetails entityDetails,
+            final HttpContext context,
+            final AsyncFilterChain.ResponseTrigger responseTrigger,
+            final AsyncFilterChain chain) throws HttpException, IOException {
+        final AsyncServerExchangeHandler exchangeHandler = handlerFactory.create(request, context);
+        if (exchangeHandler != null) {
+            exchangeHandler.handleRequest(request, entityDetails, new ResponseChannel() {
+
+                @Override
+                public void sendInformation(final HttpResponse response) throws HttpException, IOException {
+                    responseTrigger.sendInformation(response);
+                }
+
+                @Override
+                public void sendResponse(final HttpResponse response, final EntityDetails entityDetails) throws HttpException, IOException {
+                    responseTrigger.submitResponse(response, entityDetails != null ? new AsyncEntityProducer() {
+
+                        @Override
+                        public void failed(final Exception cause) {
+                            exchangeHandler.failed(cause);
+                        }
+
+                        @Override
+                        public long getContentLength() {
+                            return entityDetails.getContentLength();
+                        }
+
+                        @Override
+                        public String getContentType() {
+                            return entityDetails.getContentType();
+                        }
+
+                        @Override
+                        public String getContentEncoding() {
+                            return entityDetails.getContentEncoding();
+                        }
+
+                        @Override
+                        public boolean isChunked() {
+                            return entityDetails.isChunked();
+                        }
+
+                        @Override
+                        public Set<String> getTrailerNames() {
+                            return entityDetails.getTrailerNames();
+                        }
+
+                        @Override
+                        public int available() {
+                            return exchangeHandler.available();
+                        }
+
+                        @Override
+                        public void produce(final DataStreamChannel channel) throws IOException {
+                            exchangeHandler.produce(channel);
+                        }
+
+                        @Override
+                        public void releaseResources() {
+                            exchangeHandler.releaseResources();
+                        }
+
+                    } : null);
+                }
+
+                @Override
+                public void pushPromise(final HttpRequest promise, final AsyncPushProducer pushProducer) throws HttpException, IOException {
+                    responseTrigger.pushPromise(promise, pushProducer);
+                }
+
+            }, context);
+            return exchangeHandler;
+        } else {
+            responseTrigger.submitResponse(new BasicHttpResponse(HttpStatus.SC_NOT_FOUND), new BasicAsyncEntityProducer("Not found"));
+            return null;
+        }
+    }
+
+}