|
25 | 25 |
|
26 | 26 | import java.io.ByteArrayInputStream;
|
27 | 27 | import java.io.IOException;
|
| 28 | +import java.net.InetAddress; |
28 | 29 | import java.security.KeyManagementException;
|
29 | 30 | import java.security.NoSuchAlgorithmException;
|
30 | 31 | import java.security.cert.CertificateException;
|
|
48 | 49 | import org.apache.hc.client5.http.impl.classic.HttpClients;
|
49 | 50 | import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
|
50 | 51 | import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
|
| 52 | +import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner; |
51 | 53 | import org.apache.hc.client5.http.io.HttpClientConnectionManager;
|
52 | 54 | import org.apache.hc.client5.http.protocol.HttpClientContext;
|
53 | 55 | import org.apache.hc.client5.http.routing.HttpRoutePlanner;
|
|
57 | 59 | import org.apache.hc.core5.http.ClassicHttpResponse;
|
58 | 60 | import org.apache.hc.core5.http.Header;
|
59 | 61 | import org.apache.hc.core5.http.HttpEntity;
|
| 62 | +import org.apache.hc.core5.http.HttpException; |
| 63 | +import org.apache.hc.core5.http.HttpHost; |
60 | 64 | import org.apache.hc.core5.http.HttpResponse;
|
61 | 65 | import org.apache.hc.core5.http.config.Registry;
|
62 | 66 | import org.apache.hc.core5.http.impl.io.HttpRequestExecutor;
|
63 | 67 | import org.apache.hc.core5.http.io.SocketConfig;
|
| 68 | +import org.apache.hc.core5.http.protocol.HttpContext; |
64 | 69 | import org.apache.hc.core5.io.CloseMode;
|
65 | 70 | import org.apache.hc.core5.pool.PoolStats;
|
66 | 71 | import org.apache.hc.core5.ssl.SSLInitializationException;
|
|
108 | 113 | @SdkPublicApi
|
109 | 114 | public final class Apache5HttpClient implements SdkHttpClient {
|
110 | 115 |
|
111 |
| - public static final String CLIENT_NAME = "Apache5"; |
| 116 | + public static final String CLIENT_NAME = "Apache5Preview"; |
112 | 117 |
|
113 | 118 | private static final Logger log = Logger.loggerFor(Apache5HttpClient.class);
|
114 | 119 | private static final HostnameVerifier DEFAULT_HOSTNAME_VERIFIER = new DefaultHostnameVerifier();
|
@@ -206,7 +211,12 @@ private void addProxyConfig(HttpClientBuilder builder,
|
206 | 211 | }
|
207 | 212 |
|
208 | 213 | if (routePlanner != null) {
|
| 214 | + if (configuration.localAddress != null) { |
| 215 | + log.debug(() -> "localAddress configuration was ignored since Route planner was explicitly provided"); |
| 216 | + } |
209 | 217 | builder.setRoutePlanner(routePlanner);
|
| 218 | + } else if (configuration.localAddress != null) { |
| 219 | + builder.setRoutePlanner(new LocalAddressRoutePlanner(configuration.localAddress)); |
210 | 220 | }
|
211 | 221 |
|
212 | 222 | if (credentialsProvider != null) {
|
@@ -404,6 +414,11 @@ public interface Builder extends SdkHttpClient.Builder<Apache5HttpClient.Builder
|
404 | 414 | */
|
405 | 415 | Builder proxyConfiguration(ProxyConfiguration proxyConfiguration);
|
406 | 416 |
|
| 417 | + /** |
| 418 | + * Configure the local address that the HTTP client should use for communication. |
| 419 | + */ |
| 420 | + Builder localAddress(InetAddress localAddress); |
| 421 | + |
407 | 422 | /**
|
408 | 423 | * Configure whether the client should send an HTTP expect-continue handshake before each request.
|
409 | 424 | */
|
@@ -495,6 +510,7 @@ private static final class DefaultBuilder implements Builder {
|
495 | 510 | private final AttributeMap.Builder standardOptions = AttributeMap.builder();
|
496 | 511 | private Registry<AuthSchemeFactory> authSchemeRegistry;
|
497 | 512 | private ProxyConfiguration proxyConfiguration = ProxyConfiguration.builder().build();
|
| 513 | + private InetAddress localAddress; |
498 | 514 | private Boolean expectContinueEnabled;
|
499 | 515 | private HttpRoutePlanner httpRoutePlanner;
|
500 | 516 | private CredentialsProvider credentialsProvider;
|
@@ -560,6 +576,16 @@ public void setProxyConfiguration(ProxyConfiguration proxyConfiguration) {
|
560 | 576 | proxyConfiguration(proxyConfiguration);
|
561 | 577 | }
|
562 | 578 |
|
| 579 | + @Override |
| 580 | + public Builder localAddress(InetAddress localAddress) { |
| 581 | + this.localAddress = localAddress; |
| 582 | + return this; |
| 583 | + } |
| 584 | + |
| 585 | + public void setLocalAddress(InetAddress localAddress) { |
| 586 | + localAddress(localAddress); |
| 587 | + } |
| 588 | + |
563 | 589 | @Override
|
564 | 590 | public Builder expectContinueEnabled(Boolean expectContinueEnabled) {
|
565 | 591 | this.expectContinueEnabled = expectContinueEnabled;
|
@@ -794,4 +820,18 @@ private SocketConfig buildSocketConfig(AttributeMap standardOptions) {
|
794 | 820 | }
|
795 | 821 |
|
796 | 822 | }
|
| 823 | + |
| 824 | + private static class LocalAddressRoutePlanner extends DefaultRoutePlanner { |
| 825 | + private final InetAddress localAddress; |
| 826 | + |
| 827 | + LocalAddressRoutePlanner(InetAddress localAddress) { |
| 828 | + super(DefaultSchemePortResolver.INSTANCE); |
| 829 | + this.localAddress = localAddress; |
| 830 | + } |
| 831 | + |
| 832 | + @Override |
| 833 | + protected InetAddress determineLocalAddress(HttpHost firstHop, HttpContext context) throws HttpException { |
| 834 | + return localAddress; |
| 835 | + } |
| 836 | + } |
797 | 837 | }
|
0 commit comments