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. -->
|
||||
|
||||
<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. -->
|
||||
<property name="option" value="under"/>
|
||||
<property name="tokens" value="STATIC_IMPORT, IMPORT"/>
|
||||
<property name="tokens" value="IMPORT, STATIC_IMPORT"/>
|
||||
</module>
|
||||
|
||||
<!--
|
||||
|
|
|
@ -41,10 +41,6 @@ import io.netty.handler.codec.http2.HttpConversionUtil;
|
|||
import java.util.logging.Level;
|
||||
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.
|
||||
* 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.
|
||||
* 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 settings the settings received from the remote endpoint.
|
||||
|
@ -214,12 +210,13 @@ public class Http2EventHandler extends Http2EventAdapter {
|
|||
Http2Stream stream = connection.stream(streamId);
|
||||
FullHttpMessage msg = getMessage(stream);
|
||||
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();
|
||||
final int dataReadableBytes = data.readableBytes();
|
||||
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.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 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 msg The message to send
|
||||
|
@ -390,8 +387,7 @@ public class Http2EventHandler extends Http2EventAdapter {
|
|||
return msg;
|
||||
}
|
||||
|
||||
private void endHeader(ChannelHandlerContext ctx, Http2Stream stream, FullHttpMessage msg,
|
||||
boolean endOfStream) {
|
||||
private void endHeader(ChannelHandlerContext ctx, Http2Stream stream, FullHttpMessage msg, boolean endOfStream) {
|
||||
if (endOfStream) {
|
||||
fireChannelRead(ctx, msg, getMessage(stream) != msg, stream);
|
||||
} 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.cookie.ClientCookieEncoder;
|
||||
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.FutureListener;
|
||||
import org.xbib.netty.http.client.listener.CookieListener;
|
||||
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.HttpPushListener;
|
||||
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
||||
import org.xbib.netty.http.client.util.InetAddressKey;
|
||||
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 HttpClient INSTANCE = HttpClient.builder().build();
|
||||
|
||||
private final ByteBufAllocator byteBufAllocator;
|
||||
|
||||
private final EventLoopGroup eventLoopGroup;
|
||||
|
@ -83,11 +86,16 @@ public final class HttpClient implements Closeable {
|
|||
this.byteBufAllocator = byteBufAllocator;
|
||||
this.eventLoopGroup = eventLoopGroup;
|
||||
this.poolMap = new HttpClientChannelPoolMap(this, httpClientChannelContext, bootstrap, maxConnections);
|
||||
logger.log(Level.FINE, () -> "OpenSSL ALPN support: " + OpenSsl.isAlpnSupported());
|
||||
NetworkUtils.extendSystemProperties();
|
||||
logger.log(Level.FINE, () -> "local host name = " + NetworkUtils.getLocalHostName("localhost"));
|
||||
logger.log(Level.FINE, NetworkUtils::displayNetworkInterfaces);
|
||||
}
|
||||
|
||||
public static HttpClient getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder to configure connecting.
|
||||
*
|
||||
|
@ -106,73 +114,105 @@ public final class HttpClient implements Closeable {
|
|||
*
|
||||
* @return a request builder
|
||||
*/
|
||||
public HttpClientRequestBuilder prepareGet() {
|
||||
public HttpRequestBuilder prepareGet() {
|
||||
return prepareRequest(HttpMethod.GET);
|
||||
}
|
||||
|
||||
public HttpRequestBuilder prepareGet(String url) {
|
||||
return prepareRequest(HttpMethod.GET).setURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a HTTP HEAD request.
|
||||
*
|
||||
* @return a request builder
|
||||
*/
|
||||
public HttpClientRequestBuilder prepareHead() {
|
||||
public HttpRequestBuilder prepareHead() {
|
||||
return prepareRequest(HttpMethod.HEAD);
|
||||
}
|
||||
|
||||
public HttpRequestBuilder prepareHead(String url) {
|
||||
return prepareRequest(HttpMethod.HEAD).setURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a HTTP PUT request.
|
||||
*
|
||||
* @return a request builder
|
||||
*/
|
||||
public HttpClientRequestBuilder preparePut() {
|
||||
public HttpRequestBuilder preparePut() {
|
||||
return prepareRequest(HttpMethod.PUT);
|
||||
}
|
||||
|
||||
public HttpRequestBuilder preparePut(String url) {
|
||||
return prepareRequest(HttpMethod.PUT).setURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a HTTP POST request.
|
||||
*
|
||||
* @return a request builder
|
||||
*/
|
||||
public HttpClientRequestBuilder preparePost() {
|
||||
public HttpRequestBuilder preparePost() {
|
||||
return prepareRequest(HttpMethod.POST);
|
||||
}
|
||||
|
||||
public HttpRequestBuilder preparePost(String url) {
|
||||
return prepareRequest(HttpMethod.POST).setURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a HTTP DELETE request.
|
||||
*
|
||||
* @return a request builder
|
||||
*/
|
||||
public HttpClientRequestBuilder prepareDelete() {
|
||||
public HttpRequestBuilder prepareDelete() {
|
||||
return prepareRequest(HttpMethod.DELETE);
|
||||
}
|
||||
|
||||
public HttpRequestBuilder prepareDelete(String url) {
|
||||
return prepareRequest(HttpMethod.DELETE).setURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a HTTP OPTIONS request.
|
||||
*
|
||||
* @return a request builder
|
||||
*/
|
||||
public HttpClientRequestBuilder prepareOptions() {
|
||||
public HttpRequestBuilder prepareOptions() {
|
||||
return prepareRequest(HttpMethod.OPTIONS);
|
||||
}
|
||||
|
||||
public HttpRequestBuilder prepareOptions(String url) {
|
||||
return prepareRequest(HttpMethod.OPTIONS).setURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a HTTP PATCH request.
|
||||
*
|
||||
* @return a request builder
|
||||
*/
|
||||
public HttpClientRequestBuilder preparePatch() {
|
||||
public HttpRequestBuilder preparePatch() {
|
||||
return prepareRequest(HttpMethod.PATCH);
|
||||
}
|
||||
|
||||
public HttpRequestBuilder preparePatch(String url) {
|
||||
return prepareRequest(HttpMethod.PATCH).setURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a HTTP TRACE request.
|
||||
*
|
||||
* @return a request builder
|
||||
*/
|
||||
public HttpClientRequestBuilder prepareTrace() {
|
||||
public HttpRequestBuilder prepareTrace() {
|
||||
return prepareRequest(HttpMethod.TRACE);
|
||||
}
|
||||
|
||||
public HttpRequestBuilder prepareTrace(String url) {
|
||||
return prepareRequest(HttpMethod.TRACE).setURL(url);
|
||||
}
|
||||
|
||||
public HttpClientChannelPoolMap poolMap() {
|
||||
return poolMap;
|
||||
}
|
||||
|
@ -258,7 +298,8 @@ public final class HttpClient implements Closeable {
|
|||
} else if (httpRequest.protocolVersion().majorVersion() == 2) {
|
||||
logger.log(Level.FINE, () -> "waiting for HTTP/2 settings");
|
||||
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();
|
||||
for (Map.Entry<Integer, Map.Entry<ChannelFuture, ChannelPromise>> entry :
|
||||
httpRequestContext.getStreamIdPromiseMap().entrySet()) {
|
||||
|
@ -267,12 +308,13 @@ public final class HttpClient implements Closeable {
|
|||
logger.log(Level.FINE, "waiting for channel, stream ID = " + entry.getKey());
|
||||
if (!channelFuture.awaitUninterruptibly(timeout, TimeUnit.MILLISECONDS)) {
|
||||
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) {
|
||||
exceptionListener.onException(illegalStateException);
|
||||
httpRequestContext.fail(illegalStateException.getMessage());
|
||||
final ChannelPool channelPool =
|
||||
channelFuture.channel().attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
||||
final ChannelPool channelPool = channelFuture.channel()
|
||||
.attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
||||
channelPool.release(channelFuture.channel());
|
||||
}
|
||||
throw illegalStateException;
|
||||
|
@ -285,13 +327,14 @@ public final class HttpClient implements Closeable {
|
|||
logger.log(Level.FINE, "waiting for promise of stream ID = " + entry.getKey());
|
||||
if (!promise.awaitUninterruptibly(timeout, TimeUnit.MILLISECONDS)) {
|
||||
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) {
|
||||
exceptionListener.onException(illegalStateException);
|
||||
httpRequestContext.fail(illegalStateException.getMessage());
|
||||
if (channelFuture != null) {
|
||||
final ChannelPool channelPool =
|
||||
channelFuture.channel().attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
||||
final ChannelPool channelPool = channelFuture.channel()
|
||||
.attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
||||
channelPool.release(channelFuture.channel());
|
||||
}
|
||||
}
|
||||
|
@ -303,8 +346,8 @@ public final class HttpClient implements Closeable {
|
|||
exceptionListener.onException(runtimeException);
|
||||
httpRequestContext.fail(runtimeException.getMessage());
|
||||
if (channelFuture != null) {
|
||||
final ChannelPool channelPool =
|
||||
channelFuture.channel().attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
||||
final ChannelPool channelPool = channelFuture.channel()
|
||||
.attr(HttpClientChannelContext.CHANNEL_POOL_ATTRIBUTE_KEY).get();
|
||||
channelPool.release(channelFuture.channel());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,9 +30,9 @@ import io.netty.handler.ssl.CipherSuiteFilter;
|
|||
import io.netty.handler.ssl.SslProvider;
|
||||
import org.xbib.netty.http.client.util.ClientAuthMode;
|
||||
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.InputStream;
|
||||
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 org.xbib.netty.http.client.listener.CookieListener;
|
||||
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.HttpPushListener;
|
||||
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
||||
import org.xbib.netty.http.client.util.ClientAuthMode;
|
||||
|
||||
import java.io.InputStream;
|
||||
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.SupportedCipherSuiteFilter;
|
||||
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.InetAddressKey;
|
||||
|
||||
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.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.SNIServerName;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
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.
|
||||
|
@ -259,7 +259,7 @@ class HttpClientChannelInitializer extends ChannelInitializer<SocketChannel> {
|
|||
}
|
||||
|
||||
@Sharable
|
||||
private class UpgradeRequestHandler extends ChannelInboundHandlerAdapter {
|
||||
private static class UpgradeRequestHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@Sharable
|
||||
private class UserEventLogger extends ChannelInboundHandlerAdapter {
|
||||
private static class UserEventLogger extends ChannelInboundHandlerAdapter {
|
||||
|
||||
@Override
|
||||
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.
|
||||
*/
|
||||
@Sharable
|
||||
private final class TrafficLoggingHandler extends LoggingHandler {
|
||||
private static class TrafficLoggingHandler extends LoggingHandler {
|
||||
|
||||
TrafficLoggingHandler() {
|
||||
super("client", LogLevel.TRACE);
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.xbib.netty.http.client;
|
|||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
||||
import io.netty.handler.codec.http.DefaultHttpRequest;
|
||||
|
@ -19,8 +20,8 @@ import io.netty.util.AsciiString;
|
|||
import io.netty.util.CharsetUtil;
|
||||
import org.xbib.netty.http.client.listener.CookieListener;
|
||||
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.HttpPushListener;
|
||||
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
||||
|
||||
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 HttpVersion HTTP_2_0 = HttpVersion.valueOf("HTTP/2.0");
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
||||
private final ByteBufAllocator byteBufAllocator;
|
||||
|
@ -96,6 +99,11 @@ public class HttpClientRequestBuilder implements HttpRequestBuilder, HttpRequest
|
|||
|
||||
private HttpPushListener httpPushListener;
|
||||
|
||||
HttpClientRequestBuilder(HttpMethod httpMethod,
|
||||
ByteBufAllocator byteBufAllocator, int streamId) {
|
||||
this(null, httpMethod, byteBufAllocator, streamId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct HTTP client request builder.
|
||||
*
|
||||
|
@ -114,6 +122,28 @@ public class HttpClientRequestBuilder implements HttpRequestBuilder, HttpRequest
|
|||
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
|
||||
public HttpRequestBuilder setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
|
@ -171,12 +201,6 @@ public class HttpClientRequestBuilder implements HttpRequestBuilder, HttpRequest
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBuilder setVersion(String httpVersion) {
|
||||
this.httpVersion = HttpVersion.valueOf(httpVersion);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBuilder acceptGzip(boolean gzip) {
|
||||
this.gzip = gzip;
|
||||
|
@ -314,6 +338,14 @@ public class HttpClientRequestBuilder implements HttpRequestBuilder, HttpRequest
|
|||
|
||||
@Override
|
||||
public HttpRequestContext execute() {
|
||||
return execute(httpClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestContext execute(HttpClient httpClient) {
|
||||
if (httpClient == null) {
|
||||
return null;
|
||||
}
|
||||
if (httpRequest == null) {
|
||||
httpRequest = build();
|
||||
}
|
||||
|
@ -378,8 +410,7 @@ public class HttpClientRequestBuilder implements HttpRequestBuilder, HttpRequest
|
|||
}
|
||||
|
||||
private void content(byte[] buf, AsciiString contentType) throws IOException {
|
||||
ByteBuf buffer = byteBufAllocator.buffer(buf.length).writeBytes(buf);
|
||||
content(buffer, contentType);
|
||||
content(byteBufAllocator.buffer(buf.length).writeBytes(buf), contentType);
|
||||
}
|
||||
|
||||
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 org.xbib.netty.http.client.listener.CookieListener;
|
||||
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.HttpPushListener;
|
||||
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -33,7 +33,9 @@ import java.util.function.Function;
|
|||
*/
|
||||
public interface HttpRequestBuilder {
|
||||
|
||||
HttpRequestBuilder setTimeout(int timeout);
|
||||
HttpRequestBuilder setHttp1();
|
||||
|
||||
HttpRequestBuilder setHttp2();
|
||||
|
||||
HttpRequestBuilder setVersion(String httpVersion);
|
||||
|
||||
|
@ -81,9 +83,13 @@ public interface HttpRequestBuilder {
|
|||
|
||||
HttpRequestBuilder onPushReceived(HttpPushListener httpPushListener);
|
||||
|
||||
HttpRequestBuilder setTimeout(int timeout);
|
||||
|
||||
HttpRequest build();
|
||||
|
||||
HttpRequestContext execute();
|
||||
|
||||
HttpRequestContext execute(HttpClient httpClient);
|
||||
|
||||
<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 org.xbib.netty.http.client.listener.CookieListener;
|
||||
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.HttpPushListener;
|
||||
import org.xbib.netty.http.client.listener.HttpResponseListener;
|
||||
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 boolean hastimeout;
|
||||
|
||||
private Long stopTime;
|
||||
|
||||
HttpRequestContext(URI uri, HttpRequest httpRequest, AtomicInteger streamId,
|
||||
|
@ -233,11 +235,7 @@ public final class HttpRequestContext implements HttpResponseListener, HttpReque
|
|||
return false;
|
||||
}
|
||||
boolean secure = "https".equals(uri.getScheme());
|
||||
boolean secureMatch = (secure && cookie.isSecure()) || (!secure && !cookie.isSecure());
|
||||
if (!secureMatch) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return (secure && cookie.isSecure()) || (!secure && !cookie.isSecure());
|
||||
}
|
||||
|
||||
public int getTimeout() {
|
||||
|
@ -293,11 +291,15 @@ public final class HttpRequestContext implements HttpResponseListener, HttpReque
|
|||
}
|
||||
|
||||
public HttpRequestContext waitFor(long value, TimeUnit timeUnit) throws InterruptedException {
|
||||
latch.await(value, timeUnit);
|
||||
this.hastimeout = latch.await(value, timeUnit);
|
||||
stopTime = System.currentTimeMillis();
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isTimeout() {
|
||||
return hastimeout;
|
||||
}
|
||||
|
||||
public void success(String reason) {
|
||||
logger.log(Level.FINE, () -> "success because of " + reason);
|
||||
if (succeeded.compareAndSet(false, true)) {
|
||||
|
|
|
@ -21,8 +21,6 @@ import io.netty.handler.codec.http.HttpVersion;
|
|||
*/
|
||||
public interface HttpRequestDefaults {
|
||||
|
||||
int DEFAULT_TIMEOUT_MILLIS = 5000;
|
||||
|
||||
HttpVersion DEFAULT_HTTP_VERSION = HttpVersion.HTTP_1_1;
|
||||
|
||||
String DEFAULT_USER_AGENT = HttpClientUserAgent.getUserAgent();
|
||||
|
@ -31,5 +29,7 @@ public interface HttpRequestDefaults {
|
|||
|
||||
boolean DEFAULT_FOLLOW_REDIRECT = true;
|
||||
|
||||
int DEFAULT_TIMEOUT_MILLIS = 5000;
|
||||
|
||||
int DEFAULT_MAX_REDIRECT = 10;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import io.netty.handler.codec.http.FullHttpResponse;
|
|||
import io.netty.handler.codec.http2.Http2Headers;
|
||||
|
||||
/**
|
||||
* This listener can forward HTTP push
|
||||
* This listener can forward HTTP push.
|
||||
*
|
||||
*/
|
||||
@FunctionalInterface
|
||||
|
|
|
@ -66,7 +66,7 @@ public class InetAddressKey {
|
|||
host.equals(((InetAddressKey) object).host) &&
|
||||
port == ((InetAddressKey) object).port &&
|
||||
version.equals(((InetAddressKey) object).version) &&
|
||||
secure == ((InetAddressKey) object).secure;
|
||||
secure.equals(((InetAddressKey) object).secure);
|
||||
}
|
||||
|
||||
@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.
|
||||
* @param <E> the element type
|
||||
*/
|
||||
public final class LimitedHashSet<E> extends LinkedHashSet<E> {
|
||||
|
||||
|
|
|
@ -206,11 +206,14 @@ public class NetworkUtils {
|
|||
public static boolean matchesNetwork(NetworkClass given, NetworkClass expected) {
|
||||
switch (expected) {
|
||||
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:
|
||||
return EnumSet.of(NetworkClass.LOOPBACK, NetworkClass.LOCAL, NetworkClass.PUBLIC).contains(given);
|
||||
return EnumSet.of(NetworkClass.LOOPBACK, NetworkClass.LOCAL, NetworkClass.PUBLIC)
|
||||
.contains(given);
|
||||
case LOCAL:
|
||||
return EnumSet.of(NetworkClass.LOOPBACK, NetworkClass.LOCAL).contains(given);
|
||||
return EnumSet.of(NetworkClass.LOOPBACK, NetworkClass.LOCAL)
|
||||
.contains(given);
|
||||
case LOOPBACK:
|
||||
return NetworkClass.LOOPBACK == given;
|
||||
}
|
||||
|
@ -509,8 +512,12 @@ public class NetworkUtils {
|
|||
.append(" prefixlen:").append(interfaceAddress.getNetworkPrefixLength());
|
||||
} else {
|
||||
int netmask = 0xFFFFFFFF << (32 - interfaceAddress.getNetworkPrefixLength());
|
||||
byte[] b = new byte[] { (byte)(netmask >>> 24), (byte)(netmask >>> 16 & 0xFF),
|
||||
(byte)(netmask >>> 8 & 0xFF), (byte)(netmask & 0xFF) };
|
||||
byte[] b = new byte[] {
|
||||
(byte) (netmask >>> 24),
|
||||
(byte) (netmask >>> 16 & 0xFF),
|
||||
(byte) (netmask >>> 8 & 0xFF),
|
||||
(byte) (netmask & 0xFF)
|
||||
};
|
||||
sb.append("inet ").append(format(address));
|
||||
try {
|
||||
sb.append(" netmask:").append(format(InetAddress.getByAddress(b)));
|
||||
|
|
|
@ -34,39 +34,21 @@ public class AkamaiTest {
|
|||
|
||||
@Test
|
||||
public void testAkamaiHttps() throws Exception {
|
||||
|
||||
// here we see server PUSH_PROMISE as response to headers, a go-away frame is written.
|
||||
|
||||
/*
|
||||
----------------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")
|
||||
HttpClient httpClient = HttpClient.getInstance();
|
||||
httpClient.prepareGet("https://http2.akamai.com/demo/h2_demo_frame.html")
|
||||
.setHttp2()
|
||||
.onException(e -> logger.log(Level.SEVERE, e.getMessage(), e))
|
||||
.onResponse(fullHttpResponse -> {
|
||||
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) -> {
|
||||
logger.log(Level.INFO, "received push promise: request headers = " + headers
|
||||
.onPushReceived((requestHeaders, fullHttpResponse) -> {
|
||||
String response = fullHttpResponse.content().toString(StandardCharsets.UTF_8);
|
||||
logger.log(Level.INFO, "received push promise: request headers = " + requestHeaders
|
||||
+ " status = " + fullHttpResponse.status()
|
||||
+ " response headers = " + fullHttpResponse.headers().entries()
|
||||
+ " response body = " + response
|
||||
);
|
||||
})
|
||||
.execute()
|
||||
|
|
Loading…
Reference in a new issue