convenience API methods, checkstyle and findbug fixes
This commit is contained in:
parent
8f1a7211e6
commit
741228dd76
16 changed files with 164 additions and 96 deletions
|
@ -56,10 +56,10 @@ page at http://checkstyle.sourceforge.net/config.html -->
|
||||||
<!-- Checks for out of order import statements. -->
|
<!-- Checks for out of order import statements. -->
|
||||||
|
|
||||||
<property name="severity" value="warning"/>
|
<property name="severity" value="warning"/>
|
||||||
<property name="groups" value="com,io,junit,net,org,java,javax"/>
|
<property name="groups" value="com,io,junit,net,org,javax,java"/>
|
||||||
<!-- This ensures that static imports go last. -->
|
<!-- This ensures that static imports go last. -->
|
||||||
<property name="option" value="under"/>
|
<property name="option" value="under"/>
|
||||||
<property name="tokens" value="STATIC_IMPORT, IMPORT"/>
|
<property name="tokens" value="IMPORT, STATIC_IMPORT"/>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
|
@ -41,10 +41,6 @@ import io.netty.handler.codec.http2.HttpConversionUtil;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static io.netty.handler.codec.http2.Http2Error.INTERNAL_ERROR;
|
|
||||||
import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
|
|
||||||
import static io.netty.handler.codec.http2.Http2Exception.connectionError;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A HTTP/2 event adapter for a client.
|
* A HTTP/2 event adapter for a client.
|
||||||
* This event adapter expects {@link Http2Settings} are sent from the server before the
|
* This event adapter expects {@link Http2Settings} are sent from the server before the
|
||||||
|
@ -80,7 +76,7 @@ public class Http2EventHandler extends Http2EventAdapter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles an inbound {@code SETTINGS} frame.
|
* Handles an inbound {@code SETTINGS} frame.
|
||||||
* After frame is received, the reuqets is sent.
|
* After frame is received, the request is sent.
|
||||||
*
|
*
|
||||||
* @param ctx the context from the handler where the frame was read.
|
* @param ctx the context from the handler where the frame was read.
|
||||||
* @param settings the settings received from the remote endpoint.
|
* @param settings the settings received from the remote endpoint.
|
||||||
|
@ -214,12 +210,13 @@ public class Http2EventHandler extends Http2EventAdapter {
|
||||||
Http2Stream stream = connection.stream(streamId);
|
Http2Stream stream = connection.stream(streamId);
|
||||||
FullHttpMessage msg = getMessage(stream);
|
FullHttpMessage msg = getMessage(stream);
|
||||||
if (msg == null) {
|
if (msg == null) {
|
||||||
throw connectionError(PROTOCOL_ERROR, "data frame received for unknown stream id %d", streamId);
|
throw Http2Exception.connectionError(Http2Error.PROTOCOL_ERROR,
|
||||||
|
"data frame received for unknown stream id %d", streamId);
|
||||||
}
|
}
|
||||||
ByteBuf content = msg.content();
|
ByteBuf content = msg.content();
|
||||||
final int dataReadableBytes = data.readableBytes();
|
final int dataReadableBytes = data.readableBytes();
|
||||||
if (content.readableBytes() > maxContentLength - dataReadableBytes) {
|
if (content.readableBytes() > maxContentLength - dataReadableBytes) {
|
||||||
throw connectionError(INTERNAL_ERROR,
|
throw Http2Exception.connectionError(Http2Error.INTERNAL_ERROR,
|
||||||
"content length exceeded maximum of %d for stream id %d", maxContentLength, streamId);
|
"content length exceeded maximum of %d for stream id %d", maxContentLength, streamId);
|
||||||
}
|
}
|
||||||
content.writeBytes(data, data.readerIndex(), dataReadableBytes);
|
content.writeBytes(data, data.readerIndex(), dataReadableBytes);
|
||||||
|
@ -349,7 +346,7 @@ public class Http2EventHandler extends Http2EventAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* The stream is out of scope for the HTTP message flow and will no longer be tracked
|
* The stream is out of scope for the HTTP message flow and will no longer be tracked.
|
||||||
* @param stream The stream to remove associated state with
|
* @param stream The stream to remove associated state with
|
||||||
* @param release {@code true} to call release on the value if it is present. {@code false} to not call release.
|
* @param release {@code true} to call release on the value if it is present. {@code false} to not call release.
|
||||||
*/
|
*/
|
||||||
|
@ -361,7 +358,7 @@ public class Http2EventHandler extends Http2EventAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set final headers and fire a channel read event
|
* Set final headers and fire a channel read event.
|
||||||
*
|
*
|
||||||
* @param ctx The context to fire the event on
|
* @param ctx The context to fire the event on
|
||||||
* @param msg The message to send
|
* @param msg The message to send
|
||||||
|
@ -390,8 +387,7 @@ public class Http2EventHandler extends Http2EventAdapter {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void endHeader(ChannelHandlerContext ctx, Http2Stream stream, FullHttpMessage msg,
|
private void endHeader(ChannelHandlerContext ctx, Http2Stream stream, FullHttpMessage msg, boolean endOfStream) {
|
||||||
boolean endOfStream) {
|
|
||||||
if (endOfStream) {
|
if (endOfStream) {
|
||||||
fireChannelRead(ctx, msg, getMessage(stream) != msg, stream);
|
fireChannelRead(ctx, msg, getMessage(stream) != msg, stream);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -35,12 +35,13 @@ import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.netty.handler.codec.http.HttpVersion;
|
import io.netty.handler.codec.http.HttpVersion;
|
||||||
import io.netty.handler.codec.http.cookie.ClientCookieEncoder;
|
import io.netty.handler.codec.http.cookie.ClientCookieEncoder;
|
||||||
import io.netty.handler.codec.http.cookie.Cookie;
|
import io.netty.handler.codec.http.cookie.Cookie;
|
||||||
|
import io.netty.handler.ssl.OpenSsl;
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import io.netty.util.concurrent.FutureListener;
|
import io.netty.util.concurrent.FutureListener;
|
||||||
import org.xbib.netty.http.client.listener.CookieListener;
|
import org.xbib.netty.http.client.listener.CookieListener;
|
||||||
import org.xbib.netty.http.client.listener.ExceptionListener;
|
import org.xbib.netty.http.client.listener.ExceptionListener;
|
||||||
import org.xbib.netty.http.client.listener.HttpPushListener;
|
|
||||||
import org.xbib.netty.http.client.listener.HttpHeadersListener;
|
import org.xbib.netty.http.client.listener.HttpHeadersListener;
|
||||||
|
import org.xbib.netty.http.client.listener.HttpPushListener;
|
||||||
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
||||||
import org.xbib.netty.http.client.util.InetAddressKey;
|
import org.xbib.netty.http.client.util.InetAddressKey;
|
||||||
import org.xbib.netty.http.client.util.NetworkUtils;
|
import org.xbib.netty.http.client.util.NetworkUtils;
|
||||||
|
@ -66,6 +67,8 @@ public final class HttpClient implements Closeable {
|
||||||
|
|
||||||
private static final AtomicInteger streamId = new AtomicInteger(3);
|
private static final AtomicInteger streamId = new AtomicInteger(3);
|
||||||
|
|
||||||
|
private static final HttpClient INSTANCE = HttpClient.builder().build();
|
||||||
|
|
||||||
private final ByteBufAllocator byteBufAllocator;
|
private final ByteBufAllocator byteBufAllocator;
|
||||||
|
|
||||||
private final EventLoopGroup eventLoopGroup;
|
private final EventLoopGroup eventLoopGroup;
|
||||||
|
@ -83,11 +86,16 @@ public final class HttpClient implements Closeable {
|
||||||
this.byteBufAllocator = byteBufAllocator;
|
this.byteBufAllocator = byteBufAllocator;
|
||||||
this.eventLoopGroup = eventLoopGroup;
|
this.eventLoopGroup = eventLoopGroup;
|
||||||
this.poolMap = new HttpClientChannelPoolMap(this, httpClientChannelContext, bootstrap, maxConnections);
|
this.poolMap = new HttpClientChannelPoolMap(this, httpClientChannelContext, bootstrap, maxConnections);
|
||||||
|
logger.log(Level.FINE, () -> "OpenSSL ALPN support: " + OpenSsl.isAlpnSupported());
|
||||||
NetworkUtils.extendSystemProperties();
|
NetworkUtils.extendSystemProperties();
|
||||||
logger.log(Level.FINE, () -> "local host name = " + NetworkUtils.getLocalHostName("localhost"));
|
logger.log(Level.FINE, () -> "local host name = " + NetworkUtils.getLocalHostName("localhost"));
|
||||||
logger.log(Level.FINE, NetworkUtils::displayNetworkInterfaces);
|
logger.log(Level.FINE, NetworkUtils::displayNetworkInterfaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static HttpClient getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a builder to configure connecting.
|
* Create a builder to configure connecting.
|
||||||
*
|
*
|
||||||
|
@ -106,73 +114,105 @@ public final class HttpClient implements Closeable {
|
||||||
*
|
*
|
||||||
* @return a request builder
|
* @return a request builder
|
||||||
*/
|
*/
|
||||||
public HttpClientRequestBuilder prepareGet() {
|
public HttpRequestBuilder prepareGet() {
|
||||||
return prepareRequest(HttpMethod.GET);
|
return prepareRequest(HttpMethod.GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpRequestBuilder prepareGet(String url) {
|
||||||
|
return prepareRequest(HttpMethod.GET).setURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a HTTP HEAD request.
|
* Prepare a HTTP HEAD request.
|
||||||
*
|
*
|
||||||
* @return a request builder
|
* @return a request builder
|
||||||
*/
|
*/
|
||||||
public HttpClientRequestBuilder prepareHead() {
|
public HttpRequestBuilder prepareHead() {
|
||||||
return prepareRequest(HttpMethod.HEAD);
|
return prepareRequest(HttpMethod.HEAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpRequestBuilder prepareHead(String url) {
|
||||||
|
return prepareRequest(HttpMethod.HEAD).setURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a HTTP PUT request.
|
* Prepare a HTTP PUT request.
|
||||||
*
|
*
|
||||||
* @return a request builder
|
* @return a request builder
|
||||||
*/
|
*/
|
||||||
public HttpClientRequestBuilder preparePut() {
|
public HttpRequestBuilder preparePut() {
|
||||||
return prepareRequest(HttpMethod.PUT);
|
return prepareRequest(HttpMethod.PUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpRequestBuilder preparePut(String url) {
|
||||||
|
return prepareRequest(HttpMethod.PUT).setURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a HTTP POST request.
|
* Prepare a HTTP POST request.
|
||||||
*
|
*
|
||||||
* @return a request builder
|
* @return a request builder
|
||||||
*/
|
*/
|
||||||
public HttpClientRequestBuilder preparePost() {
|
public HttpRequestBuilder preparePost() {
|
||||||
return prepareRequest(HttpMethod.POST);
|
return prepareRequest(HttpMethod.POST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpRequestBuilder preparePost(String url) {
|
||||||
|
return prepareRequest(HttpMethod.POST).setURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a HTTP DELETE request.
|
* Prepare a HTTP DELETE request.
|
||||||
*
|
*
|
||||||
* @return a request builder
|
* @return a request builder
|
||||||
*/
|
*/
|
||||||
public HttpClientRequestBuilder prepareDelete() {
|
public HttpRequestBuilder prepareDelete() {
|
||||||
return prepareRequest(HttpMethod.DELETE);
|
return prepareRequest(HttpMethod.DELETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpRequestBuilder prepareDelete(String url) {
|
||||||
|
return prepareRequest(HttpMethod.DELETE).setURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a HTTP OPTIONS request.
|
* Prepare a HTTP OPTIONS request.
|
||||||
*
|
*
|
||||||
* @return a request builder
|
* @return a request builder
|
||||||
*/
|
*/
|
||||||
public HttpClientRequestBuilder prepareOptions() {
|
public HttpRequestBuilder prepareOptions() {
|
||||||
return prepareRequest(HttpMethod.OPTIONS);
|
return prepareRequest(HttpMethod.OPTIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpRequestBuilder prepareOptions(String url) {
|
||||||
|
return prepareRequest(HttpMethod.OPTIONS).setURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a HTTP PATCH request.
|
* Prepare a HTTP PATCH request.
|
||||||
*
|
*
|
||||||
* @return a request builder
|
* @return a request builder
|
||||||
*/
|
*/
|
||||||
public HttpClientRequestBuilder preparePatch() {
|
public HttpRequestBuilder preparePatch() {
|
||||||
return prepareRequest(HttpMethod.PATCH);
|
return prepareRequest(HttpMethod.PATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpRequestBuilder preparePatch(String url) {
|
||||||
|
return prepareRequest(HttpMethod.PATCH).setURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a HTTP TRACE request.
|
* Prepare a HTTP TRACE request.
|
||||||
*
|
*
|
||||||
* @return a request builder
|
* @return a request builder
|
||||||
*/
|
*/
|
||||||
public HttpClientRequestBuilder prepareTrace() {
|
public HttpRequestBuilder prepareTrace() {
|
||||||
return prepareRequest(HttpMethod.TRACE);
|
return prepareRequest(HttpMethod.TRACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpRequestBuilder prepareTrace(String url) {
|
||||||
|
return prepareRequest(HttpMethod.TRACE).setURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
public HttpClientChannelPoolMap poolMap() {
|
public HttpClientChannelPoolMap poolMap() {
|
||||||
return poolMap;
|
return poolMap;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +298,8 @@ public final class HttpClient implements Closeable {
|
||||||
} else if (httpRequest.protocolVersion().majorVersion() == 2) {
|
} else if (httpRequest.protocolVersion().majorVersion() == 2) {
|
||||||
logger.log(Level.FINE, () -> "waiting for HTTP/2 settings");
|
logger.log(Level.FINE, () -> "waiting for HTTP/2 settings");
|
||||||
settingsPromise.await(httpRequestContext.getTimeout(), TimeUnit.MILLISECONDS);
|
settingsPromise.await(httpRequestContext.getTimeout(), TimeUnit.MILLISECONDS);
|
||||||
logger.log(Level.FINE, () -> "waiting for HTTP/2 responses = " + httpRequestContext.getStreamIdPromiseMap().size());
|
logger.log(Level.FINE, () -> "waiting for HTTP/2 responses = " +
|
||||||
|
httpRequestContext.getStreamIdPromiseMap().size());
|
||||||
int timeout = httpRequestContext.getTimeout();
|
int timeout = httpRequestContext.getTimeout();
|
||||||
for (Map.Entry<Integer, Map.Entry<ChannelFuture, ChannelPromise>> entry :
|
for (Map.Entry<Integer, Map.Entry<ChannelFuture, ChannelPromise>> entry :
|
||||||
httpRequestContext.getStreamIdPromiseMap().entrySet()) {
|
httpRequestContext.getStreamIdPromiseMap().entrySet()) {
|
||||||
|
@ -267,12 +308,13 @@ public final class HttpClient implements Closeable {
|
||||||
logger.log(Level.FINE, "waiting for channel, stream ID = " + entry.getKey());
|
logger.log(Level.FINE, "waiting for channel, stream ID = " + entry.getKey());
|
||||||
if (!channelFuture.awaitUninterruptibly(timeout, TimeUnit.MILLISECONDS)) {
|
if (!channelFuture.awaitUninterruptibly(timeout, TimeUnit.MILLISECONDS)) {
|
||||||
IllegalStateException illegalStateException =
|
IllegalStateException illegalStateException =
|
||||||
new IllegalStateException("time out while waiting to write for stream id " + entry.getKey());
|
new IllegalStateException("time out while waiting to write for stream id " +
|
||||||
|
entry.getKey());
|
||||||
if (exceptionListener != null) {
|
if (exceptionListener != null) {
|
||||||
exceptionListener.onException(illegalStateException);
|
exceptionListener.onException(illegalStateException);
|
||||||
httpRequestContext.fail(illegalStateException.getMessage());
|
httpRequestContext.fail(illegalStateException.getMessage());
|
||||||
final ChannelPool channelPool =
|
final ChannelPool channelPool = channelFuture.channel()
|
||||||
channelFuture.channel().attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
.attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
||||||
channelPool.release(channelFuture.channel());
|
channelPool.release(channelFuture.channel());
|
||||||
}
|
}
|
||||||
throw illegalStateException;
|
throw illegalStateException;
|
||||||
|
@ -285,13 +327,14 @@ public final class HttpClient implements Closeable {
|
||||||
logger.log(Level.FINE, "waiting for promise of stream ID = " + entry.getKey());
|
logger.log(Level.FINE, "waiting for promise of stream ID = " + entry.getKey());
|
||||||
if (!promise.awaitUninterruptibly(timeout, TimeUnit.MILLISECONDS)) {
|
if (!promise.awaitUninterruptibly(timeout, TimeUnit.MILLISECONDS)) {
|
||||||
IllegalStateException illegalStateException =
|
IllegalStateException illegalStateException =
|
||||||
new IllegalStateException("time out while waiting for response on stream id " + entry.getKey());
|
new IllegalStateException("time out while waiting for response on stream id " +
|
||||||
|
entry.getKey());
|
||||||
if (exceptionListener != null) {
|
if (exceptionListener != null) {
|
||||||
exceptionListener.onException(illegalStateException);
|
exceptionListener.onException(illegalStateException);
|
||||||
httpRequestContext.fail(illegalStateException.getMessage());
|
httpRequestContext.fail(illegalStateException.getMessage());
|
||||||
if (channelFuture != null) {
|
if (channelFuture != null) {
|
||||||
final ChannelPool channelPool =
|
final ChannelPool channelPool = channelFuture.channel()
|
||||||
channelFuture.channel().attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
.attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
||||||
channelPool.release(channelFuture.channel());
|
channelPool.release(channelFuture.channel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,8 +346,8 @@ public final class HttpClient implements Closeable {
|
||||||
exceptionListener.onException(runtimeException);
|
exceptionListener.onException(runtimeException);
|
||||||
httpRequestContext.fail(runtimeException.getMessage());
|
httpRequestContext.fail(runtimeException.getMessage());
|
||||||
if (channelFuture != null) {
|
if (channelFuture != null) {
|
||||||
final ChannelPool channelPool =
|
final ChannelPool channelPool = channelFuture.channel()
|
||||||
channelFuture.channel().attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
.attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
||||||
channelPool.release(channelFuture.channel());
|
channelPool.release(channelFuture.channel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,9 @@ import io.netty.handler.ssl.CipherSuiteFilter;
|
||||||
import io.netty.handler.ssl.SslProvider;
|
import io.netty.handler.ssl.SslProvider;
|
||||||
import org.xbib.netty.http.client.util.ClientAuthMode;
|
import org.xbib.netty.http.client.util.ClientAuthMode;
|
||||||
|
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
|
@ -24,13 +24,13 @@ import io.netty.handler.ssl.SslProvider;
|
||||||
import io.netty.util.AttributeKey;
|
import io.netty.util.AttributeKey;
|
||||||
import org.xbib.netty.http.client.listener.CookieListener;
|
import org.xbib.netty.http.client.listener.CookieListener;
|
||||||
import org.xbib.netty.http.client.listener.ExceptionListener;
|
import org.xbib.netty.http.client.listener.ExceptionListener;
|
||||||
import org.xbib.netty.http.client.listener.HttpPushListener;
|
|
||||||
import org.xbib.netty.http.client.listener.HttpHeadersListener;
|
import org.xbib.netty.http.client.listener.HttpHeadersListener;
|
||||||
|
import org.xbib.netty.http.client.listener.HttpPushListener;
|
||||||
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
||||||
import org.xbib.netty.http.client.util.ClientAuthMode;
|
import org.xbib.netty.http.client.util.ClientAuthMode;
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -21,8 +21,8 @@ import io.netty.handler.ssl.OpenSsl;
|
||||||
import io.netty.handler.ssl.SslProvider;
|
import io.netty.handler.ssl.SslProvider;
|
||||||
import io.netty.handler.ssl.SupportedCipherSuiteFilter;
|
import io.netty.handler.ssl.SupportedCipherSuiteFilter;
|
||||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||||
import org.xbib.netty.http.client.util.InetAddressKey;
|
|
||||||
import org.xbib.netty.http.client.util.ClientAuthMode;
|
import org.xbib.netty.http.client.util.ClientAuthMode;
|
||||||
|
import org.xbib.netty.http.client.util.InetAddressKey;
|
||||||
|
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
|
||||||
|
|
|
@ -50,15 +50,15 @@ import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||||
import org.xbib.netty.http.client.listener.ExceptionListener;
|
import org.xbib.netty.http.client.listener.ExceptionListener;
|
||||||
import org.xbib.netty.http.client.util.InetAddressKey;
|
import org.xbib.netty.http.client.util.InetAddressKey;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import javax.net.ssl.SNIHostName;
|
import javax.net.ssl.SNIHostName;
|
||||||
import javax.net.ssl.SNIServerName;
|
import javax.net.ssl.SNIServerName;
|
||||||
import javax.net.ssl.SSLEngine;
|
import javax.net.ssl.SSLEngine;
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
import javax.net.ssl.SSLParameters;
|
import javax.net.ssl.SSLParameters;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Netty HTTP client channel initializer.
|
* Netty HTTP client channel initializer.
|
||||||
|
@ -259,7 +259,7 @@ class HttpClientChannelInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Sharable
|
@Sharable
|
||||||
private class UpgradeRequestHandler extends ChannelInboundHandlerAdapter {
|
private static class UpgradeRequestHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send an upgrade request if channel becomes active.
|
* Send an upgrade request if channel becomes active.
|
||||||
|
@ -299,7 +299,7 @@ class HttpClientChannelInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
* A Netty handler that logs user events and find expetced ones.
|
* A Netty handler that logs user events and find expetced ones.
|
||||||
*/
|
*/
|
||||||
@Sharable
|
@Sharable
|
||||||
private class UserEventLogger extends ChannelInboundHandlerAdapter {
|
private static class UserEventLogger extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||||
|
@ -319,7 +319,7 @@ class HttpClientChannelInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
* A Netty handler that logs the I/O traffic of a connection.
|
* A Netty handler that logs the I/O traffic of a connection.
|
||||||
*/
|
*/
|
||||||
@Sharable
|
@Sharable
|
||||||
private final class TrafficLoggingHandler extends LoggingHandler {
|
private static class TrafficLoggingHandler extends LoggingHandler {
|
||||||
|
|
||||||
TrafficLoggingHandler() {
|
TrafficLoggingHandler() {
|
||||||
super("client", LogLevel.TRACE);
|
super("client", LogLevel.TRACE);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.xbib.netty.http.client;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufAllocator;
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||||
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
||||||
import io.netty.handler.codec.http.DefaultHttpRequest;
|
import io.netty.handler.codec.http.DefaultHttpRequest;
|
||||||
|
@ -19,8 +20,8 @@ import io.netty.util.AsciiString;
|
||||||
import io.netty.util.CharsetUtil;
|
import io.netty.util.CharsetUtil;
|
||||||
import org.xbib.netty.http.client.listener.CookieListener;
|
import org.xbib.netty.http.client.listener.CookieListener;
|
||||||
import org.xbib.netty.http.client.listener.ExceptionListener;
|
import org.xbib.netty.http.client.listener.ExceptionListener;
|
||||||
import org.xbib.netty.http.client.listener.HttpPushListener;
|
|
||||||
import org.xbib.netty.http.client.listener.HttpHeadersListener;
|
import org.xbib.netty.http.client.listener.HttpHeadersListener;
|
||||||
|
import org.xbib.netty.http.client.listener.HttpPushListener;
|
||||||
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -50,6 +51,8 @@ public class HttpClientRequestBuilder implements HttpRequestBuilder, HttpRequest
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(HttpClientRequestBuilder.class.getName());
|
private static final Logger logger = Logger.getLogger(HttpClientRequestBuilder.class.getName());
|
||||||
|
|
||||||
|
private static final HttpVersion HTTP_2_0 = HttpVersion.valueOf("HTTP/2.0");
|
||||||
|
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
|
|
||||||
private final ByteBufAllocator byteBufAllocator;
|
private final ByteBufAllocator byteBufAllocator;
|
||||||
|
@ -96,6 +99,11 @@ public class HttpClientRequestBuilder implements HttpRequestBuilder, HttpRequest
|
||||||
|
|
||||||
private HttpPushListener httpPushListener;
|
private HttpPushListener httpPushListener;
|
||||||
|
|
||||||
|
HttpClientRequestBuilder(HttpMethod httpMethod,
|
||||||
|
ByteBufAllocator byteBufAllocator, int streamId) {
|
||||||
|
this(null, httpMethod, byteBufAllocator, streamId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct HTTP client request builder.
|
* Construct HTTP client request builder.
|
||||||
*
|
*
|
||||||
|
@ -114,6 +122,28 @@ public class HttpClientRequestBuilder implements HttpRequestBuilder, HttpRequest
|
||||||
this.cookies = new HashSet<>();
|
this.cookies = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static HttpRequestBuilder builder(HttpMethod httpMethod) {
|
||||||
|
return new HttpClientRequestBuilder(httpMethod, UnpooledByteBufAllocator.DEFAULT, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequestBuilder setHttp1() {
|
||||||
|
this.httpVersion = HttpVersion.HTTP_1_1;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequestBuilder setHttp2() {
|
||||||
|
this.httpVersion = HTTP_2_0;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequestBuilder setVersion(String httpVersion) {
|
||||||
|
this.httpVersion = HttpVersion.valueOf(httpVersion);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpRequestBuilder setTimeout(int timeout) {
|
public HttpRequestBuilder setTimeout(int timeout) {
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
|
@ -171,12 +201,6 @@ public class HttpClientRequestBuilder implements HttpRequestBuilder, HttpRequest
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpRequestBuilder setVersion(String httpVersion) {
|
|
||||||
this.httpVersion = HttpVersion.valueOf(httpVersion);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpRequestBuilder acceptGzip(boolean gzip) {
|
public HttpRequestBuilder acceptGzip(boolean gzip) {
|
||||||
this.gzip = gzip;
|
this.gzip = gzip;
|
||||||
|
@ -314,6 +338,14 @@ public class HttpClientRequestBuilder implements HttpRequestBuilder, HttpRequest
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpRequestContext execute() {
|
public HttpRequestContext execute() {
|
||||||
|
return execute(httpClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequestContext execute(HttpClient httpClient) {
|
||||||
|
if (httpClient == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (httpRequest == null) {
|
if (httpRequest == null) {
|
||||||
httpRequest = build();
|
httpRequest = build();
|
||||||
}
|
}
|
||||||
|
@ -378,8 +410,7 @@ public class HttpClientRequestBuilder implements HttpRequestBuilder, HttpRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
private void content(byte[] buf, AsciiString contentType) throws IOException {
|
private void content(byte[] buf, AsciiString contentType) throws IOException {
|
||||||
ByteBuf buffer = byteBufAllocator.buffer(buf.length).writeBytes(buf);
|
content(byteBufAllocator.buffer(buf.length).writeBytes(buf), contentType);
|
||||||
content(buffer, contentType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void content(ByteBuf body, AsciiString contentType) throws IOException {
|
private void content(ByteBuf body, AsciiString contentType) throws IOException {
|
||||||
|
|
|
@ -21,8 +21,8 @@ import io.netty.handler.codec.http.HttpRequest;
|
||||||
import io.netty.handler.codec.http.cookie.Cookie;
|
import io.netty.handler.codec.http.cookie.Cookie;
|
||||||
import org.xbib.netty.http.client.listener.CookieListener;
|
import org.xbib.netty.http.client.listener.CookieListener;
|
||||||
import org.xbib.netty.http.client.listener.ExceptionListener;
|
import org.xbib.netty.http.client.listener.ExceptionListener;
|
||||||
import org.xbib.netty.http.client.listener.HttpPushListener;
|
|
||||||
import org.xbib.netty.http.client.listener.HttpHeadersListener;
|
import org.xbib.netty.http.client.listener.HttpHeadersListener;
|
||||||
|
import org.xbib.netty.http.client.listener.HttpPushListener;
|
||||||
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -33,7 +33,9 @@ import java.util.function.Function;
|
||||||
*/
|
*/
|
||||||
public interface HttpRequestBuilder {
|
public interface HttpRequestBuilder {
|
||||||
|
|
||||||
HttpRequestBuilder setTimeout(int timeout);
|
HttpRequestBuilder setHttp1();
|
||||||
|
|
||||||
|
HttpRequestBuilder setHttp2();
|
||||||
|
|
||||||
HttpRequestBuilder setVersion(String httpVersion);
|
HttpRequestBuilder setVersion(String httpVersion);
|
||||||
|
|
||||||
|
@ -81,9 +83,13 @@ public interface HttpRequestBuilder {
|
||||||
|
|
||||||
HttpRequestBuilder onPushReceived(HttpPushListener httpPushListener);
|
HttpRequestBuilder onPushReceived(HttpPushListener httpPushListener);
|
||||||
|
|
||||||
|
HttpRequestBuilder setTimeout(int timeout);
|
||||||
|
|
||||||
HttpRequest build();
|
HttpRequest build();
|
||||||
|
|
||||||
HttpRequestContext execute();
|
HttpRequestContext execute();
|
||||||
|
|
||||||
|
HttpRequestContext execute(HttpClient httpClient);
|
||||||
|
|
||||||
<T> CompletableFuture<T> execute(Function<FullHttpResponse, T> supplier);
|
<T> CompletableFuture<T> execute(Function<FullHttpResponse, T> supplier);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,8 @@ import io.netty.handler.codec.http2.Http2Headers;
|
||||||
import io.netty.util.internal.PlatformDependent;
|
import io.netty.util.internal.PlatformDependent;
|
||||||
import org.xbib.netty.http.client.listener.CookieListener;
|
import org.xbib.netty.http.client.listener.CookieListener;
|
||||||
import org.xbib.netty.http.client.listener.ExceptionListener;
|
import org.xbib.netty.http.client.listener.ExceptionListener;
|
||||||
import org.xbib.netty.http.client.listener.HttpPushListener;
|
|
||||||
import org.xbib.netty.http.client.listener.HttpHeadersListener;
|
import org.xbib.netty.http.client.listener.HttpHeadersListener;
|
||||||
|
import org.xbib.netty.http.client.listener.HttpPushListener;
|
||||||
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
||||||
import org.xbib.netty.http.client.util.LimitedHashSet;
|
import org.xbib.netty.http.client.util.LimitedHashSet;
|
||||||
|
|
||||||
|
@ -91,6 +91,8 @@ public final class HttpRequestContext implements HttpResponseListener, HttpReque
|
||||||
|
|
||||||
private Map<Integer, FullHttpResponse> httpResponses;
|
private Map<Integer, FullHttpResponse> httpResponses;
|
||||||
|
|
||||||
|
private boolean hastimeout;
|
||||||
|
|
||||||
private Long stopTime;
|
private Long stopTime;
|
||||||
|
|
||||||
HttpRequestContext(URI uri, HttpRequest httpRequest, AtomicInteger streamId,
|
HttpRequestContext(URI uri, HttpRequest httpRequest, AtomicInteger streamId,
|
||||||
|
@ -233,11 +235,7 @@ public final class HttpRequestContext implements HttpResponseListener, HttpReque
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean secure = "https".equals(uri.getScheme());
|
boolean secure = "https".equals(uri.getScheme());
|
||||||
boolean secureMatch = (secure && cookie.isSecure()) || (!secure && !cookie.isSecure());
|
return (secure && cookie.isSecure()) || (!secure && !cookie.isSecure());
|
||||||
if (!secureMatch) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTimeout() {
|
public int getTimeout() {
|
||||||
|
@ -293,11 +291,15 @@ public final class HttpRequestContext implements HttpResponseListener, HttpReque
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpRequestContext waitFor(long value, TimeUnit timeUnit) throws InterruptedException {
|
public HttpRequestContext waitFor(long value, TimeUnit timeUnit) throws InterruptedException {
|
||||||
latch.await(value, timeUnit);
|
this.hastimeout = latch.await(value, timeUnit);
|
||||||
stopTime = System.currentTimeMillis();
|
stopTime = System.currentTimeMillis();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTimeout() {
|
||||||
|
return hastimeout;
|
||||||
|
}
|
||||||
|
|
||||||
public void success(String reason) {
|
public void success(String reason) {
|
||||||
logger.log(Level.FINE, () -> "success because of " + reason);
|
logger.log(Level.FINE, () -> "success because of " + reason);
|
||||||
if (succeeded.compareAndSet(false, true)) {
|
if (succeeded.compareAndSet(false, true)) {
|
||||||
|
|
|
@ -21,8 +21,6 @@ import io.netty.handler.codec.http.HttpVersion;
|
||||||
*/
|
*/
|
||||||
public interface HttpRequestDefaults {
|
public interface HttpRequestDefaults {
|
||||||
|
|
||||||
int DEFAULT_TIMEOUT_MILLIS = 5000;
|
|
||||||
|
|
||||||
HttpVersion DEFAULT_HTTP_VERSION = HttpVersion.HTTP_1_1;
|
HttpVersion DEFAULT_HTTP_VERSION = HttpVersion.HTTP_1_1;
|
||||||
|
|
||||||
String DEFAULT_USER_AGENT = HttpClientUserAgent.getUserAgent();
|
String DEFAULT_USER_AGENT = HttpClientUserAgent.getUserAgent();
|
||||||
|
@ -31,5 +29,7 @@ public interface HttpRequestDefaults {
|
||||||
|
|
||||||
boolean DEFAULT_FOLLOW_REDIRECT = true;
|
boolean DEFAULT_FOLLOW_REDIRECT = true;
|
||||||
|
|
||||||
|
int DEFAULT_TIMEOUT_MILLIS = 5000;
|
||||||
|
|
||||||
int DEFAULT_MAX_REDIRECT = 10;
|
int DEFAULT_MAX_REDIRECT = 10;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import io.netty.handler.codec.http.FullHttpResponse;
|
||||||
import io.netty.handler.codec.http2.Http2Headers;
|
import io.netty.handler.codec.http2.Http2Headers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This listener can forward HTTP push
|
* This listener can forward HTTP push.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class InetAddressKey {
|
||||||
host.equals(((InetAddressKey) object).host) &&
|
host.equals(((InetAddressKey) object).host) &&
|
||||||
port == ((InetAddressKey) object).port &&
|
port == ((InetAddressKey) object).port &&
|
||||||
version.equals(((InetAddressKey) object).version) &&
|
version.equals(((InetAddressKey) object).version) &&
|
||||||
secure == ((InetAddressKey) object).secure;
|
secure.equals(((InetAddressKey) object).secure);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.util.LinkedHashSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link java.util.Set} with limited size. If the size is exceeded, an exception is thrown.
|
* A {@link java.util.Set} with limited size. If the size is exceeded, an exception is thrown.
|
||||||
|
* @param <E> the element type
|
||||||
*/
|
*/
|
||||||
public final class LimitedHashSet<E> extends LinkedHashSet<E> {
|
public final class LimitedHashSet<E> extends LinkedHashSet<E> {
|
||||||
|
|
||||||
|
|
|
@ -206,11 +206,14 @@ public class NetworkUtils {
|
||||||
public static boolean matchesNetwork(NetworkClass given, NetworkClass expected) {
|
public static boolean matchesNetwork(NetworkClass given, NetworkClass expected) {
|
||||||
switch (expected) {
|
switch (expected) {
|
||||||
case ANY:
|
case ANY:
|
||||||
return EnumSet.of(NetworkClass.LOOPBACK, NetworkClass.LOCAL, NetworkClass.PUBLIC, NetworkClass.ANY).contains(given);
|
return EnumSet.of(NetworkClass.LOOPBACK, NetworkClass.LOCAL, NetworkClass.PUBLIC, NetworkClass.ANY)
|
||||||
|
.contains(given);
|
||||||
case PUBLIC:
|
case PUBLIC:
|
||||||
return EnumSet.of(NetworkClass.LOOPBACK, NetworkClass.LOCAL, NetworkClass.PUBLIC).contains(given);
|
return EnumSet.of(NetworkClass.LOOPBACK, NetworkClass.LOCAL, NetworkClass.PUBLIC)
|
||||||
|
.contains(given);
|
||||||
case LOCAL:
|
case LOCAL:
|
||||||
return EnumSet.of(NetworkClass.LOOPBACK, NetworkClass.LOCAL).contains(given);
|
return EnumSet.of(NetworkClass.LOOPBACK, NetworkClass.LOCAL)
|
||||||
|
.contains(given);
|
||||||
case LOOPBACK:
|
case LOOPBACK:
|
||||||
return NetworkClass.LOOPBACK == given;
|
return NetworkClass.LOOPBACK == given;
|
||||||
}
|
}
|
||||||
|
@ -509,8 +512,12 @@ public class NetworkUtils {
|
||||||
.append(" prefixlen:").append(interfaceAddress.getNetworkPrefixLength());
|
.append(" prefixlen:").append(interfaceAddress.getNetworkPrefixLength());
|
||||||
} else {
|
} else {
|
||||||
int netmask = 0xFFFFFFFF << (32 - interfaceAddress.getNetworkPrefixLength());
|
int netmask = 0xFFFFFFFF << (32 - interfaceAddress.getNetworkPrefixLength());
|
||||||
byte[] b = new byte[] { (byte)(netmask >>> 24), (byte)(netmask >>> 16 & 0xFF),
|
byte[] b = new byte[] {
|
||||||
(byte)(netmask >>> 8 & 0xFF), (byte)(netmask & 0xFF) };
|
(byte) (netmask >>> 24),
|
||||||
|
(byte) (netmask >>> 16 & 0xFF),
|
||||||
|
(byte) (netmask >>> 8 & 0xFF),
|
||||||
|
(byte) (netmask & 0xFF)
|
||||||
|
};
|
||||||
sb.append("inet ").append(format(address));
|
sb.append("inet ").append(format(address));
|
||||||
try {
|
try {
|
||||||
sb.append(" netmask:").append(format(InetAddress.getByAddress(b)));
|
sb.append(" netmask:").append(format(InetAddress.getByAddress(b)));
|
||||||
|
|
|
@ -34,39 +34,21 @@ public class AkamaiTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAkamaiHttps() throws Exception {
|
public void testAkamaiHttps() throws Exception {
|
||||||
|
HttpClient httpClient = HttpClient.getInstance();
|
||||||
// here we see server PUSH_PROMISE as response to headers, a go-away frame is written.
|
httpClient.prepareGet("https://http2.akamai.com/demo/h2_demo_frame.html")
|
||||||
|
.setHttp2()
|
||||||
/*
|
|
||||||
----------------INBOUND--------------------
|
|
||||||
[id: 0x27d23874, L:/192.168.178.23:52376 - R:http2.akamai.com/104.94.191.203:443]
|
|
||||||
PUSH_PROMISE: streamId=3, promisedStreamId=2, headers=DefaultHttp2Headers[:method: GET,
|
|
||||||
:path: /resources/push.css, :authority: http2.akamai.com, :scheme: https, host: http2.akamai.com,
|
|
||||||
user-agent: XbibHttpClient/unknown (Java/Azul Systems, Inc./1.8.0_112) (Netty/4.1.9.Final),
|
|
||||||
accept-encoding: gzip], padding=0
|
|
||||||
------------------------------------
|
|
||||||
2017-05-01 18:53:46.076 AM FEINSTEN [org.xbib.netty.http.client.HttpClientChannelInitializer]
|
|
||||||
io.netty.handler.codec.http2.Http2FrameLogger log
|
|
||||||
----------------OUTBOUND--------------------
|
|
||||||
[id: 0x27d23874, L:/192.168.178.23:52376 - R:http2.akamai.com/104.94.191.203:443]
|
|
||||||
GO_AWAY: lastStreamId=2, errorCode=1, length=75, bytes=556e7265636f676e697a656420485454...
|
|
||||||
*/
|
|
||||||
|
|
||||||
HttpClient httpClient = HttpClient.builder()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
httpClient.prepareGet()
|
|
||||||
.setVersion("HTTP/2.0")
|
|
||||||
.setURL("https://http2.akamai.com/demo/h2_demo_frame.html")
|
|
||||||
.onException(e -> logger.log(Level.SEVERE, e.getMessage(), e))
|
.onException(e -> logger.log(Level.SEVERE, e.getMessage(), e))
|
||||||
.onResponse(fullHttpResponse -> {
|
.onResponse(fullHttpResponse -> {
|
||||||
String response = fullHttpResponse.content().toString(StandardCharsets.UTF_8);
|
String response = fullHttpResponse.content().toString(StandardCharsets.UTF_8);
|
||||||
logger.log(Level.INFO, "status = " + fullHttpResponse.status() + " response body = " + response);
|
logger.log(Level.INFO, "status = " + fullHttpResponse.status()
|
||||||
|
+ " response body = " + response);
|
||||||
})
|
})
|
||||||
.onPushReceived((headers, fullHttpResponse) -> {
|
.onPushReceived((requestHeaders, fullHttpResponse) -> {
|
||||||
logger.log(Level.INFO, "received push promise: request headers = " + headers
|
String response = fullHttpResponse.content().toString(StandardCharsets.UTF_8);
|
||||||
|
logger.log(Level.INFO, "received push promise: request headers = " + requestHeaders
|
||||||
+ " status = " + fullHttpResponse.status()
|
+ " status = " + fullHttpResponse.status()
|
||||||
+ " response headers = " + fullHttpResponse.headers().entries()
|
+ " response headers = " + fullHttpResponse.headers().entries()
|
||||||
|
+ " response body = " + response
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.execute()
|
.execute()
|
||||||
|
|
Loading…
Reference in a new issue