HTTPCLIENT-2292: HttpClient ignores socketConfig#getSocksProxyAddress

This commit is contained in:
Oleg Kalnichevski 2023-08-31 16:30:14 +02:00
parent 509ba6753f
commit aa5a7c7fe0
8 changed files with 48 additions and 67 deletions

View File

@ -29,7 +29,9 @@ package org.apache.hc.client5.http.impl.io;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.Arrays;
import org.apache.hc.client5.http.ConnectExceptionSupport;
@ -146,13 +148,14 @@ public class DefaultHttpClientConnectionOperator implements HttpClientConnection
}
final Timeout soTimeout = socketConfig.getSoTimeout();
final SocketAddress socksProxyAddress = socketConfig.getSocksProxyAddress();
final Proxy proxy = socksProxyAddress != null ? new Proxy(Proxy.Type.SOCKS, socksProxyAddress) : null;
final int port = this.schemePortResolver.resolve(host);
for (int i = 0; i < remoteAddresses.length; i++) {
final InetAddress address = remoteAddresses[i];
final boolean last = i == remoteAddresses.length - 1;
Socket sock = sf.createSocket(context);
Socket sock = sf.createSocket(proxy, context);
if (soTimeout != null) {
sock.setSoTimeout(soTimeout.toMillisecondsIntBound());
}

View File

@ -29,9 +29,11 @@ package org.apache.hc.client5.http.socket;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.Internal;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.protocol.HttpContext;
@ -50,13 +52,21 @@ public interface ConnectionSocketFactory {
* Creates new, unconnected socket. The socket should subsequently be passed to
* {@link #connectSocket(TimeValue, Socket, HttpHost, InetSocketAddress, InetSocketAddress,
* HttpContext) connectSocket} method.
*
* @return a new socket
*
* @throws IOException if an I/O error occurs while creating the socket
*/
Socket createSocket(HttpContext context) throws IOException;
/**
* Creates new, unconnected socket via a proxy (generally SOCKS is expected).
* The socket should subsequently be passed to {@link #connectSocket(TimeValue, Socket,
* HttpHost, InetSocketAddress, InetSocketAddress, HttpContext) connectSocket} method.
*
* @since 5.2
*/
@Internal
default Socket createSocket(Proxy proxy, HttpContext context) throws IOException {
return createSocket(context);
}
/**
* Connects the socket to the target host with the given resolved remote address.
*

View File

@ -29,6 +29,7 @@ package org.apache.hc.client5.http.socket;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import java.security.AccessController;
import java.security.PrivilegedActionException;
@ -60,6 +61,11 @@ public class PlainConnectionSocketFactory implements ConnectionSocketFactory {
super();
}
@Override
public Socket createSocket(final Proxy proxy, final HttpContext context) throws IOException {
return proxy != null ? new Socket(proxy) : new Socket();
}
@Override
public Socket createSocket(final HttpContext context) throws IOException {
return new Socket();

View File

@ -30,6 +30,7 @@ package org.apache.hc.client5.http.ssl;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import java.security.AccessController;
import java.security.PrivilegedActionException;
@ -39,7 +40,6 @@ import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
@ -200,7 +200,12 @@ public class SSLConnectionSocketFactory implements LayeredConnectionSocketFactor
@Override
public Socket createSocket(final HttpContext context) throws IOException {
return SocketFactory.getDefault().createSocket();
return new Socket();
}
@Override
public Socket createSocket(final Proxy proxy, final HttpContext context) throws IOException {
return new Socket(proxy);
}
@Override

View File

@ -27,25 +27,17 @@
package org.apache.hc.client5.http.examples;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import org.apache.hc.client5.http.classic.methods.HttpGet;
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.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.StatusLine;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.util.TimeValue;
/**
* How to send a request via SOCKS proxy.
@ -55,10 +47,7 @@ import org.apache.hc.core5.util.TimeValue;
public class ClientExecuteSOCKS {
public static void main(final String[] args)throws Exception {
final Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", new MyConnectionSocketFactory())
.build();
final InetSocketAddress socksaddr = new InetSocketAddress("mysockshost", 1234);
final InetSocketAddress socksaddr = new InetSocketAddress("localhost", 1080);
final PoolingHttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create()
.setDefaultSocketConfig(SocketConfig.custom()
.setSocksProxyAddress(socksaddr)
@ -82,36 +71,4 @@ public class ClientExecuteSOCKS {
}
}
static class MyConnectionSocketFactory implements ConnectionSocketFactory {
@Override
public Socket createSocket(final HttpContext context) throws IOException {
final InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address");
final Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
return new Socket(proxy);
}
@Override
public Socket connectSocket(
final TimeValue connectTimeout,
final Socket socket,
final HttpHost host,
final InetSocketAddress remoteAddress,
final InetSocketAddress localAddress,
final HttpContext context) throws IOException {
final Socket sock;
if (socket != null) {
sock = socket;
} else {
sock = createSocket(context);
}
if (localAddress != null) {
sock.bind(localAddress);
}
sock.connect(remoteAddress, connectTimeout != null ? connectTimeout.toMillisecondsIntBound() : 0);
return sock;
}
}
}

View File

@ -375,7 +375,7 @@ public class TestBasicHttpClientConnectionManager {
Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] {remote});
Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(plainSocketFactory);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.createSocket(Mockito.any(), Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
Mockito.eq(socket),
Mockito.any(),
@ -389,7 +389,7 @@ public class TestBasicHttpClientConnectionManager {
Mockito.verify(dnsResolver, Mockito.times(1)).resolve("somehost");
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target);
Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(context);
Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(null, context);
Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(
socket,
target,
@ -403,7 +403,7 @@ public class TestBasicHttpClientConnectionManager {
Mockito.verify(dnsResolver, Mockito.times(2)).resolve("somehost");
Mockito.verify(schemePortResolver, Mockito.times(2)).resolve(target);
Mockito.verify(plainSocketFactory, Mockito.times(2)).createSocket(context);
Mockito.verify(plainSocketFactory, Mockito.times(2)).createSocket(null, context);
Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(
socket,
target,
@ -447,7 +447,7 @@ public class TestBasicHttpClientConnectionManager {
Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory);
Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(sslSocketFactory);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.createSocket(Mockito.any(), Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
Mockito.eq(socket),
Mockito.any(),
@ -461,7 +461,7 @@ public class TestBasicHttpClientConnectionManager {
Mockito.verify(dnsResolver, Mockito.times(1)).resolve("someproxy");
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(proxy);
Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(context);
Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(null, context);
Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(
socket,
proxy,

View File

@ -91,7 +91,7 @@ public class TestHttpClientConnectionOperator {
Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] { ip1, ip2 });
Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory);
Mockito.when(schemePortResolver.resolve(host)).thenReturn(80);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.createSocket(Mockito.any(), Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
Mockito.any(),
Mockito.any(),
@ -141,7 +141,7 @@ public class TestHttpClientConnectionOperator {
Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] { ip1, ip2 });
Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory);
Mockito.when(schemePortResolver.resolve(host)).thenReturn(80);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.createSocket(Mockito.any(), Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
Mockito.any(),
Mockito.any(),
@ -166,7 +166,7 @@ public class TestHttpClientConnectionOperator {
Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] { ip1, ip2 });
Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory);
Mockito.when(schemePortResolver.resolve(host)).thenReturn(80);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.createSocket(Mockito.any(), Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
Mockito.any(),
Mockito.any(),
@ -192,7 +192,7 @@ public class TestHttpClientConnectionOperator {
Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] { ip1, ip2 });
Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory);
Mockito.when(schemePortResolver.resolve(host)).thenReturn(80);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.createSocket(Mockito.any(), Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
Mockito.any(),
Mockito.any(),
@ -236,7 +236,7 @@ public class TestHttpClientConnectionOperator {
Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainSocketFactory);
Mockito.when(schemePortResolver.resolve(host)).thenReturn(80);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.createSocket(Mockito.any(), Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
Mockito.any(),
Mockito.any(),

View File

@ -260,7 +260,7 @@ public class TestPoolingHttpClientConnectionManager {
Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[]{remote});
Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(plainSocketFactory);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.createSocket(Mockito.any(), Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
Mockito.eq(socket),
Mockito.any(),
@ -274,7 +274,7 @@ public class TestPoolingHttpClientConnectionManager {
Mockito.verify(dnsResolver, Mockito.times(1)).resolve("somehost");
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target);
Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(context);
Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(null, context);
Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(
socket,
target,
@ -288,7 +288,7 @@ public class TestPoolingHttpClientConnectionManager {
Mockito.verify(dnsResolver, Mockito.times(2)).resolve("somehost");
Mockito.verify(schemePortResolver, Mockito.times(2)).resolve(target);
Mockito.verify(plainSocketFactory, Mockito.times(2)).createSocket(context);
Mockito.verify(plainSocketFactory, Mockito.times(2)).createSocket(null, context);
Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(
socket,
target,
@ -345,7 +345,7 @@ public class TestPoolingHttpClientConnectionManager {
Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
Mockito.when(socketFactoryRegistry.lookup("http")).thenReturn(plainsf);
Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(sslsf);
Mockito.when(plainsf.createSocket(Mockito.any())).thenReturn(mockSock);
Mockito.when(plainsf.createSocket(Mockito.any(), Mockito.any())).thenReturn(mockSock);
Mockito.when(plainsf.connectSocket(
Mockito.eq(mockSock),
Mockito.any(),
@ -359,7 +359,7 @@ public class TestPoolingHttpClientConnectionManager {
Mockito.verify(dnsResolver, Mockito.times(1)).resolve("someproxy");
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(proxy);
Mockito.verify(plainsf, Mockito.times(1)).createSocket(context);
Mockito.verify(plainsf, Mockito.times(1)).createSocket(null, context);
Mockito.verify(plainsf, Mockito.times(1)).connectSocket(
mockSock,
proxy,