Skip to content

Commit c568701

Browse files
committed
Add support for HTTPS over UDS
1 parent 025275b commit c568701

7 files changed

Lines changed: 55 additions & 27 deletions

File tree

httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/UdsAsyncIntegrationTests.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ public Http1() {
4646
}
4747
}
4848

49+
@Nested
50+
@DisplayName("Fundamentals (HTTP/1.1, TLS)")
51+
class Http1Tls extends TestHttp1Async {
52+
public Http1Tls() {
53+
super(URIScheme.HTTPS, true);
54+
checkForUdsSupport();
55+
}
56+
}
57+
4958
@Nested
5059
@DisplayName("Request re-execution (HTTP/1.1)")
5160
class Http1RequestReExecution extends TestHttp1RequestReExecution {

httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/UdsIntegrationTests.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
import org.junit.jupiter.api.DisplayName;
3131
import org.junit.jupiter.api.Nested;
3232

33-
import static org.junit.jupiter.api.Assumptions.assumeTrue;
34-
3533
class UdsIntegrationTests {
3634
@Nested
3735
@DisplayName("Request execution (HTTP/1.1)")
@@ -46,7 +44,6 @@ public RequestExecution() {
4644
class RequestExecutionTls extends TestClientRequestExecution {
4745
public RequestExecutionTls() {
4846
super(URIScheme.HTTPS, true);
49-
assumeTrue(false, "HTTPS is not currently supported over Unix domain sockets");
5047
}
5148
}
5249

httpclient5/src/main/java/org/apache/hc/client5/http/HttpRoute.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,7 @@ public final class HttpRoute implements RouteInfo, Cloneable {
109109
}
110110

111111
private void validateUdsArguments() {
112-
if (this.secure) {
113-
throw new UnsupportedOperationException("HTTPS is not supported over a UDS connection");
114-
} else if (this.localAddress != null) {
112+
if (this.localAddress != null) {
115113
throw new UnsupportedOperationException("A localAddress cannot be specified for a UDS connection");
116114
} else if (this.proxyChain != null) {
117115
throw new UnsupportedOperationException("Proxies are not supported over a UDS connection");
@@ -225,7 +223,22 @@ public HttpRoute(final HttpHost target, final NamedEndpoint targetName, final In
225223
* @since 5.6
226224
*/
227225
public HttpRoute(final HttpHost target, final Path unixDomainSocket) {
228-
this(target, null, null, Collections.emptyList(), unixDomainSocket, false, TunnelType.PLAIN, LayerType.PLAIN);
226+
this(target, false, unixDomainSocket);
227+
}
228+
229+
/**
230+
* Creates a new direct route that connects over a Unix domain socket rather than TCP.
231+
*
232+
* @param target the host to which to route
233+
* @param secure {@code true} if the route is (to be) secure,
234+
* {@code false} otherwise
235+
* @param unixDomainSocket the path to the Unix domain socket
236+
*
237+
* @since 5.6
238+
*/
239+
public HttpRoute(final HttpHost target, final boolean secure, final Path unixDomainSocket) {
240+
this(target, null, null, Collections.emptyList(), unixDomainSocket, secure,
241+
TunnelType.PLAIN, LayerType.PLAIN);
229242
}
230243

231244
/**

httpclient5/src/main/java/org/apache/hc/client5/http/RouteTracker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ public HttpRoute toRoute() {
292292
if (!this.connected) {
293293
return null;
294294
} else if (this.unixDomainSocket != null) {
295-
return new HttpRoute(this.targetHost, this.unixDomainSocket);
295+
return new HttpRoute(this.targetHost, this.secure, this.unixDomainSocket);
296296
} else {
297297
return new HttpRoute(this.targetHost, this.localAddress,
298298
this.proxyChain, this.secure,

httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
*/
2727
package org.apache.hc.client5.http.impl.io;
2828

29+
import javax.net.ssl.SSLSocket;
2930
import java.io.IOException;
3031
import java.net.InetSocketAddress;
3132
import java.net.Proxy;
@@ -36,8 +37,6 @@
3637
import java.util.Collections;
3738
import java.util.List;
3839

39-
import javax.net.ssl.SSLSocket;
40-
4140
import org.apache.hc.client5.http.ConnectExceptionSupport;
4241
import org.apache.hc.client5.http.DnsResolver;
4342
import org.apache.hc.client5.http.SchemePortResolver;
@@ -182,7 +181,7 @@ public void connect(
182181
final SocketAddress socksProxyAddress = socketConfig.getSocksProxyAddress();
183182
final Proxy socksProxy = socksProxyAddress != null ? new Proxy(Proxy.Type.SOCKS, socksProxyAddress) : null;
184183
if (unixDomainSocket != null) {
185-
connectToUnixDomainSocket(conn, endpointHost, unixDomainSocket, connectTimeout, socketConfig, context, soTimeout);
184+
connectToUnixDomainSocket(conn, endpointHost, endpointName, attachment, unixDomainSocket, connectTimeout, socketConfig, context, soTimeout);
186185
return;
187186
}
188187

@@ -218,17 +217,7 @@ public void connect(
218217
conn.setSocketTimeout(soTimeout);
219218
final TlsSocketStrategy tlsSocketStrategy = tlsSocketStrategyLookup != null ? tlsSocketStrategyLookup.lookup(endpointHost.getSchemeName()) : null;
220219
if (tlsSocketStrategy != null) {
221-
final NamedEndpoint tlsName = endpointName != null ? endpointName : endpointHost;
222-
onBeforeTlsHandshake(context, endpointHost);
223-
if (LOG.isDebugEnabled()) {
224-
LOG.debug("{} {} upgrading to TLS", ConnPoolSupport.getId(conn), tlsName);
225-
}
226-
final SSLSocket sslSocket = tlsSocketStrategy.upgrade(socket, tlsName.getHostName(), tlsName.getPort(), attachment, context);
227-
conn.bind(sslSocket, socket);
228-
onAfterTlsHandshake(context, endpointHost);
229-
if (LOG.isDebugEnabled()) {
230-
LOG.debug("{} {} upgraded to TLS", ConnPoolSupport.getId(conn), tlsName);
231-
}
220+
upgradeToTls(conn, endpointHost, endpointName, attachment, context, tlsSocketStrategy, socket);
232221
}
233222
return;
234223
} catch (final RuntimeException ex) {
@@ -249,9 +238,27 @@ public void connect(
249238
}
250239
}
251240

241+
private void upgradeToTls(final ManagedHttpClientConnection conn, final HttpHost endpointHost,
242+
final NamedEndpoint endpointName, final Object attachment, final HttpContext context,
243+
final TlsSocketStrategy tlsSocketStrategy, final Socket socket) throws IOException {
244+
final NamedEndpoint tlsName = endpointName != null ? endpointName : endpointHost;
245+
onBeforeTlsHandshake(context, endpointHost);
246+
if (LOG.isDebugEnabled()) {
247+
LOG.debug("{} {} upgrading to TLS", ConnPoolSupport.getId(conn), tlsName);
248+
}
249+
final SSLSocket sslSocket = tlsSocketStrategy.upgrade(socket, tlsName.getHostName(), tlsName.getPort(), attachment, context);
250+
conn.bind(sslSocket, socket);
251+
onAfterTlsHandshake(context, endpointHost);
252+
if (LOG.isDebugEnabled()) {
253+
LOG.debug("{} {} upgraded to TLS", ConnPoolSupport.getId(conn), tlsName);
254+
}
255+
}
256+
252257
private void connectToUnixDomainSocket(
253258
final ManagedHttpClientConnection conn,
254259
final HttpHost endpointHost,
260+
final NamedEndpoint endpointName,
261+
final Object attachment,
255262
final Path unixDomainSocket,
256263
final Timeout connectTimeout,
257264
final SocketConfig socketConfig,
@@ -273,6 +280,11 @@ private void connectToUnixDomainSocket(
273280
LOG.debug("{} {} connected to {}", ConnPoolSupport.getId(conn), endpointHost, unixDomainSocket);
274281
}
275282
conn.setSocketTimeout(soTimeout);
283+
284+
final TlsSocketStrategy tlsSocketStrategy = tlsSocketStrategyLookup != null ? tlsSocketStrategyLookup.lookup(endpointHost.getSchemeName()) : null;
285+
if (tlsSocketStrategy != null) {
286+
upgradeToTls(conn, endpointHost, endpointName, attachment, context, tlsSocketStrategy, socket);
287+
}
276288
} catch (final RuntimeException ex) {
277289
Closer.closeQuietly(newSocket);
278290
throw ex;

httpclient5/src/main/java/org/apache/hc/client5/http/impl/routing/DefaultRoutePlanner.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,8 @@ public final HttpRoute determineRoute(final HttpHost host, final HttpRequest req
100100
if (unixDomainSocket != null) {
101101
if (proxy != null) {
102102
throw new UnsupportedOperationException("Proxies are not supported over Unix domain sockets");
103-
} else if (secure) {
104-
throw new UnsupportedOperationException("HTTPS is not supported over Unix domain sockets");
105103
}
106-
return new HttpRoute(target, unixDomainSocket);
104+
return new HttpRoute(target, secure, unixDomainSocket);
107105
}
108106
final InetAddress inetAddress = determineLocalAddress(target, context);
109107
if (proxy == null) {

httpclient5/src/test/java/org/apache/hc/client5/http/TestHttpRoute.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,7 @@ void testUnixDomainSocketValidation() {
487487
final List<HttpHost> noProxies = Collections.emptyList();
488488
final List<HttpHost> oneProxy = Collections.singletonList(PROXY1);
489489
new HttpRoute(TARGET1, null, null, noProxies, uds, false, TunnelType.PLAIN, LayerType.PLAIN);
490-
Assertions.assertThrows(RuntimeException.class, () ->
491-
new HttpRoute(TARGET1, null, null, noProxies, uds, true, TunnelType.PLAIN, LayerType.PLAIN));
490+
new HttpRoute(TARGET1, null, null, null, uds, true, TunnelType.PLAIN, LayerType.PLAIN);
492491
Assertions.assertThrows(RuntimeException.class, () ->
493492
new HttpRoute(TARGET1, null, LOCAL41, noProxies, uds, false, TunnelType.PLAIN, LayerType.PLAIN));
494493
Assertions.assertThrows(RuntimeException.class, () ->

0 commit comments

Comments
 (0)