当域名绑定多个ip的时候,需要指定当前请求的域名是哪个ip地址。
HttpClient 4.x how to find target IP of the requested site
直接通过httpclient 去获取,查到的资料基本基于3.x版本的扩展。
最后搜索到:
https://stackoverflow.com/questions/23281462/apache-httpclient-4-3-3-how-to-find-target-ip-of-the-requested-site
解决方式可以参考:
Since the Socket s = super.createSocket(context); creates simple java Socket in the abstraction, I tried to override connectSocket method and it works this time. Here is the working example:
public static void main(String[] args) throws ClientProtocolException,
IOException {
String s = "http://google.com";
PoolingHttpClientConnectionManager m = new PoolingHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", new PlainConnectionSocketFactory() {
@Override
public Socket connectSocket(int connectTimeout,
Socket socket, HttpHost host,
InetSocketAddress remoteAddress,
InetSocketAddress localAddress,
HttpContext context) throws IOException {
context.setAttribute("sock-address",
remoteAddress);
return super.connectSocket(connectTimeout,
socket, host, remoteAddress,
localAddress, context);
}
}).build(), new SystemDefaultDnsResolver());
CloseableHttpClient minimal = HttpClients.custom()
.setConnectionManager(m).build();
HttpGet get = new HttpGet(s);
HttpClientContext context = HttpClientContext.create();
CloseableHttpResponse response = minimal.execute(get, context);
InetSocketAddress addr = (InetSocketAddress) context
.getAttribute("sock-address");
System.out.println(addr.getAddress().getHostAddress());
}
对于4.x版本,也可以通过上下文的方式获取到当前链接,由于连接在返回时候可能就会被释放。因此通过扩展HttpRequestExecutor的方式去提前获取到ip并保持在context,之后通过context获取ip即可:
一、增加HttpRequestExecutorEx获取ip
public class HttpRequestExecutorEx extends HttpRequestExecutor {
public static final String HTTP_HOSTADDRESS = "http.hostAddress";
@Override
public HttpResponse execute(
final HttpRequest request,
final HttpClientConnection conn,
final HttpContext context) throws IOException, HttpException {
Args.notNull(request, "HTTP request");
Args.notNull(conn, "Client connection");
Args.notNull(context, "HTTP context");
try {
HttpResponse response = doSendRequest(request, conn, context);
if (response == null) {
response = doReceiveResponse(request, conn, context);
}
processRequestIp(conn, context);
return response;
} catch (final IOException ex) {
processRequestIp(conn,context);
closeConnection(conn);
throw ex;
} catch (final HttpException ex) {
processRequestIp(conn, context);
closeConnection(conn);
throw ex;
} catch (final RuntimeException ex) {
processRequestIp(conn, context);
closeConnection(conn);
throw ex;
}
}
private void processRequestIp(HttpClientConnection conn, HttpContext context) {
if (conn instanceof ManagedHttpClientConnection) {
ManagedHttpClientConnection managedConn = (ManagedHttpClientConnection) conn;
if (managedConn != null && managedConn.isOpen()) {
Socket socket = managedConn.getSocket();
String hostAddress = socket.getInetAddress().getHostAddress();
context.setAttribute(HTTP_HOSTADDRESS, hostAddress);
}
}
}
private static void closeConnection(final HttpClientConnection conn) {
try {
conn.close();
} catch (final IOException ignore) {
}
}
}
二、将该类增加到httpclient中:
CloseableHttpClient httpClient = HttpClients.custom()
.setRequestExecutor(new HttpRequestExecutorEx())
.build();
三、 最后从context获取
BasicHttpContext basicHttpContext = new BasicHttpContext();
HttpResponse response = httpClient.execute(post, basicHttpContext);
hostAddress = (String) basicHttpContext.getAttribute(HttpRequestExecutorEx.HTTP_HOSTADDRESS);