I'd like to migrate from HTTP Client 4 to 5 using SOCKS. Here's my code with HTTP Client 4:
InetSocketAddress socksaddr = new InetSocketAddress((String) call.props.get(PROXY_HOST_NAME),
Integer.parseInt((String) call.props.get(PROXY_PORT)));
Lookup<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
.<ConnectionSocketFactory>create()
.register(HTTP, new SocksCompatibleConnectionSocketFactory(socksaddr))
.register(HTTPS, new SocksCompatibleSSLConnectionSocketFactory(socksaddr,
(javax.net.ssl.SSLSocketFactory) SSLSocketFactory.getDefault()))
.build();
BasicHttpClientConnectionManager basicmgr = new BasicHttpClientConnectionManager(
socketFactoryRegistry);
final CloseableHttpClient client = HttpClientBuilder.create().setConnectionManager(basicmgr)
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectTimeout(MxParam.getIntWithDefaultValueNoException(WSTIMEOUT, 30000))
.setSocketTimeout(MxParam.getIntWithDefaultValueNoException(WSTIMEOUT, 30000))
.build())
.setConnectionManagerShared(true)
.useSystemProperties()
.setMaxConnPerRoute(MxParam.getIntWithDefaultValueNoException(MAXCONECTIONPERHOST, 20))
.setMaxConnTotal(MxParam.getIntWithDefaultValueNoException(MAXTOTALCONNECTION, 20))
.build();
With the 2 following classes:
static class SocksCompatibleConnectionSocketFactory extends PlainConnectionSocketFactory {
private final InetSocketAddress socksAddress;
public SocksCompatibleConnectionSocketFactory(InetSocketAddress socksAddress) {
super();
this.socksAddress = socksAddress;
}
@Override
public Socket createSocket(HttpContext context) throws IOException {
return new Socket(new Proxy(Proxy.Type.SOCKS, socksAddress));
}
}
static class SocksCompatibleSSLConnectionSocketFactory extends SSLConnectionSocketFactory {
final InetSocketAddress socksAddress;
public SocksCompatibleSSLConnectionSocketFactory(final InetSocketAddress socksAddress,
final SSLSocketFactory sslSocketFactory) {
super(sslSocketFactory, split(System.getProperty("https.protocols")),
split(System.getProperty("https.cipherSuites")), getDefaultHostnameVerifier());
this.socksAddress = socksAddress;
}
@Override
public Socket createSocket(final HttpContext context) throws IOException {
return new Socket(new Proxy(Proxy.Type.SOCKS, socksAddress));
}
private static String[] split(final String s) {
if (TextUtils.isBlank(s)) {
return null;
}
return s.split(" *, *");
}
}
I don't see what to do in order to use my SOCKS compatible socket factories, could you please help me ?
One no longer needs to do any of these. One can configure connection tunneling through a SOCKS proxy using SocketConfig
final InetSocketAddress socksaddr = new InetSocketAddress("localhost", 1080);
final PoolingHttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create()
.setDefaultSocketConfig(SocketConfig.custom()
.setSocksProxyAddress(socksaddr)
.build())
.build();
try (final CloseableHttpClient httpclient = HttpClients.custom()
.setConnectionManager(cm)
.build()) {
final HttpHost target = new HttpHost("http", "httpbin.org", 80);
final HttpGet request = new HttpGet("/get");
System.out.println("Executing request " + request.getMethod() + " " + request.getUri() +
" via SOCKS proxy " + socksaddr);
httpclient.execute(target, request, response -> {
System.out.println("----------------------------------------");
System.out.println(request + "->" + new StatusLine(response));
EntityUtils.consume(response.getEntity());
return null;
});
}