简体   繁体   中英

Apache HttpClient 4.3.3 how to find target IP of the requested site

I have read this one :

http://httpcomponents.10934.n7.nabble.com/get-InetAddress-for-the-HTTP-TARGET-HOST-td18332.html

And I could not figure out how to do the same with the latest Apache HttpClient 4.3.3. What I want to do is to obtain the IP of the requested site. I know that this is not possible with the minimal httpclient, but how exactly should it be used?

Since the minimal httpclient has PoolingHttpClientConnectionManager(HttpClientConnectionManager) as argument but not ClientConnectionManager I don't know which methods to override and which attributes to set. The example above has direct access to sockets, which is not the case with the new one.

So the question is how to do that with the new (4.3.3) API. And how it is correct to keep the already resolved IPs from redirects for example, avoiding second DNS resolution.

And a code snippet which approximates the written in the link and which both lines of output are NULL:

 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 createSocket(HttpContext context)
                                    throws IOException {
                                Socket s = super.createSocket(context);
                                context.setAttribute("sock-address",
                                        s.getRemoteSocketAddress());
                                return s;
                            }
                        }).build(), new SystemDefaultDnsResolver());

        CloseableHttpClient minimal = HttpClients.createMinimal(m);

        HttpGet get = new HttpGet(s);

        HttpClientContext context = HttpClientContext.create();

        CloseableHttpResponse response = minimal.execute(get, context);

        InetSocketAddress addr = (InetSocketAddress) context
                .getAttribute("sock-address");

        HttpHost target = (HttpHost) context
                .getAttribute(ExecutionContext.HTTP_TARGET_HOST);

        System.out.println(addr);
        System.out.println(target.getAddress());

    }

And the only maven dependencies:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.3.3</version>
</dependency>       

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());

    }

In addition, a site could have multiple IPs to which it could be resolved and the upper solution will choose only the first it connects to. In case you want the other IPs you have to resolve them on your own with :

SystemDefaultDnsResolver r = new SystemDefaultDnsResolver();
InetAddress[] resolve = r.resolve("google.com");

This could lead to additional dns checks and bad performance. What I read about is to setup nscd service that caches the dns checks and speeds up requests.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM