當域名綁定多個ip的時候,需要指定當前請求的域名是哪個ip地址。
HttpClient 4.x how to find target IP of the requested site
直接通過httpclient 去獲取,查到的資料基本基于3.x版本的擴展。
最后搜索到:
//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 = "//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);