com.foxinmy.weixin4j.http.support.netty.Netty4HttpClient Maven / Gradle / Ivy
package com.foxinmy.weixin4j.http.support.netty;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.ssl.SslHandler;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import com.foxinmy.weixin4j.http.AbstractHttpClient;
import com.foxinmy.weixin4j.http.HttpClientException;
import com.foxinmy.weixin4j.http.HttpHeaders;
import com.foxinmy.weixin4j.http.HttpParams;
import com.foxinmy.weixin4j.http.HttpRequest;
import com.foxinmy.weixin4j.http.HttpResponse;
import com.foxinmy.weixin4j.http.entity.HttpEntity;
import com.foxinmy.weixin4j.http.factory.HttpClientFactory;
import com.foxinmy.weixin4j.util.Consts;
import com.foxinmy.weixin4j.util.SettableFuture;
import com.foxinmy.weixin4j.util.StringUtil;
/**
* Netty 4.x
*
* @className Netty4HttpClient
* @author jinyu([email protected])
* @date 2015年8月30日
* @since JDK 1.6
* @see
*/
public class Netty4HttpClient extends AbstractHttpClient {
private final Bootstrap bootstrap;
private final HttpParams params;
public Netty4HttpClient(Bootstrap bootstrap, HttpParams params) {
this.bootstrap = bootstrap;
this.params = params;
}
@Override
public HttpResponse execute(final HttpRequest request)
throws HttpClientException {
HttpResponse response = null;
try {
final URI uri = request.getURI();
final SettableFuture future = new SettableFuture();
ChannelFutureListener listener = new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture)
throws Exception {
if (channelFuture.isSuccess()) {
Channel channel = channelFuture.channel();
if ("https".equals(uri.getScheme())) {
SSLContext sslContext;
if (params != null
&& params.getSSLContext() != null) {
sslContext = params.getSSLContext();
} else {
sslContext = HttpClientFactory
.allowSSLContext();
}
SSLEngine sslEngine = sslContext.createSSLEngine();
sslEngine.setUseClientMode(true);
channel.pipeline().addFirst(
new SslHandler(sslEngine));
}
channel.pipeline().addLast(new RequestHandler(future));
DefaultHttpRequest uriRequest = createRequest(request);
channel.writeAndFlush(uriRequest);
} else {
future.setException(channelFuture.cause());
}
}
};
InetSocketAddress address = params != null
&& params.getProxy() != null ? (InetSocketAddress) params
.getProxy().address() : new InetSocketAddress(
InetAddress.getByName(uri.getHost()), getPort(uri));
bootstrap.connect(address).addListener(listener);
response = future.get();
handleResponse(response);
} catch (IOException e) {
throw new HttpClientException("I/O error on "
+ request.getMethod().name() + " request for \""
+ request.getURI().toString(), e);
} catch (InterruptedException e) {
throw new HttpClientException("Execute error on "
+ request.getMethod().name() + " request for \""
+ request.getURI().toString(), e);
} catch (ExecutionException e) {
throw new HttpClientException("Execute error on "
+ request.getMethod().name() + " request for \""
+ request.getURI().toString(), e);
} finally {
if (response != null) {
response.close();
}
}
return response;
}
private DefaultHttpRequest createRequest(HttpRequest request)
throws IOException {
HttpMethod method = HttpMethod.valueOf(request.getMethod().name());
URI uri = request.getURI();
String url = StringUtil.isBlank(uri.getRawPath()) ? "/" : uri
.getRawPath();
if (StringUtil.isNotBlank(uri.getRawQuery())) {
url += "?" + uri.getRawQuery();
}
DefaultHttpRequest uriRequest = new DefaultHttpRequest(
HttpVersion.HTTP_1_1, method, url);
// entity
HttpEntity entity = request.getEntity();
if (entity != null) {
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
ByteBufOutputStream out = new ByteBufOutputStream(byteBuf);
entity.writeTo(out);
out.flush();
out.close();
uriRequest = new DefaultFullHttpRequest(
uriRequest.getProtocolVersion(), uriRequest.getMethod(),
uriRequest.getUri(), byteBuf);
if (entity.getContentType() != null) {
uriRequest.headers().add(HttpHeaders.CONTENT_TYPE,
entity.getContentType().toString());
}
if (entity.getContentLength() < 0) {
uriRequest.headers().add(HttpHeaders.TRANSFER_ENCODING,
io.netty.handler.codec.http.HttpHeaders.Values.CHUNKED);
} else {
uriRequest.headers().add(HttpHeaders.CONTENT_LENGTH,
entity.getContentLength());
}
}
// header
HttpHeaders headers = request.getHeaders();
if (headers == null) {
headers = new HttpHeaders();
}
if (!headers.containsKey(HttpHeaders.HOST)) {
headers.set(HttpHeaders.HOST, uri.getHost());
}
// Add default accept headers
if (!headers.containsKey(HttpHeaders.ACCEPT)) {
headers.set(HttpHeaders.ACCEPT, "*/*");
}
// Add default user agent
if (!headers.containsKey(HttpHeaders.USER_AGENT)) {
headers.set(HttpHeaders.USER_AGENT, "netty/httpclient");
}
for (Entry> header : headers.entrySet()) {
uriRequest.headers().set(header.getKey(), header.getValue());
}
uriRequest.headers().set(HttpHeaders.ACCEPT_CHARSET,
Consts.UTF_8.displayName());
uriRequest.headers().set(HttpHeaders.CONNECTION,
io.netty.handler.codec.http.HttpHeaders.Values.CLOSE);
return uriRequest;
}
private int getPort(URI uri) {
int port = uri.getPort();
if (port == -1) {
if ("http".equalsIgnoreCase(uri.getScheme())) {
port = 80;
} else if ("https".equalsIgnoreCase(uri.getScheme())) {
port = 443;
}
}
return port;
}
private static class RequestHandler extends
SimpleChannelInboundHandler {
private final SettableFuture future;
public RequestHandler(SettableFuture future) {
this.future = future;
}
@Override
protected void channelRead0(ChannelHandlerContext context,
FullHttpResponse response) throws Exception {
byte[] content = null;
ByteBuf byteBuf = response.content();
if (byteBuf.hasArray()) {
content = byteBuf.array();
} else {
content = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(content);
}
future.set(new Netty4HttpResponse(context, response, content));
}
@Override
public void exceptionCaught(ChannelHandlerContext context,
Throwable cause) throws Exception {
future.setException(cause);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy