This document describes how to integrate HTTPDNS with Apache HttpClient in a Java application.
1. Background
Apache HttpClient is a widely used HTTP network library in the Java ecosystem. It supports two major versions: 4.x and 5.x. You can integrate HTTPDNS into HttpClient by implementing the DnsResolver interface.
2. Implement a custom DnsResolver
HttpClient 5.x
import org.apache.hc.client5.http.DnsResolver;
import com.alibaba.sdk.java.httpdns.HttpDnsClient;
import com.alibaba.sdk.java.httpdns.HTTPDNSResult;
import com.alibaba.sdk.java.httpdns.RequestIpType;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
public class HttpDnsResolver implements DnsResolver {
private final HttpDnsClient httpDnsClient;
public HttpDnsResolver(HttpDnsClient httpDnsClient) {
this.httpDnsClient = httpDnsClient;
}
@Override
public String resolveCanonicalHostname(String host) {
return host;
}
@Override
public InetAddress[] resolve(String host) throws UnknownHostException {
HTTPDNSResult result = httpDnsClient.getHttpDnsResultForHostSyncNonBlocking(host, RequestIpType.both);
List<InetAddress> addresses = new ArrayList<>();
try {
if (result != null && result.getIps() != null) {
for (String ip : result.getIps()) {
addresses.add(InetAddress.getByName(ip));
}
}
if (result != null && result.getIpv6s() != null) {
for (String ip : result.getIpv6s()) {
addresses.add(InetAddress.getByName(ip));
}
}
} catch (UnknownHostException e) {
// Ignore the failure to parse a single IP address.
}
if (!addresses.isEmpty()) {
return addresses.toArray(new InetAddress[0]);
}
// Degrade to the system DNS.
return InetAddress.getAllByName(host);
}
}HttpClient 4.x
import org.apache.http.conn.DnsResolver;
import com.alibaba.sdk.java.httpdns.HttpDnsClient;
import com.alibaba.sdk.java.httpdns.HTTPDNSResult;
import com.alibaba.sdk.java.httpdns.RequestIpType;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
public class HttpDnsResolver4 implements DnsResolver {
private final HttpDnsClient httpDnsClient;
public HttpDnsResolver4(HttpDnsClient httpDnsClient) {
this.httpDnsClient = httpDnsClient;
}
@Override
public InetAddress[] resolve(String host) throws UnknownHostException {
HTTPDNSResult result = httpDnsClient.getHttpDnsResultForHostSyncNonBlocking(host, RequestIpType.both);
List<InetAddress> addresses = new ArrayList<>();
try {
if (result != null && result.getIps() != null) {
for (String ip : result.getIps()) {
addresses.add(InetAddress.getByName(ip));
}
}
if (result != null && result.getIpv6s() != null) {
for (String ip : result.getIpv6s()) {
addresses.add(InetAddress.getByName(ip));
}
}
} catch (UnknownHostException e) {
// Ignore the failure to parse a single IP address.
}
if (!addresses.isEmpty()) {
return addresses.toArray(new InetAddress[0]);
}
// Degrade to the system DNS.
return InetAddress.getAllByName(host);
}
}The DnsResolver for versions 4.x and 5.x comes from different packages. For version 5.x, you must also implement the resolveCanonicalHostname() method.
3. Configure HttpClient
HttpClient 5.x
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
HttpDnsClient httpDnsClient = HttpDnsClient.getClient(accountId);
HttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
.setDnsResolver(new HttpDnsResolver(httpDnsClient))
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
HttpClient 4.x
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
HttpDnsClient httpDnsClient = HttpDnsClient.getClient(accountId);
CloseableHttpClient httpClient = HttpClients.custom()
.setDnsResolver(new HttpDnsResolver4(httpDnsClient))
.build();4. Summary
The main advantages of using Apache HttpClient with HTTPDNS are:
Simple implementation: You only need to implement the
DnsResolverinterface to integrate.High versatility: It works in scenarios such as HTTPS, Server Name Indication (SNI), and setting cookies. You do not need to handle extra steps such as certificate validation or domain name verification.
Version compatibility: Supports both HttpClient 4.x and 5.x.