Skip to content

Commit 039d98f

Browse files
committed
Enable HTTP proxying for Netty client
See #858
1 parent 0dbdd43 commit 039d98f

14 files changed

+1625
-112
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"category": "Netty NIO HTTP Client",
3+
"type": "feature",
4+
"description": "Add ability to to use HTTP proxies with the Netty async client."
5+
}

Diff for: http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.java

+22
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ private NettyNioAsyncHttpClient(DefaultBuilder builder, AttributeMap serviceDefa
9191
.maxStreams(maxStreams)
9292
.sdkEventLoopGroup(sdkEventLoopGroup)
9393
.sslProvider(resolveSslProvider(builder))
94+
.proxyConfiguration(builder.proxyConfiguration)
9495
.build();
9596
}
9697

@@ -343,6 +344,16 @@ public interface Builder extends SdkAsyncHttpClient.Builder<NettyNioAsyncHttpCli
343344
* @return the builder of the method chaining.
344345
*/
345346
Builder sslProvider(SslProvider sslProvider);
347+
348+
/**
349+
* Set the proxy configuration for this client. The configured proxy will be used to proxy any HTTP request
350+
* destined for any host that does not match any of the hosts in configured non proxy hosts.
351+
*
352+
* @param proxyConfiguration The proxy configuration.
353+
* @return The builder for method chaining.
354+
* @see ProxyConfiguration#nonProxyHosts()
355+
*/
356+
Builder proxyConfiguration(ProxyConfiguration proxyConfiguration);
346357
}
347358

348359
/**
@@ -359,6 +370,7 @@ private static final class DefaultBuilder implements Builder {
359370
private SdkEventLoopGroup.Builder eventLoopGroupBuilder;
360371
private Integer maxHttp2Streams;
361372
private SslProvider sslProvider;
373+
private ProxyConfiguration proxyConfiguration;
362374

363375
private DefaultBuilder() {
364376
}
@@ -515,6 +527,16 @@ public void setSslProvider(SslProvider sslProvider) {
515527
sslProvider(sslProvider);
516528
}
517529

530+
@Override
531+
public Builder proxyConfiguration(ProxyConfiguration proxyConfiguration) {
532+
this.proxyConfiguration = proxyConfiguration;
533+
return this;
534+
}
535+
536+
public void setProxyConfiguration(ProxyConfiguration proxyConfiguration) {
537+
proxyConfiguration(proxyConfiguration);
538+
}
539+
518540
@Override
519541
public SdkAsyncHttpClient buildWithDefaults(AttributeMap serviceDefaults) {
520542
return new NettyNioAsyncHttpClient(this, standardOptions.build()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/*
2+
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.http.nio.netty;
17+
18+
import java.util.Collections;
19+
import java.util.HashSet;
20+
import java.util.Set;
21+
import software.amazon.awssdk.annotations.SdkPublicApi;
22+
import software.amazon.awssdk.utils.builder.CopyableBuilder;
23+
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
24+
25+
/**
26+
* Proxy configuration for {@link NettyNioAsyncHttpClient}. This class is used to configure an HTTP proxy to be used by
27+
* the {@link NettyNioAsyncHttpClient}.
28+
*
29+
* @see NettyNioAsyncHttpClient.Builder#proxyConfiguration(ProxyConfiguration)
30+
*/
31+
@SdkPublicApi
32+
public final class ProxyConfiguration implements ToCopyableBuilder<ProxyConfiguration.Builder, ProxyConfiguration> {
33+
private final String scheme;
34+
private final String host;
35+
private final int port;
36+
private final Set<String> nonProxyHosts;
37+
38+
private ProxyConfiguration(BuilderImpl builder) {
39+
this.scheme = builder.scheme;
40+
this.host = builder.host;
41+
this.port = builder.port;
42+
this.nonProxyHosts = Collections.unmodifiableSet(builder.nonProxyHosts);
43+
}
44+
45+
/**
46+
* @return The proxy scheme.
47+
*/
48+
public String scheme() {
49+
return scheme;
50+
}
51+
52+
/**
53+
* @return The proxy host.
54+
*/
55+
public String host() {
56+
return host;
57+
}
58+
59+
/**
60+
* @return The proxy port.
61+
*/
62+
public int port() {
63+
return port;
64+
}
65+
66+
/**
67+
* @return The set of hosts that should not be proxied.
68+
*/
69+
public Set<String> nonProxyHosts() {
70+
return nonProxyHosts;
71+
}
72+
73+
@Override
74+
public boolean equals(Object o) {
75+
if (this == o) {
76+
return true;
77+
}
78+
79+
if (o == null || getClass() != o.getClass()) {
80+
return false;
81+
}
82+
83+
ProxyConfiguration that = (ProxyConfiguration) o;
84+
85+
if (port != that.port) {
86+
return false;
87+
}
88+
89+
if (scheme != null ? !scheme.equals(that.scheme) : that.scheme != null) {
90+
return false;
91+
}
92+
93+
if (host != null ? !host.equals(that.host) : that.host != null) {
94+
return false;
95+
}
96+
97+
return nonProxyHosts.equals(that.nonProxyHosts);
98+
99+
}
100+
101+
@Override
102+
public int hashCode() {
103+
int result = scheme != null ? scheme.hashCode() : 0;
104+
result = 31 * result + (host != null ? host.hashCode() : 0);
105+
result = 31 * result + port;
106+
result = 31 * result + nonProxyHosts.hashCode();
107+
return result;
108+
}
109+
110+
@Override
111+
public Builder toBuilder() {
112+
return new BuilderImpl(this);
113+
}
114+
115+
public static Builder builder() {
116+
return new BuilderImpl();
117+
}
118+
119+
/**
120+
* Builder for {@link ProxyConfiguration}.
121+
*/
122+
public interface Builder extends CopyableBuilder<Builder, ProxyConfiguration> {
123+
124+
/**
125+
* Set the hostname of the proxy.
126+
* @param host The proxy host.
127+
* @return This object for method chaining.
128+
*/
129+
Builder host(String host);
130+
131+
/**
132+
* Set the port that the proxy expects connections on.
133+
* @param port The proxy port.
134+
* @return This object for method chaining.
135+
*/
136+
Builder port(int port);
137+
138+
/**
139+
* The HTTP scheme to use for connecting to the proxy. Valid values are {@code http} and {@code https}.
140+
* <p>
141+
* The client defaults to {@code http} if none is given.
142+
*
143+
* @param scheme The proxy scheme.
144+
* @return This object for method chaining.
145+
*/
146+
Builder scheme(String scheme);
147+
148+
/**
149+
* Set the set of hosts that should not be proxied. Any request whose host portion matches any of the patterns
150+
* given in the set will be sent to the remote host directly instead of through the proxy.
151+
*
152+
* @param nonProxyHosts The set of hosts that should not be proxied.
153+
* @return This object for method chaining.
154+
*/
155+
Builder nonProxyHosts(Set<String> nonProxyHosts);
156+
}
157+
158+
private static final class BuilderImpl implements Builder {
159+
private String scheme;
160+
private String host;
161+
private int port;
162+
private Set<String> nonProxyHosts = Collections.emptySet();
163+
164+
private BuilderImpl() {
165+
}
166+
167+
private BuilderImpl(ProxyConfiguration proxyConfiguration) {
168+
this.scheme = proxyConfiguration.scheme;
169+
this.host = proxyConfiguration.host;
170+
this.port = proxyConfiguration.port;
171+
this.nonProxyHosts = new HashSet<>(proxyConfiguration.nonProxyHosts);
172+
}
173+
174+
@Override
175+
public Builder scheme(String scheme) {
176+
this.scheme = scheme;
177+
return this;
178+
}
179+
180+
@Override
181+
public Builder host(String host) {
182+
this.host = host;
183+
return this;
184+
}
185+
186+
@Override
187+
public Builder port(int port) {
188+
this.port = port;
189+
return this;
190+
}
191+
192+
@Override
193+
public Builder nonProxyHosts(Set<String> nonProxyHosts) {
194+
if (nonProxyHosts != null) {
195+
this.nonProxyHosts = new HashSet<>(nonProxyHosts);
196+
} else {
197+
this.nonProxyHosts = Collections.emptySet();
198+
}
199+
return this;
200+
}
201+
202+
@Override
203+
public ProxyConfiguration build() {
204+
return new ProxyConfiguration(this);
205+
}
206+
}
207+
}

0 commit comments

Comments
 (0)