You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2016/12/04 13:50:00 UTC
svn commit: r1772536 [1/2] - in /httpcomponents/httpcore/trunk:
httpcore5-h2/src/examples/ httpcore5-h2/src/examples/org/
httpcore5-h2/src/examples/org/apache/
httpcore5-h2/src/examples/org/apache/hc/
httpcore5-h2/src/examples/org/apache/hc/core5/ http...
Author: olegk
Date: Sun Dec 4 13:49:59 2016
New Revision: 1772536
URL: http://svn.apache.org/viewvc?rev=1772536&view=rev
Log:
Added bootstrap classes for HTTP/2 server and requester; updated examples
Added:
httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/
httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/
httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/
httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/
httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/
httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/
httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/
httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2FileServerExample.java (with props)
httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2MultiStreamExecutionExample.java
- copied, changed from r1772441, httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2RequestExecutionExample.java
- copied, changed from r1772441, httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/Http2Processors.java (contents, props changed)
- copied, changed from r1772441, httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/AsyncPushConsumerRegistry.java (with props)
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java (with props)
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java (with props)
Removed:
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java
Modified:
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/Http2StreamListener.java
httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http/Http1TestClient.java
httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/Http2TestClient.java
httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/Http2TestServer.java
httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/InternalHttp2StreamListener.java
httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java
httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncRequestExecutionExample.java
httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/ClassicGetExecutionExample.java
httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/ClassicPostExecutionExample.java
httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/ClassicPostWithTrailersExecutionExample.java
httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/HttpRequester.java
httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/bootstrap/HttpServer.java
httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/bootstrap/AsyncRequester.java
httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/message/BasicHttpRequest.java
httpcomponents/httpcore/trunk/httpcore5/src/main/java/org/apache/hc/core5/http/nio/BasicRequestProducer.java
Added: httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2FileServerExample.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2FileServerExample.java?rev=1772536&view=auto
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2FileServerExample.java (added)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2FileServerExample.java Sun Dec 4 13:49:59 2016
@@ -0,0 +1,240 @@
+/*
+ * ====================================================================
+ * 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.examples;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketTimeoutException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.core5.http.ConnectionClosedException;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.ExceptionListener;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpConnection;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.Message;
+import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.hc.core5.http.impl.nio.bootstrap.HttpAsyncServer;
+import org.apache.hc.core5.http.nio.AsyncRequestConsumer;
+import org.apache.hc.core5.http.nio.BasicRequestConsumer;
+import org.apache.hc.core5.http.nio.BasicResponseProducer;
+import org.apache.hc.core5.http.nio.entity.FileEntityProducer;
+import org.apache.hc.core5.http.nio.entity.NoopEntityConsumer;
+import org.apache.hc.core5.http.nio.support.RequestConsumerSupplier;
+import org.apache.hc.core5.http.nio.support.ResponseHandler;
+import org.apache.hc.core5.http.nio.support.ResponseTrigger;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.http.protocol.HttpCoreContext;
+import org.apache.hc.core5.http2.frame.RawFrame;
+import org.apache.hc.core5.http2.impl.nio.Http2StreamListener;
+import org.apache.hc.core5.http2.impl.nio.bootstrap.H2ServerBootstrap;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+import org.apache.hc.core5.reactor.ListenerEndpoint;
+
+/**
+ * Example of asynchronous embedded HTTP/2 file server.
+ */
+public class Http2FileServerExample {
+
+ public static void main(String[] args) throws Exception {
+ if (args.length < 1) {
+ System.err.println("Please specify document root directory");
+ System.exit(1);
+ }
+ // Document root directory
+ final File docRoot = new File(args[0]);
+ int port = 8080;
+ if (args.length >= 2) {
+ port = Integer.parseInt(args[1]);
+ }
+
+ IOReactorConfig config = IOReactorConfig.custom()
+ .setSoTimeout(15000)
+ .setTcpNoDelay(true)
+ .build();
+
+ final HttpAsyncServer server = H2ServerBootstrap.bootstrap()
+ .setIOReactorConfig(config)
+ .setExceptionListener(new ExceptionListener() {
+
+ @Override
+ public void onError(final Exception ex) {
+ if (ex instanceof ConnectionClosedException) {
+ return;
+ }
+ if (ex instanceof SocketTimeoutException) {
+ System.out.println("Timeout");
+ } else if (ex instanceof IOException) {
+ System.out.println("I/O error: " + ex.getMessage());
+ } else {
+ ex.printStackTrace();
+ }
+ }
+ })
+ .setConnectionListener(new ConnectionListener() {
+
+ @Override
+ public void onConnect(final HttpConnection connection) {
+ System.out.println(connection + " connected");
+ }
+
+ @Override
+ public void onError(final HttpConnection connection, final Exception ex) {
+ System.err.println(connection + " error: " + ex.getMessage());
+ }
+
+ @Override
+ public void onDisconnect(final HttpConnection connection) {
+ System.out.println(connection + " disconnected");
+ }
+
+ })
+ .setStreamListener(new Http2StreamListener() {
+
+ @Override
+ public void onHeaderInput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
+ for (int i = 0; i < headers.size(); i++) {
+ System.out.println(connection + " (" + streamId + ") << " + headers.get(i));
+ }
+ }
+
+ @Override
+ public void onHeaderOutput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
+ for (int i = 0; i < headers.size(); i++) {
+ System.out.println(connection + " (" + streamId + ") >> " + headers.get(i));
+ }
+ }
+
+ @Override
+ public void onFrameInput(final HttpConnection connection, final int streamId, final RawFrame frame) {
+ }
+
+ @Override
+ public void onFrameOutput(final HttpConnection connection, final int streamId, final RawFrame frame) {
+ }
+
+ @Override
+ public void onInputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
+ }
+
+ @Override
+ public void onOutputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
+ }
+
+ })
+ .register("*", new RequestConsumerSupplier<Message<HttpRequest, Void>>() {
+
+ @Override
+ public AsyncRequestConsumer<Message<HttpRequest, Void>> get(
+ final HttpRequest request,
+ final HttpContext context) throws HttpException {
+ return new BasicRequestConsumer<>(new NoopEntityConsumer());
+ }
+
+ }, new ResponseHandler<Message<HttpRequest, Void>>() {
+
+ @Override
+ public void handle(
+ final Message<HttpRequest, Void> message,
+ final ResponseTrigger responseTrigger,
+ final HttpContext context) throws HttpException, IOException {
+ HttpRequest request = message.getHead();
+ URI requestUri;
+ try {
+ requestUri = request.getUri();
+ } catch (URISyntaxException ex) {
+ throw new ProtocolException(ex.getMessage(), ex);
+ }
+ String path = requestUri.getPath();
+ final File file = new File(docRoot, path);
+ if (!file.exists()) {
+
+ System.out.println("File " + file.getPath() + " not found");
+ responseTrigger.submitResponse(new BasicResponseProducer(
+ HttpStatus.SC_NOT_FOUND,
+ "<html><body><h1>File" + file.getPath() +
+ " not found</h1></body></html>",
+ ContentType.TEXT_HTML));
+
+ } else if (!file.canRead() || file.isDirectory()) {
+
+ System.out.println("Cannot read file " + file.getPath());
+ responseTrigger.submitResponse(new BasicResponseProducer(
+ HttpStatus.SC_FORBIDDEN,
+ "<html><body><h1>Access denied</h1></body></html>",
+ ContentType.TEXT_HTML));
+
+ } else {
+
+ final ContentType contentType;
+ final String filename = file.getName().toLowerCase(Locale.ROOT);
+ if (filename.endsWith(".txt")) {
+ contentType = ContentType.TEXT_PLAIN;
+ } else if (filename.endsWith(".html") || filename.endsWith(".htm")) {
+ contentType = ContentType.TEXT_HTML;
+ } else if (filename.endsWith(".xml")) {
+ contentType = ContentType.TEXT_XML;
+ } else {
+ contentType = ContentType.DEFAULT_BINARY;
+ }
+
+ final HttpConnection connection = (HttpConnection) context.getAttribute(HttpCoreContext.HTTP_CONNECTION);
+
+ System.out.println(connection + " serving file " + file.getPath());
+ responseTrigger.submitResponse(new BasicResponseProducer(
+ HttpStatus.SC_OK, new FileEntityProducer(file, contentType)));
+ }
+ }
+
+ })
+ .create();
+
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ System.out.println("HTTP server shutting down");
+ server.shutdown(5, TimeUnit.SECONDS);
+ }
+ });
+
+ server.start();
+ ListenerEndpoint listenerEndpoint = server.listen(new InetSocketAddress(port));
+ listenerEndpoint.waitFor();
+ System.out.print("Listening on " + listenerEndpoint.getAddress());
+ server.awaitShutdown(Long.MAX_VALUE, TimeUnit.DAYS);
+ }
+
+}
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2FileServerExample.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2FileServerExample.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2FileServerExample.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Copied: httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2MultiStreamExecutionExample.java (from r1772441, httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2MultiStreamExecutionExample.java?p2=httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2MultiStreamExecutionExample.java&p1=httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java&r1=1772441&r2=1772536&rev=1772536&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2MultiStreamExecutionExample.java Sun Dec 4 13:49:59 2016
@@ -26,31 +26,75 @@
*/
package org.apache.hc.core5.http.examples;
-import java.net.URI;
+import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpConnection;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.Message;
import org.apache.hc.core5.http.impl.nio.bootstrap.HttpAsyncRequester;
import org.apache.hc.core5.http.impl.nio.bootstrap.PooledClientEndpoint;
-import org.apache.hc.core5.http.impl.nio.bootstrap.RequesterBootstrap;
import org.apache.hc.core5.http.nio.BasicRequestProducer;
import org.apache.hc.core5.http.nio.BasicResponseConsumer;
import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
+import org.apache.hc.core5.http2.config.H2Config;
+import org.apache.hc.core5.http2.frame.RawFrame;
+import org.apache.hc.core5.http2.impl.nio.Http2StreamListener;
+import org.apache.hc.core5.http2.impl.nio.bootstrap.H2RequesterBootstrap;
/**
- * Example of asynchronous HTTP/1.1 request execution.
+ * Example of HTTP/2 concurrent request execution using multiple streams.
*/
-public class AsyncPipelinedRequestExecutionExample {
+public class Http2MultiStreamExecutionExample {
public static void main(String[] args) throws Exception {
// Create and start requester
- final HttpAsyncRequester requester = RequesterBootstrap.bootstrap().create();
+ H2Config h2Config = H2Config.custom()
+ .setPushEnabled(false)
+ .setMaxConcurrentStreams(100)
+ .build();
+ final HttpAsyncRequester requester = H2RequesterBootstrap.bootstrap()
+ .setH2Config(h2Config)
+ .setStreamListener(new Http2StreamListener() {
+
+ @Override
+ public void onHeaderInput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
+ for (int i = 0; i < headers.size(); i++) {
+ System.out.println(connection + " (" + streamId + ") << " + headers.get(i));
+ }
+ }
+
+ @Override
+ public void onHeaderOutput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
+ for (int i = 0; i < headers.size(); i++) {
+ System.out.println(connection + " (" + streamId + ") >> " + headers.get(i));
+ }
+ }
+
+ @Override
+ public void onFrameInput(final HttpConnection connection, final int streamId, final RawFrame frame) {
+ }
+
+ @Override
+ public void onFrameOutput(final HttpConnection connection, final int streamId, final RawFrame frame) {
+ }
+
+ @Override
+ public void onInputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
+ }
+
+ @Override
+ public void onOutputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
+ }
+
+ })
+ .create();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
@@ -60,9 +104,8 @@ public class AsyncPipelinedRequestExecut
});
requester.start();
- HttpHost target = new HttpHost("www.apache.org");
- String[] requestUris = new String[] {"/", "/foundation",
- "/foundation/how-it-works.html", "/foundation/getinvolved.html"};
+ HttpHost target = new HttpHost("http2bin.org");
+ String[] requestUris = new String[] {"/", "/ip", "/user-agent", "/headers"};
Future<PooledClientEndpoint> future = requester.connect(target, 5, TimeUnit.SECONDS);
PooledClientEndpoint clientEndpoint = future.get();
@@ -70,7 +113,7 @@ public class AsyncPipelinedRequestExecut
final CountDownLatch latch = new CountDownLatch(requestUris.length);
for (final String requestUri: requestUris) {
clientEndpoint.execute(
- new BasicRequestProducer("GET", URI.create(requestUri)),
+ new BasicRequestProducer("GET", target, requestUri),
new BasicResponseConsumer<>(new StringAsyncEntityConsumer()),
new FutureCallback<Message<HttpResponse, String>>() {
@@ -78,7 +121,9 @@ public class AsyncPipelinedRequestExecut
public void completed(final Message<HttpResponse, String> message) {
latch.countDown();
HttpResponse response = message.getHead();
+ String body = message.getBody();
System.out.println(requestUri + "->" + response.getCode());
+ System.out.println(body);
}
@Override
Copied: httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2RequestExecutionExample.java (from r1772441, httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2RequestExecutionExample.java?p2=httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2RequestExecutionExample.java&p1=httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java&r1=1772441&r2=1772536&rev=1772536&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2RequestExecutionExample.java Sun Dec 4 13:49:59 2016
@@ -26,31 +26,75 @@
*/
package org.apache.hc.core5.http.examples;
-import java.net.URI;
+import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpConnection;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.Message;
import org.apache.hc.core5.http.impl.nio.bootstrap.HttpAsyncRequester;
import org.apache.hc.core5.http.impl.nio.bootstrap.PooledClientEndpoint;
-import org.apache.hc.core5.http.impl.nio.bootstrap.RequesterBootstrap;
import org.apache.hc.core5.http.nio.BasicRequestProducer;
import org.apache.hc.core5.http.nio.BasicResponseConsumer;
import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
+import org.apache.hc.core5.http2.config.H2Config;
+import org.apache.hc.core5.http2.frame.RawFrame;
+import org.apache.hc.core5.http2.impl.nio.Http2StreamListener;
+import org.apache.hc.core5.http2.impl.nio.bootstrap.H2RequesterBootstrap;
/**
- * Example of asynchronous HTTP/1.1 request execution.
+ * Example of HTTP/2 request execution.
*/
-public class AsyncPipelinedRequestExecutionExample {
+public class Http2RequestExecutionExample {
public static void main(String[] args) throws Exception {
// Create and start requester
- final HttpAsyncRequester requester = RequesterBootstrap.bootstrap().create();
+ H2Config h2Config = H2Config.custom()
+ .setPushEnabled(false)
+ .build();
+
+ final HttpAsyncRequester requester = H2RequesterBootstrap.bootstrap()
+ .setH2Config(h2Config)
+ .setStreamListener(new Http2StreamListener() {
+
+ @Override
+ public void onHeaderInput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
+ for (int i = 0; i < headers.size(); i++) {
+ System.out.println(connection + " (" + streamId + ") << " + headers.get(i));
+ }
+ }
+
+ @Override
+ public void onHeaderOutput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
+ for (int i = 0; i < headers.size(); i++) {
+ System.out.println(connection + " (" + streamId + ") >> " + headers.get(i));
+ }
+ }
+
+ @Override
+ public void onFrameInput(final HttpConnection connection, final int streamId, final RawFrame frame) {
+ }
+
+ @Override
+ public void onFrameOutput(final HttpConnection connection, final int streamId, final RawFrame frame) {
+ }
+
+ @Override
+ public void onInputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
+ }
+
+ @Override
+ public void onOutputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
+ }
+
+ })
+ .create();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
@@ -60,17 +104,15 @@ public class AsyncPipelinedRequestExecut
});
requester.start();
- HttpHost target = new HttpHost("www.apache.org");
- String[] requestUris = new String[] {"/", "/foundation",
- "/foundation/how-it-works.html", "/foundation/getinvolved.html"};
-
- Future<PooledClientEndpoint> future = requester.connect(target, 5, TimeUnit.SECONDS);
- PooledClientEndpoint clientEndpoint = future.get();
+ HttpHost target = new HttpHost("http2bin.org");
+ String[] requestUris = new String[] {"/", "/ip", "/user-agent", "/headers"};
final CountDownLatch latch = new CountDownLatch(requestUris.length);
for (final String requestUri: requestUris) {
- clientEndpoint.execute(
- new BasicRequestProducer("GET", URI.create(requestUri)),
+ final Future<PooledClientEndpoint> future = requester.connect(target, 5, TimeUnit.SECONDS);
+ final PooledClientEndpoint clientEndpoint = future.get();
+ clientEndpoint.executeAndRelease(
+ new BasicRequestProducer("GET", target, requestUri),
new BasicResponseConsumer<>(new StringAsyncEntityConsumer()),
new FutureCallback<Message<HttpResponse, String>>() {
@@ -78,7 +120,9 @@ public class AsyncPipelinedRequestExecut
public void completed(final Message<HttpResponse, String> message) {
latch.countDown();
HttpResponse response = message.getHead();
+ String body = message.getBody();
System.out.println(requestUri + "->" + response.getCode());
+ System.out.println(body);
}
@Override
@@ -97,10 +141,6 @@ public class AsyncPipelinedRequestExecut
}
latch.await();
-
- // Manually release client endpoint when done !!!
- clientEndpoint.releaseResources();
-
System.out.println("Shutting down I/O reactor");
requester.initiateShutdown();
}
Copied: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/Http2Processors.java (from r1772441, httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/Http2Processors.java?p2=httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/Http2Processors.java&p1=httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java&r1=1772441&r2=1772536&rev=1772536&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/bootstrap/Http2Processors.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/Http2Processors.java Sun Dec 4 13:49:59 2016
@@ -24,7 +24,7 @@
* <http://www.apache.org/>.
*
*/
-package org.apache.hc.core5.http2.bootstrap;
+package org.apache.hc.core5.http2.impl;
import org.apache.hc.core5.http.impl.HttpProcessors;
import org.apache.hc.core5.http.protocol.HttpProcessor;
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/Http2Processors.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/Http2Processors.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/Http2Processors.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
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=1772536&r1=1772535&r2=1772536&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 Sun Dec 4 13:49:59 2016
@@ -178,7 +178,7 @@ abstract class AbstractHttp2StreamMultip
final int streamId, final AtomicInteger window, final int delta) throws ArithmeticException {
final int newSize = updateWindow(window, delta);
if (streamListener != null) {
- streamListener.onInputFlowControl(streamId, delta, newSize);
+ streamListener.onInputFlowControl(this, streamId, delta, newSize);
}
return newSize;
}
@@ -187,7 +187,7 @@ abstract class AbstractHttp2StreamMultip
final int streamId, final AtomicInteger window, final int delta) throws ArithmeticException {
final int newSize = updateWindow(window, delta);
if (streamListener != null) {
- streamListener.onOutputFlowControl(streamId, delta, newSize);
+ streamListener.onOutputFlowControl(this, streamId, delta, newSize);
}
return newSize;
}
@@ -195,7 +195,7 @@ abstract class AbstractHttp2StreamMultip
private void commitFrameInternal(final RawFrame frame) throws IOException {
if (outputBuffer.isEmpty() && outputQueue.isEmpty()) {
if (streamListener != null) {
- streamListener.onFrameOutput(frame);
+ streamListener.onFrameOutput(this, frame.getStreamId(), frame);
}
outputBuffer.write(frame, ioSession.channel());
} else {
@@ -217,7 +217,7 @@ abstract class AbstractHttp2StreamMultip
private void commitHeaders(
final int streamId, final List<? extends Header> headers, final boolean endStream) throws IOException {
if (streamListener != null) {
- streamListener.onHeaderOutput(headers);
+ streamListener.onHeaderOutput(this, streamId, headers);
}
final ByteArrayBuffer buf = new ByteArrayBuffer(512);
hPackEncoder.encodeHeaders(buf, headers);
@@ -251,7 +251,7 @@ abstract class AbstractHttp2StreamMultip
throw new H2ConnectionException(H2Error.INTERNAL_ERROR, "Message headers are missing");
}
if (streamListener != null) {
- streamListener.onHeaderOutput(headers);
+ streamListener.onHeaderOutput(this, streamId, headers);
}
final ByteArrayBuffer buf = new ByteArrayBuffer(512);
buf.append((byte)(promisedStreamId >> 24));
@@ -298,7 +298,7 @@ abstract class AbstractHttp2StreamMultip
chunk = payload.remaining();
final RawFrame dataFrame = frameFactory.createData(streamId, payload, false);
if (streamListener != null) {
- streamListener.onFrameOutput(dataFrame);
+ streamListener.onFrameOutput(this, streamId, dataFrame);
}
outputBuffer.write(dataFrame, ioSession.channel());
} else {
@@ -308,7 +308,7 @@ abstract class AbstractHttp2StreamMultip
payload.limit(payload.position() + chunk);
final RawFrame dataFrame = frameFactory.createData(streamId, payload, false);
if (streamListener != null) {
- streamListener.onFrameOutput(dataFrame);
+ streamListener.onFrameOutput(this, streamId, dataFrame);
}
outputBuffer.write(dataFrame, ioSession.channel());
} finally {
@@ -387,7 +387,7 @@ abstract class AbstractHttp2StreamMultip
RawFrame frame;
while ((frame = inputBuffer.read(ioSession.channel())) != null) {
if (streamListener != null) {
- streamListener.onFrameInput(frame);
+ streamListener.onFrameInput(this, frame.getStreamId(), frame);
}
consumeFrame(frame);
}
@@ -404,7 +404,7 @@ abstract class AbstractHttp2StreamMultip
final RawFrame frame = outputQueue.poll();
if (frame != null) {
if (streamListener != null) {
- streamListener.onFrameOutput(frame);
+ streamListener.onFrameOutput(this, frame.getStreamId(), frame);
}
outputBuffer.write(frame, ioSession.channel());
} else {
@@ -907,7 +907,7 @@ abstract class AbstractHttp2StreamMultip
processedRemoteStreamId = promisedStreamId;
}
if (streamListener != null) {
- streamListener.onHeaderInput(headers);
+ streamListener.onHeaderInput(this, promisedStreamId, headers);
}
if (connState == ConnectionHandshake.GRACEFUL_SHUTDOWN) {
throw new H2StreamResetException(H2Error.REFUSED_STREAM, "Stream refused");
@@ -935,7 +935,7 @@ abstract class AbstractHttp2StreamMultip
processedRemoteStreamId = streamId;
}
if (streamListener != null) {
- streamListener.onHeaderInput(headers);
+ streamListener.onHeaderInput(this, streamId, headers);
}
if (connState == ConnectionHandshake.GRACEFUL_SHUTDOWN) {
throw new H2StreamResetException(H2Error.PROTOCOL_ERROR, "Stream refused");
@@ -965,7 +965,7 @@ abstract class AbstractHttp2StreamMultip
processedRemoteStreamId = streamId;
}
if (streamListener != null) {
- streamListener.onHeaderInput(headers);
+ streamListener.onHeaderInput(this, streamId, headers);
}
if (connState == ConnectionHandshake.GRACEFUL_SHUTDOWN) {
throw new H2StreamResetException(H2Error.PROTOCOL_ERROR, "Stream refused");
Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamListener.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamListener.java?rev=1772536&r1=1772535&r2=1772536&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamListener.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/Http2StreamListener.java Sun Dec 4 13:49:59 2016
@@ -31,6 +31,7 @@ import java.util.List;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpConnection;
import org.apache.hc.core5.http2.frame.RawFrame;
/**
@@ -41,16 +42,16 @@ import org.apache.hc.core5.http2.frame.R
@Contract(threading = ThreadingBehavior.STATELESS)
public interface Http2StreamListener {
- void onHeaderInput(List<? extends Header> headers);
+ void onHeaderInput(HttpConnection connection, int streamId, List<? extends Header> headers);
- void onHeaderOutput(List<? extends Header> headers);
+ void onHeaderOutput(HttpConnection connection, int streamId, List<? extends Header> headers);
- void onFrameInput(RawFrame frame);
+ void onFrameInput(HttpConnection connection, int streamId, RawFrame frame);
- void onFrameOutput(RawFrame frame);
+ void onFrameOutput(HttpConnection connection, int streamId, RawFrame frame);
- void onInputFlowControl(int streamId, int delta, int actualSize);
+ void onInputFlowControl(HttpConnection connection, int streamId, int delta, int actualSize);
- void onOutputFlowControl(int streamId, int delta, int actualSize);
+ void onOutputFlowControl(HttpConnection connection, int streamId, int delta, int actualSize);
}
Added: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/AsyncPushConsumerRegistry.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/AsyncPushConsumerRegistry.java?rev=1772536&view=auto
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/AsyncPushConsumerRegistry.java (added)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/AsyncPushConsumerRegistry.java Sun Dec 4 13:49:59 2016
@@ -0,0 +1,103 @@
+/*
+ * ====================================================================
+ * 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.http2.impl.nio.bootstrap;
+
+import java.util.Locale;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.hc.core5.function.Supplier;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.nio.AsyncPushConsumer;
+import org.apache.hc.core5.http.nio.HandlerFactory;
+import org.apache.hc.core5.http.protocol.UriPatternMatcher;
+import org.apache.hc.core5.net.URIAuthority;
+import org.apache.hc.core5.util.Args;
+
+public class AsyncPushConsumerRegistry implements HandlerFactory<AsyncPushConsumer> {
+
+ private final UriPatternMatcher<Supplier<AsyncPushConsumer>> primary;
+ private final ConcurrentMap<String, UriPatternMatcher<Supplier<AsyncPushConsumer>>> hostMap;
+
+ public AsyncPushConsumerRegistry() {
+ this.primary = new UriPatternMatcher<>();
+ this.hostMap = new ConcurrentHashMap<>();
+ }
+
+ private UriPatternMatcher<Supplier<AsyncPushConsumer>> getPatternMatcher(final String hostname) {
+ if (hostname == null) {
+ return primary;
+ }
+ final UriPatternMatcher<Supplier<AsyncPushConsumer>> hostMatcher = hostMap.get(hostname);
+ if (hostMatcher != null) {
+ return hostMatcher;
+ }
+ return primary;
+ }
+
+ @Override
+ public AsyncPushConsumer create(final HttpRequest request) throws HttpException {
+ final URIAuthority authority = request.getAuthority();
+ final String key = authority != null ? authority.getHostName().toLowerCase(Locale.ROOT) : null;
+ final UriPatternMatcher<Supplier<AsyncPushConsumer>> patternMatcher = getPatternMatcher(key);
+ if (patternMatcher == null) {
+ return null;
+ }
+ String path = request.getPath();
+ final int i = path.indexOf("?");
+ if (i != -1) {
+ path = path.substring(0, i - 1);
+ }
+ final Supplier<AsyncPushConsumer> supplier = patternMatcher.lookup(path);
+ if (supplier != null) {
+ return supplier.get();
+ }
+ return null;
+ }
+
+ public void register(final String hostname, final String uriPattern, final Supplier<AsyncPushConsumer> supplier) {
+ Args.notBlank(uriPattern, "URI pattern");
+ Args.notNull(supplier, "Supplier");
+ if (hostname == null) {
+ primary.register(uriPattern, supplier);
+ } else {
+ final String key = hostname.toLowerCase(Locale.ROOT);
+ UriPatternMatcher<Supplier<AsyncPushConsumer>> matcher = hostMap.get(key);
+ if (matcher == null) {
+ final UriPatternMatcher<Supplier<AsyncPushConsumer>> newMatcher = new UriPatternMatcher<>();
+ matcher = hostMap.putIfAbsent(key, newMatcher);
+ if (matcher == null) {
+ matcher = newMatcher;
+ }
+ }
+ matcher.register(uriPattern, supplier);
+ }
+ }
+
+}
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/AsyncPushConsumerRegistry.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/AsyncPushConsumerRegistry.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/AsyncPushConsumerRegistry.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java?rev=1772536&view=auto
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java (added)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java Sun Dec 4 13:49:59 2016
@@ -0,0 +1,210 @@
+/*
+ * ====================================================================
+ * 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.http2.impl.nio.bootstrap;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.core5.function.Supplier;
+import org.apache.hc.core5.http.ExceptionListener;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.hc.core5.http.impl.nio.bootstrap.ClientEndpoint;
+import org.apache.hc.core5.http.impl.nio.bootstrap.HttpAsyncRequester;
+import org.apache.hc.core5.http.nio.AsyncPushConsumer;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http2.config.H2Config;
+import org.apache.hc.core5.http2.impl.Http2Processors;
+import org.apache.hc.core5.http2.impl.nio.ClientHttpProtocolNegotiatorFactory;
+import org.apache.hc.core5.http2.impl.nio.Http2StreamListener;
+import org.apache.hc.core5.pool.ConnPoolListener;
+import org.apache.hc.core5.pool.StrictConnPool;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+import org.apache.hc.core5.util.Args;
+
+/**
+ * @since 5.0
+ */
+public class H2RequesterBootstrap {
+
+ private final List<PushConsumerEntry> pushConsumerList;
+
+ private IOReactorConfig ioReactorConfig;
+ private HttpProcessor httpProcessor;
+ private Charset charset;
+ private H2Config h2Config;
+ private int defaultMaxPerRoute;
+ private int maxTotal;
+ private long timeToLive;
+ private TimeUnit timeUnit;
+ private ExceptionListener exceptionListener;
+ private ConnectionListener connectionListener;
+ private Http2StreamListener streamListener;
+ private ConnPoolListener<HttpHost> connPoolListener;
+
+ private H2RequesterBootstrap() {
+ this.pushConsumerList = new ArrayList<>();
+ }
+
+ public static H2RequesterBootstrap bootstrap() {
+ return new H2RequesterBootstrap();
+ }
+
+ /**
+ * Sets I/O reactor configuration.
+ */
+ public final H2RequesterBootstrap setIOReactorConfig(final IOReactorConfig ioReactorConfig) {
+ this.ioReactorConfig = ioReactorConfig;
+ return this;
+ }
+
+ /**
+ * Assigns {@link HttpProcessor} instance.
+ */
+ public final H2RequesterBootstrap setHttpProcessor(final HttpProcessor httpProcessor) {
+ this.httpProcessor = httpProcessor;
+ return this;
+ }
+
+ /**
+ * Sets HTTP/2 protocol parameters
+ */
+ public final H2RequesterBootstrap setH2Config(final H2Config h2Config) {
+ this.h2Config = h2Config;
+ return this;
+ }
+
+ /**
+ * Sets charset for HTTP/2 messages.
+ */
+ public final H2RequesterBootstrap setCharset(final Charset charset) {
+ this.charset = charset;
+ return this;
+ }
+
+ public final H2RequesterBootstrap setDefaultMaxPerRoute(final int defaultMaxPerRoute) {
+ this.defaultMaxPerRoute = defaultMaxPerRoute;
+ return this;
+ }
+
+ public final H2RequesterBootstrap setMaxTotal(final int maxTotal) {
+ this.maxTotal = maxTotal;
+ return this;
+ }
+
+ public final H2RequesterBootstrap setTimeToLive(final long timeToLive, final TimeUnit timeUnit) {
+ this.timeToLive = timeToLive;
+ this.timeUnit = timeUnit;
+ return this;
+ }
+
+ /**
+ * Assigns {@link ExceptionListener} instance.
+ */
+ public final H2RequesterBootstrap setExceptionListener(final ExceptionListener exceptionListener) {
+ this.exceptionListener = exceptionListener;
+ return this;
+ }
+
+ /**
+ * Assigns {@link ConnectionListener} instance.
+ */
+ public final H2RequesterBootstrap setConnectionListener(final ConnectionListener connectionListener) {
+ this.connectionListener = connectionListener;
+ return this;
+ }
+
+ /**
+ * Assigns {@link Http2StreamListener} instance.
+ */
+ public final H2RequesterBootstrap setStreamListener(final Http2StreamListener streamListener) {
+ this.streamListener = streamListener;
+ return this;
+ }
+
+ public final H2RequesterBootstrap setConnPoolListener(final ConnPoolListener<HttpHost> connPoolListener) {
+ this.connPoolListener = connPoolListener;
+ return this;
+ }
+
+ public final H2RequesterBootstrap register(final String uriPattern, final Supplier<AsyncPushConsumer> supplier) {
+ Args.notBlank(uriPattern, "URI pattern");
+ Args.notNull(supplier, "Supplier");
+ pushConsumerList.add(new PushConsumerEntry(null, uriPattern, supplier));
+ return this;
+ }
+
+ public final H2RequesterBootstrap register(final String hostname, final String uriPattern, final Supplier<AsyncPushConsumer> supplier) {
+ Args.notBlank(hostname, "Hostname");
+ Args.notBlank(uriPattern, "URI pattern");
+ Args.notNull(supplier, "Supplier");
+ pushConsumerList.add(new PushConsumerEntry(hostname, uriPattern, supplier));
+ return this;
+ }
+
+ public HttpAsyncRequester create() {
+ final StrictConnPool<HttpHost, ClientEndpoint> connPool = new StrictConnPool<>(
+ defaultMaxPerRoute > 0 ? defaultMaxPerRoute : 20,
+ maxTotal > 0 ? maxTotal : 50,
+ timeToLive, timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS,
+ connPoolListener);
+ final AsyncPushConsumerRegistry pushConsumerRegistry = new AsyncPushConsumerRegistry();
+ for (PushConsumerEntry entry: pushConsumerList) {
+ pushConsumerRegistry.register(entry.hostname, entry.uriPattern, entry.supplier);
+ }
+ final ClientHttpProtocolNegotiatorFactory ioEventHandlerFactory = new ClientHttpProtocolNegotiatorFactory(
+ httpProcessor != null ? httpProcessor : Http2Processors.client(),
+ pushConsumerRegistry,
+ charset != null ? charset : StandardCharsets.US_ASCII,
+ h2Config != null ? h2Config : H2Config.DEFAULT,
+ connectionListener,
+ streamListener);
+ return new HttpAsyncRequester(
+ ioReactorConfig,
+ exceptionListener,
+ ioEventHandlerFactory,
+ connPool);
+ }
+
+ private static class PushConsumerEntry {
+
+ final String hostname;
+ final String uriPattern;
+ final Supplier<AsyncPushConsumer> supplier;
+
+ public PushConsumerEntry(final String hostname, final String uriPattern, final Supplier<AsyncPushConsumer> supplier) {
+ this.hostname = hostname;
+ this.uriPattern = uriPattern;
+ this.supplier = supplier;
+ }
+
+ }
+
+}
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java?rev=1772536&view=auto
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java (added)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java Sun Dec 4 13:49:59 2016
@@ -0,0 +1,220 @@
+/*
+ * ====================================================================
+ * 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.http2.impl.nio.bootstrap;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hc.core5.function.Supplier;
+import org.apache.hc.core5.http.ExceptionListener;
+import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.hc.core5.http.impl.nio.bootstrap.AsyncServerExchangeHandlerRegistry;
+import org.apache.hc.core5.http.impl.nio.bootstrap.HttpAsyncServer;
+import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
+import org.apache.hc.core5.http.nio.support.BasicServerExchangeHandler;
+import org.apache.hc.core5.http.nio.support.RequestConsumerSupplier;
+import org.apache.hc.core5.http.nio.support.ResponseHandler;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http2.config.H2Config;
+import org.apache.hc.core5.http2.impl.Http2Processors;
+import org.apache.hc.core5.http2.impl.nio.Http2StreamListener;
+import org.apache.hc.core5.http2.impl.nio.ServerHttpProtocolNegotiatorFactory;
+import org.apache.hc.core5.net.InetAddressUtils;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+import org.apache.hc.core5.util.Args;
+
+/**
+ * @since 5.0
+ */
+public class H2ServerBootstrap {
+
+ private final List<HandlerEntry> handlerList;
+ private String canonicalHostName;
+ private IOReactorConfig ioReactorConfig;
+ private HttpProcessor httpProcessor;
+ private Charset charset;
+ private H2Config h2Config;
+ private ExceptionListener exceptionListener;
+ private ConnectionListener connectionListener;
+ private Http2StreamListener streamListener;
+
+ private H2ServerBootstrap() {
+ this.handlerList = new ArrayList<>();
+ }
+
+ public static H2ServerBootstrap bootstrap() {
+ return new H2ServerBootstrap();
+ }
+
+ /**
+ * Sets canonical name (fully qualified domain name) of the server.
+ *
+ * @since 5.0
+ */
+ public final H2ServerBootstrap setCanonicalHostName(final String canonicalHostName) {
+ this.canonicalHostName = canonicalHostName;
+ return this;
+ }
+
+ /**
+ * Sets I/O reactor configuration.
+ */
+ public final H2ServerBootstrap setIOReactorConfig(final IOReactorConfig ioReactorConfig) {
+ this.ioReactorConfig = ioReactorConfig;
+ return this;
+ }
+
+ /**
+ * Assigns {@link HttpProcessor} instance.
+ */
+ public final H2ServerBootstrap setHttpProcessor(final HttpProcessor httpProcessor) {
+ this.httpProcessor = httpProcessor;
+ return this;
+ }
+
+ /**
+ * Sets HTTP/2 protocol parameters
+ */
+ public final H2ServerBootstrap setH2Config(final H2Config h2Config) {
+ this.h2Config = h2Config;
+ return this;
+ }
+
+ /**
+ * Sets charset for HTTP/2 messages.
+ */
+ public final H2ServerBootstrap setCharset(final Charset charset) {
+ this.charset = charset;
+ return this;
+ }
+
+ /**
+ * Assigns {@link ExceptionListener} instance.
+ */
+ public final H2ServerBootstrap setExceptionListener(final ExceptionListener exceptionListener) {
+ this.exceptionListener = exceptionListener;
+ return this;
+ }
+
+ /**
+ * Assigns {@link ConnectionListener} instance.
+ */
+ public final H2ServerBootstrap setConnectionListener(final ConnectionListener connectionListener) {
+ this.connectionListener = connectionListener;
+ return this;
+ }
+
+ /**
+ * Assigns {@link Http2StreamListener} instance.
+ */
+ public final H2ServerBootstrap setStreamListener(final Http2StreamListener streamListener) {
+ this.streamListener = streamListener;
+ return this;
+ }
+
+ public final H2ServerBootstrap register(final String uriPattern, final Supplier<AsyncServerExchangeHandler> supplier) {
+ Args.notBlank(uriPattern, "URI pattern");
+ Args.notNull(supplier, "Supplier");
+ handlerList.add(new HandlerEntry(null, uriPattern, supplier));
+ return this;
+ }
+
+ public final H2ServerBootstrap registerVirtual(final String hostname, final String uriPattern, final Supplier<AsyncServerExchangeHandler> supplier) {
+ Args.notBlank(hostname, "Hostname");
+ Args.notBlank(uriPattern, "URI pattern");
+ Args.notNull(supplier, "Supplier");
+ handlerList.add(new HandlerEntry(hostname, uriPattern, supplier));
+ return this;
+ }
+
+ public final <T> H2ServerBootstrap register(
+ final String uriPattern,
+ final RequestConsumerSupplier<T> consumerSupplier,
+ final ResponseHandler<T> responseHandler) {
+ register(uriPattern, new Supplier<AsyncServerExchangeHandler>() {
+
+ @Override
+ public AsyncServerExchangeHandler get() {
+ return new BasicServerExchangeHandler<>(consumerSupplier, responseHandler);
+ }
+
+ });
+ return this;
+ }
+
+ public final <T> H2ServerBootstrap registerVirtual(
+ final String hostname,
+ final String uriPattern,
+ final RequestConsumerSupplier<T> consumerSupplier,
+ final ResponseHandler<T> responseHandler) {
+ registerVirtual(hostname, uriPattern, new Supplier<AsyncServerExchangeHandler>() {
+
+ @Override
+ public AsyncServerExchangeHandler get() {
+ return new BasicServerExchangeHandler<>(consumerSupplier, responseHandler);
+ }
+
+ });
+ return this;
+ }
+
+ public HttpAsyncServer create() {
+ final AsyncServerExchangeHandlerRegistry exchangeHandlerFactory = new AsyncServerExchangeHandlerRegistry(
+ canonicalHostName != null ? canonicalHostName : InetAddressUtils.getCanonicalLocalHostName());
+ for (HandlerEntry entry: handlerList) {
+ exchangeHandlerFactory.register(entry.hostname, entry.uriPattern, entry.supplier);
+ }
+ final ServerHttpProtocolNegotiatorFactory ioEventHandlerFactory = new ServerHttpProtocolNegotiatorFactory(
+ httpProcessor != null ? httpProcessor : Http2Processors.server(),
+ exchangeHandlerFactory,
+ charset != null ? charset : StandardCharsets.US_ASCII,
+ h2Config != null ? h2Config : H2Config.DEFAULT,
+ connectionListener,
+ streamListener);
+ return new HttpAsyncServer(
+ ioEventHandlerFactory,
+ ioReactorConfig,
+ exceptionListener);
+ }
+
+ private static class HandlerEntry {
+
+ final String hostname;
+ final String uriPattern;
+ final Supplier<AsyncServerExchangeHandler> supplier;
+
+ public HandlerEntry(final String hostname, final String uriPattern, final Supplier<AsyncServerExchangeHandler> supplier) {
+ this.hostname = hostname;
+ this.uriPattern = uriPattern;
+ this.supplier = supplier;
+ }
+
+ }
+
+}
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http/Http1TestClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http/Http1TestClient.java?rev=1772536&r1=1772535&r2=1772536&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http/Http1TestClient.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http/Http1TestClient.java Sun Dec 4 13:49:59 2016
@@ -43,12 +43,11 @@ import org.apache.hc.core5.http.config.C
import org.apache.hc.core5.http.config.H1Config;
import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
import org.apache.hc.core5.http.impl.HttpProcessors;
-import org.apache.hc.core5.http.impl.nio.bootstrap.ClientEndpoint;
import org.apache.hc.core5.http.impl.nio.bootstrap.AsyncRequester;
+import org.apache.hc.core5.http.impl.nio.bootstrap.ClientEndpoint;
import org.apache.hc.core5.http.nio.command.ShutdownCommand;
import org.apache.hc.core5.http.nio.command.ShutdownType;
import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.apache.hc.core5.net.NamedEndpoint;
import org.apache.hc.core5.reactor.IOReactorConfig;
import org.apache.hc.core5.reactor.IOSession;
import org.apache.hc.core5.reactor.SessionRequest;
@@ -109,20 +108,20 @@ public class Http1TestClient extends Asy
@Override
public SessionRequest requestSession(
- final NamedEndpoint remoteEndpoint,
+ final HttpHost host,
final long timeout,
final TimeUnit timeUnit,
final SessionRequestCallback callback) {
- return super.requestSession(remoteEndpoint, timeout, timeUnit, callback);
+ return super.requestSession(host, timeout, timeUnit, callback);
}
public Future<ClientEndpoint> connect(
- final NamedEndpoint remoteEndpoint,
+ final HttpHost host,
final long timeout,
final TimeUnit timeUnit,
final FutureCallback<ClientEndpoint> callback) throws InterruptedException {
final BasicFuture<ClientEndpoint> future = new BasicFuture<>(callback);
- requestSession(remoteEndpoint, timeout, timeUnit, new SessionRequestCallback() {
+ requestSession(host, timeout, timeUnit, new SessionRequestCallback() {
@Override
public void completed(final SessionRequest request) {
@@ -149,10 +148,10 @@ public class Http1TestClient extends Asy
}
public Future<ClientEndpoint> connect(
- final NamedEndpoint remoteEndpoint,
+ final HttpHost host,
final long timeout,
final TimeUnit timeUnit) throws InterruptedException {
- return connect(remoteEndpoint, timeout, timeUnit, null);
+ return connect(host, timeout, timeUnit, null);
}
public Future<ClientEndpoint> connect(
Modified: httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/Http2TestClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/Http2TestClient.java?rev=1772536&r1=1772535&r2=1772536&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/Http2TestClient.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/Http2TestClient.java Sun Dec 4 13:49:59 2016
@@ -40,22 +40,16 @@ import org.apache.hc.core5.concurrent.Fu
import org.apache.hc.core5.function.Callback;
import org.apache.hc.core5.function.Supplier;
import org.apache.hc.core5.http.ExceptionListener;
-import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpHost;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.MisdirectedRequestException;
-import org.apache.hc.core5.http.impl.nio.bootstrap.ClientEndpoint;
import org.apache.hc.core5.http.impl.nio.bootstrap.AsyncRequester;
+import org.apache.hc.core5.http.impl.nio.bootstrap.ClientEndpoint;
import org.apache.hc.core5.http.nio.AsyncPushConsumer;
-import org.apache.hc.core5.http.nio.HandlerFactory;
import org.apache.hc.core5.http.nio.command.ShutdownCommand;
import org.apache.hc.core5.http.nio.command.ShutdownType;
import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.apache.hc.core5.http.protocol.UriPatternMatcher;
-import org.apache.hc.core5.http2.bootstrap.Http2Processors;
import org.apache.hc.core5.http2.config.H2Config;
-import org.apache.hc.core5.net.NamedEndpoint;
-import org.apache.hc.core5.net.URIAuthority;
+import org.apache.hc.core5.http2.impl.Http2Processors;
+import org.apache.hc.core5.http2.impl.nio.bootstrap.AsyncPushConsumerRegistry;
import org.apache.hc.core5.reactor.IOEventHandlerFactory;
import org.apache.hc.core5.reactor.IOReactorConfig;
import org.apache.hc.core5.reactor.IOSession;
@@ -68,7 +62,7 @@ import org.apache.logging.log4j.Logger;
public class Http2TestClient extends AsyncRequester {
private final SSLContext sslContext;
- private final UriPatternMatcher<Supplier<AsyncPushConsumer>> pushHandlerMatcher;
+ private final AsyncPushConsumerRegistry pushConsumerRegistry;
public Http2TestClient(final IOReactorConfig ioReactorConfig, final SSLContext sslContext) throws IOException {
super(ioReactorConfig, new ExceptionListener() {
@@ -89,36 +83,17 @@ public class Http2TestClient extends Asy
});
this.sslContext = sslContext;
- this.pushHandlerMatcher = new UriPatternMatcher<>();
+ this.pushConsumerRegistry = new AsyncPushConsumerRegistry();
}
public Http2TestClient() throws IOException {
this(IOReactorConfig.DEFAULT, null);
}
- private AsyncPushConsumer createHandler(final HttpRequest request) throws HttpException {
-
- final URIAuthority authority = request.getAuthority();
- if (authority != null && !"localhost".equalsIgnoreCase(authority.getHostName())) {
- throw new MisdirectedRequestException("Not authoritative");
- }
- String path = request.getPath();
- final int i = path.indexOf("?");
- if (i != -1) {
- path = path.substring(0, i - 1);
- }
- final Supplier<AsyncPushConsumer> supplier = pushHandlerMatcher.lookup(path);
- if (supplier != null) {
- return supplier.get();
- } else {
- return null;
- }
- }
-
public void register(final String uriPattern, final Supplier<AsyncPushConsumer> supplier) {
Args.notNull(uriPattern, "URI pattern");
Args.notNull(supplier, "Supplier");
- pushHandlerMatcher.register(uriPattern, supplier);
+ pushConsumerRegistry.register(null, uriPattern, supplier);
}
public void start(final IOEventHandlerFactory handlerFactory) throws IOException {
@@ -128,14 +103,7 @@ public class Http2TestClient extends Asy
public void start(final HttpProcessor httpProcessor, final H2Config h2Config) throws IOException {
start(new InternalClientHttp2EventHandlerFactory(
httpProcessor,
- new HandlerFactory<AsyncPushConsumer>() {
-
- @Override
- public AsyncPushConsumer create(final HttpRequest request) throws HttpException {
- return createHandler(request);
- }
-
- },
+ pushConsumerRegistry,
StandardCharsets.US_ASCII,
h2Config,
sslContext));
@@ -150,12 +118,12 @@ public class Http2TestClient extends Asy
}
public Future<ClientEndpoint> connect(
- final NamedEndpoint remoteEndpoint,
+ final HttpHost host,
final long timeout,
final TimeUnit timeUnit,
final FutureCallback<ClientEndpoint> callback) throws InterruptedException {
final BasicFuture<ClientEndpoint> future = new BasicFuture<>(callback);
- requestSession(remoteEndpoint, timeout, timeUnit, new SessionRequestCallback() {
+ requestSession(host, timeout, timeUnit, new SessionRequestCallback() {
@Override
public void completed(final SessionRequest request) {
@@ -182,10 +150,10 @@ public class Http2TestClient extends Asy
}
public Future<ClientEndpoint> connect(
- final NamedEndpoint remoteEndpoint,
+ final HttpHost host,
final long timeout,
final TimeUnit timeUnit) throws InterruptedException {
- return connect(remoteEndpoint, timeout, timeUnit, null);
+ return connect(host, timeout, timeUnit, null);
}
public Future<ClientEndpoint> connect(
Modified: httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/Http2TestServer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/Http2TestServer.java?rev=1772536&r1=1772535&r2=1772536&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/Http2TestServer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/Http2TestServer.java Sun Dec 4 13:49:59 2016
@@ -45,7 +45,7 @@ import org.apache.hc.core5.http.nio.supp
import org.apache.hc.core5.http.nio.support.RequestConsumerSupplier;
import org.apache.hc.core5.http.nio.support.ResponseHandler;
import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.apache.hc.core5.http2.bootstrap.Http2Processors;
+import org.apache.hc.core5.http2.impl.Http2Processors;
import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.reactor.IOEventHandlerFactory;
import org.apache.hc.core5.reactor.IOReactorConfig;
Modified: httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/InternalHttp2StreamListener.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/InternalHttp2StreamListener.java?rev=1772536&r1=1772535&r2=1772536&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/InternalHttp2StreamListener.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/http2/InternalHttp2StreamListener.java Sun Dec 4 13:49:59 2016
@@ -31,6 +31,7 @@ import java.io.IOException;
import java.util.List;
import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpConnection;
import org.apache.hc.core5.http2.frame.FramePrinter;
import org.apache.hc.core5.http2.frame.RawFrame;
import org.apache.hc.core5.http2.impl.nio.Http2StreamListener;
@@ -82,7 +83,7 @@ class InternalHttp2StreamListener implem
}
@Override
- public void onHeaderInput(final List<? extends Header> headers) {
+ public void onHeaderInput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
if (headerLog.isDebugEnabled()) {
for (int i = 0; i < headers.size(); i++) {
headerLog.debug(id + " << " + headers.get(i));
@@ -91,7 +92,7 @@ class InternalHttp2StreamListener implem
}
@Override
- public void onHeaderOutput(final List<? extends Header> headers) {
+ public void onHeaderOutput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
if (headerLog.isDebugEnabled()) {
for (int i = 0; i < headers.size(); i++) {
headerLog.debug(id + " >> " + headers.get(i));
@@ -100,7 +101,7 @@ class InternalHttp2StreamListener implem
}
@Override
- public void onFrameInput(final RawFrame frame) {
+ public void onFrameInput(final HttpConnection connection, final int streamId, final RawFrame frame) {
if (frameLog.isDebugEnabled()) {
logFrameInfo(id + " <<", frame);
}
@@ -110,7 +111,7 @@ class InternalHttp2StreamListener implem
}
@Override
- public void onFrameOutput(final RawFrame frame) {
+ public void onFrameOutput(final HttpConnection connection, final int streamId, final RawFrame frame) {
if (frameLog.isDebugEnabled()) {
logFrameInfo(id + " >>", frame);
}
@@ -120,14 +121,14 @@ class InternalHttp2StreamListener implem
}
@Override
- public void onInputFlowControl(final int streamId, final int delta, final int actualSize) {
+ public void onInputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
if (flowCtrlLog.isDebugEnabled()) {
logFlowControl(id + " <<", streamId, delta, actualSize);
}
}
@Override
- public void onOutputFlowControl(final int streamId, final int delta, final int actualSize) {
+ public void onOutputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
if (flowCtrlLog.isDebugEnabled()) {
logFlowControl(id + " >>", streamId, delta, actualSize);
}
Modified: httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java?rev=1772536&r1=1772535&r2=1772536&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncPipelinedRequestExecutionExample.java Sun Dec 4 13:49:59 2016
@@ -26,21 +26,26 @@
*/
package org.apache.hc.core5.http.examples;
-import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.HttpConnection;
import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.Message;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
import org.apache.hc.core5.http.impl.nio.bootstrap.HttpAsyncRequester;
import org.apache.hc.core5.http.impl.nio.bootstrap.PooledClientEndpoint;
import org.apache.hc.core5.http.impl.nio.bootstrap.RequesterBootstrap;
+import org.apache.hc.core5.http.message.RequestLine;
+import org.apache.hc.core5.http.message.StatusLine;
import org.apache.hc.core5.http.nio.BasicRequestProducer;
import org.apache.hc.core5.http.nio.BasicResponseConsumer;
import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
+import org.apache.hc.core5.reactor.IOReactorConfig;
/**
* Example of asynchronous HTTP/1.1 request execution.
@@ -49,8 +54,39 @@ public class AsyncPipelinedRequestExecut
public static void main(String[] args) throws Exception {
+ IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
+ .setConnectTimeout(5000)
+ .setSoTimeout(5000)
+ .build();
+
// Create and start requester
- final HttpAsyncRequester requester = RequesterBootstrap.bootstrap().create();
+ final HttpAsyncRequester requester = RequesterBootstrap.bootstrap()
+ .setIOReactorConfig(ioReactorConfig)
+ .setStreamListener(new Http1StreamListener() {
+
+ @Override
+ public void onRequestHead(final HttpConnection connection, final HttpRequest request) {
+ System.out.println(connection + " " + new RequestLine(request));
+
+ }
+
+ @Override
+ public void onResponseHead(final HttpConnection connection, final HttpResponse response) {
+ System.out.println(connection + " " + new StatusLine(response));
+ }
+
+ @Override
+ public void onExchangeComplete(final HttpConnection connection, final boolean keepAlive) {
+ if (keepAlive) {
+ System.out.println(connection + " can be kept alive");
+ } else {
+ System.out.println(connection + " cannot be kept alive");
+ }
+ }
+
+ })
+ .create();
+
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
@@ -60,9 +96,8 @@ public class AsyncPipelinedRequestExecut
});
requester.start();
- HttpHost target = new HttpHost("www.apache.org");
- String[] requestUris = new String[] {"/", "/foundation",
- "/foundation/how-it-works.html", "/foundation/getinvolved.html"};
+ HttpHost target = new HttpHost("httpbin.org");
+ String[] requestUris = new String[] {"/", "/ip", "/user-agent", "/headers"};
Future<PooledClientEndpoint> future = requester.connect(target, 5, TimeUnit.SECONDS);
PooledClientEndpoint clientEndpoint = future.get();
@@ -70,7 +105,7 @@ public class AsyncPipelinedRequestExecut
final CountDownLatch latch = new CountDownLatch(requestUris.length);
for (final String requestUri: requestUris) {
clientEndpoint.execute(
- new BasicRequestProducer("GET", URI.create(requestUri)),
+ new BasicRequestProducer("GET", target, requestUri),
new BasicResponseConsumer<>(new StringAsyncEntityConsumer()),
new FutureCallback<Message<HttpResponse, String>>() {
@@ -78,7 +113,9 @@ public class AsyncPipelinedRequestExecut
public void completed(final Message<HttpResponse, String> message) {
latch.countDown();
HttpResponse response = message.getHead();
+ String body = message.getBody();
System.out.println(requestUri + "->" + response.getCode());
+ System.out.println(body);
}
@Override