From 157f8382f4d2c6d282425477e340f769e4980c4c Mon Sep 17 00:00:00 2001 From: Guillermo Priego Date: Mon, 7 Jun 2021 18:46:41 +0200 Subject: [PATCH 1/8] feat(client): support proxy with auth into netty client --- .../http/nio/netty/ProxyConfiguration.java | 32 +++++++++++++++++++ .../internal/AwaitCloseChannelPoolMap.java | 5 +-- .../internal/Http1TunnelConnectionPool.java | 26 ++++++++++++--- .../internal/ProxyTunnelInitHandler.java | 26 +++++++++++++-- .../Http1TunnelConnectionPoolTest.java | 16 +++++----- .../internal/ProxyTunnelInitHandlerTest.java | 2 +- 6 files changed, 88 insertions(+), 19 deletions(-) diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java index 5ee2ac1cf977..7cbb12ea0ec6 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java @@ -33,12 +33,16 @@ public final class ProxyConfiguration implements ToCopyableBuilder nonProxyHosts; private ProxyConfiguration(BuilderImpl builder) { this.scheme = builder.scheme; this.host = builder.host; this.port = builder.port; + this.username = builder.username; + this.password = builder.password; this.nonProxyHosts = Collections.unmodifiableSet(builder.nonProxyHosts); } @@ -63,6 +67,14 @@ public int port() { return port; } + public String username() { + return username; + } + + public String password() { + return password; + } + /** * @return The set of hosts that should not be proxied. */ @@ -153,12 +165,18 @@ public interface Builder extends CopyableBuilder { * @return This object for method chaining. */ Builder nonProxyHosts(Set nonProxyHosts); + + Builder username(String username); + + Builder password(String password); } private static final class BuilderImpl implements Builder { private String scheme; private String host; private int port; + private String username; + private String password; private Set nonProxyHosts = Collections.emptySet(); private BuilderImpl() { @@ -189,6 +207,8 @@ public Builder port(int port) { return this; } + + @Override public Builder nonProxyHosts(Set nonProxyHosts) { if (nonProxyHosts != null) { @@ -199,6 +219,18 @@ public Builder nonProxyHosts(Set nonProxyHosts) { return this; } + @Override + public Builder username(String username) { + this.username = username; + return this; + } + + @Override + public Builder password(String password) { + this.password = password; + return this; + } + @Override public ProxyConfiguration build() { return new ProxyConfiguration(this); diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMap.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMap.java index 9cadab45bef4..a6ed34f787f3 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMap.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMap.java @@ -136,8 +136,9 @@ protected SimpleChannelPoolAwareChannelPool newPool(URI key) { ChannelPool baseChannelPool; if (shouldUseProxyForHost(key)) { tcpChannelPool = new BetterSimpleChannelPool(bootstrap, NOOP_HANDLER); - baseChannelPool = new Http1TunnelConnectionPool(bootstrap.config().group().next(), tcpChannelPool, - sslContext, proxyAddress(key), key, pipelineInitializer); + baseChannelPool = new Http1TunnelConnectionPool(bootstrap.config().group().next(), tcpChannelPool, sslContext, + proxyAddress(key), proxyConfiguration.username(), proxyConfiguration.password(), + key, pipelineInitializer); } else { tcpChannelPool = new BetterSimpleChannelPool(bootstrap, pipelineInitializer); baseChannelPool = tcpChannelPool; diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java index 0d9b3703eb33..245a4e0c3b8c 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java @@ -49,24 +49,38 @@ public class Http1TunnelConnectionPool implements ChannelPool { private final ChannelPool delegate; private final SslContext sslContext; private final URI proxyAddress; + private final String proxyUser; + private final String proxyPassword; private final URI remoteAddress; private final ChannelPoolHandler handler; private final InitHandlerSupplier initHandlerSupplier; + public Http1TunnelConnectionPool(EventLoop eventLoop, ChannelPool delegate, SslContext sslContext, + URI proxyAddress, String proxyUsername, String proxyPassword, + URI remoteAddress, ChannelPoolHandler handler) { + this(eventLoop, delegate, sslContext, + proxyAddress, proxyUsername, proxyPassword, remoteAddress, handler, + ProxyTunnelInitHandler::new); + } + public Http1TunnelConnectionPool(EventLoop eventLoop, ChannelPool delegate, SslContext sslContext, URI proxyAddress, URI remoteAddress, ChannelPoolHandler handler) { - this(eventLoop, delegate, sslContext, proxyAddress, remoteAddress, handler, ProxyTunnelInitHandler::new); + this(eventLoop, delegate, sslContext, + proxyAddress, null, null, remoteAddress, handler, + ProxyTunnelInitHandler::new); } @SdkTestInternalApi Http1TunnelConnectionPool(EventLoop eventLoop, ChannelPool delegate, SslContext sslContext, - URI proxyAddress, URI remoteAddress, ChannelPoolHandler handler, - InitHandlerSupplier initHandlerSupplier) { + URI proxyAddress, String proxyUser, String proxyPassword, URI remoteAddress, + ChannelPoolHandler handler, InitHandlerSupplier initHandlerSupplier) { this.eventLoop = eventLoop; this.delegate = delegate; this.sslContext = sslContext; this.proxyAddress = proxyAddress; + this.proxyUser = proxyUser; + this.proxyPassword = proxyPassword; this.remoteAddress = remoteAddress; this.handler = handler; this.initHandlerSupplier = initHandlerSupplier; @@ -120,7 +134,8 @@ private void setupChannel(Channel ch, Promise acquirePromise) { if (sslHandler != null) { ch.pipeline().addLast(sslHandler); } - ch.pipeline().addLast(initHandlerSupplier.newInitHandler(delegate, remoteAddress, tunnelEstablishedPromise)); + ch.pipeline().addLast(initHandlerSupplier.newInitHandler(delegate, this.proxyUser, this.proxyPassword, remoteAddress, + tunnelEstablishedPromise)); tunnelEstablishedPromise.addListener((Future f) -> { if (f.isSuccess()) { Channel tunnel = f.getNow(); @@ -160,6 +175,7 @@ private static boolean isTunnelEstablished(Channel ch) { @SdkTestInternalApi @FunctionalInterface interface InitHandlerSupplier { - ChannelHandler newInitHandler(ChannelPool sourcePool, URI remoteAddress, Promise tunnelInitFuture); + ChannelHandler newInitHandler(ChannelPool sourcePool, String proxyUsername, String proxyPassword, URI remoteAddress, + Promise tunnelInitFuture); } } diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandler.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandler.java index c5500f7f6633..7591412f7618 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandler.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandler.java @@ -28,35 +28,48 @@ import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpVersion; +import io.netty.util.CharsetUtil; import io.netty.util.concurrent.Promise; import java.io.IOException; import java.net.URI; +import java.util.Base64; import java.util.function.Supplier; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.annotations.SdkTestInternalApi; import software.amazon.awssdk.utils.Logger; +import software.amazon.awssdk.utils.StringUtils; /** * Handler that initializes the HTTP tunnel. */ @SdkInternalApi public final class ProxyTunnelInitHandler extends ChannelDuplexHandler { + public static final Logger log = Logger.loggerFor(ProxyTunnelInitHandler.class); private final ChannelPool sourcePool; + private final String username; + private final String password; private final URI remoteHost; private final Promise initPromise; private final Supplier httpCodecSupplier; + public ProxyTunnelInitHandler(ChannelPool sourcePool, String proxyUsername, String proxyPassword, URI remoteHost, + Promise initPromise) { + this(sourcePool, proxyUsername, proxyPassword, remoteHost, initPromise, HttpClientCodec::new); + } + public ProxyTunnelInitHandler(ChannelPool sourcePool, URI remoteHost, Promise initPromise) { - this(sourcePool, remoteHost, initPromise, HttpClientCodec::new); + this(sourcePool, null, null, remoteHost, initPromise, HttpClientCodec::new); } @SdkTestInternalApi - public ProxyTunnelInitHandler(ChannelPool sourcePool, URI remoteHost, Promise initPromise, - Supplier httpCodecSupplier) { + public ProxyTunnelInitHandler(ChannelPool sourcePool, String prosyUsername, String proxyPassword, + URI remoteHost, Promise initPromise, Supplier httpCodecSupplier) { this.sourcePool = sourcePool; this.remoteHost = remoteHost; this.initPromise = initPromise; + this.username = prosyUsername; + this.password = proxyPassword; this.httpCodecSupplier = httpCodecSupplier; } @@ -137,6 +150,13 @@ private HttpRequest connectRequest() { HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.CONNECT, uri, Unpooled.EMPTY_BUFFER, false); request.headers().add(HttpHeaderNames.HOST, uri); + + if (!StringUtils.isEmpty(this.username) && !StringUtils.isEmpty(this.password)) { + String authToken = String.format("%s:%s", this.username, this.password); + String authB64 = Base64.getEncoder().encodeToString(authToken.getBytes(CharsetUtil.UTF_8)); + request.headers().add(HttpHeaderNames.PROXY_AUTHORIZATION, String.format("Basic %s", authB64)); + } + return request; } diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java index 12100fcf8acc..48e3274f8b82 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java @@ -138,13 +138,13 @@ public void tunnelNotEstablished_addsInitHandler() throws InterruptedException { @Test public void tunnelInitFails_acquireFutureFails() { - Http1TunnelConnectionPool.InitHandlerSupplier supplier = (srcPool, remoteAddr, initFuture) -> { + Http1TunnelConnectionPool.InitHandlerSupplier supplier = (srcPool, proxyUser, proxyPassword, remoteAddr, initFuture) -> { initFuture.setFailure(new IOException("boom")); return mock(ChannelHandler.class); }; Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, - HTTP_PROXY_ADDRESS, REMOTE_ADDRESS, mockHandler, supplier); + HTTP_PROXY_ADDRESS,null, null, REMOTE_ADDRESS, mockHandler, supplier); Future acquireFuture = tunnelPool.acquire(); @@ -153,13 +153,13 @@ public void tunnelInitFails_acquireFutureFails() { @Test public void tunnelInitSucceeds_acquireFutureSucceeds() { - Http1TunnelConnectionPool.InitHandlerSupplier supplier = (srcPool, remoteAddr, initFuture) -> { + Http1TunnelConnectionPool.InitHandlerSupplier supplier = (srcPool, proxyUser, proxyPassword, remoteAddr, initFuture) -> { initFuture.setSuccess(mockChannel); return mock(ChannelHandler.class); }; Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, - HTTP_PROXY_ADDRESS, REMOTE_ADDRESS, mockHandler, supplier); + HTTP_PROXY_ADDRESS, null, null, REMOTE_ADDRESS, mockHandler, supplier); Future acquireFuture = tunnelPool.acquire(); @@ -186,13 +186,13 @@ public void sslContextProvided_andProxyUsingHttps_addsSslHandler() { when(mockSslEngine.getSSLParameters()).thenReturn(mock(SSLParameters.class)); TestSslContext mockSslCtx = new TestSslContext(mockSslHandler); - Http1TunnelConnectionPool.InitHandlerSupplier supplier = (srcPool, remoteAddr, initFuture) -> { + Http1TunnelConnectionPool.InitHandlerSupplier supplier = (srcPool, proxyUser, proxyPassword, remoteAddr, initFuture) -> { initFuture.setSuccess(mockChannel); return mock(ChannelHandler.class); }; Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, mockSslCtx, - HTTPS_PROXY_ADDRESS, REMOTE_ADDRESS, mockHandler, supplier); + HTTPS_PROXY_ADDRESS, null, null, REMOTE_ADDRESS, mockHandler, supplier); tunnelPool.acquire().awaitUninterruptibly(); @@ -207,13 +207,13 @@ public void sslContextProvided_andProxyNotUsingHttps_doesNotAddSslHandler() { SslHandler mockSslHandler = mock(SslHandler.class); TestSslContext mockSslCtx = new TestSslContext(mockSslHandler); - Http1TunnelConnectionPool.InitHandlerSupplier supplier = (srcPool, remoteAddr, initFuture) -> { + Http1TunnelConnectionPool.InitHandlerSupplier supplier = (srcPool, proxyUser, proxyPassword, remoteAddr, initFuture) -> { initFuture.setSuccess(mockChannel); return mock(ChannelHandler.class); }; Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, mockSslCtx, - HTTP_PROXY_ADDRESS, REMOTE_ADDRESS, mockHandler, supplier); + HTTP_PROXY_ADDRESS, null, null, REMOTE_ADDRESS, mockHandler, supplier); tunnelPool.acquire().awaitUninterruptibly(); diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java index 22f534a85f37..b68b1abb82b9 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java @@ -92,7 +92,7 @@ public void addedToPipeline_addsCodec() { Supplier codecSupplier = () -> codec; when(mockCtx.name()).thenReturn("foo"); - ProxyTunnelInitHandler handler = new ProxyTunnelInitHandler(mockChannelPool, REMOTE_HOST, null, codecSupplier); + ProxyTunnelInitHandler handler = new ProxyTunnelInitHandler(mockChannelPool, null, null, REMOTE_HOST, null, codecSupplier); handler.handlerAdded(mockCtx); verify(mockPipeline).addBefore(eq("foo"), eq(null), eq(codec)); From cf0b939e6b8a999c5ee25b9052644caeb0fe8820 Mon Sep 17 00:00:00 2001 From: Guillermo Priego Date: Tue, 8 Jun 2021 10:04:03 +0200 Subject: [PATCH 2/8] test: test with proxy auth --- .../AwaitCloseChannelPoolMapTest.java | 41 ++++++++++++-- .../Http1TunnelConnectionPoolTest.java | 50 +++++++++++++++++ .../internal/ProxyTunnelInitHandlerTest.java | 54 ++++++++++++------- 3 files changed, 121 insertions(+), 24 deletions(-) diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java index e85e71a56f9d..641015b2af77 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java @@ -24,15 +24,15 @@ import static software.amazon.awssdk.http.SdkHttpConfigurationOption.TLS_KEY_MANAGERS_PROVIDER; import java.net.URI; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.nio.charset.StandardCharsets; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; import com.github.tomakehurst.wiremock.junit.WireMockRule; +import io.netty.util.CharsetUtil; +import org.apache.commons.lang3.CharSetUtils; import org.apache.commons.lang3.RandomStringUtils; import org.junit.After; import org.junit.Rule; @@ -215,6 +215,39 @@ public void usingProxy_noSchemeGiven_defaultsToHttp() { assertThat(requests).contains("CONNECT some-awesome-service:443"); } + @Test + public void usingProxy_withAuth() { + ProxyConfiguration proxyConfiguration = ProxyConfiguration.builder() + .host("localhost") + .port(mockProxy.port()) + .username("myuser") + .password("mypassword") + .build(); + + channelPoolMap = AwaitCloseChannelPoolMap.builder() + .proxyConfiguration(proxyConfiguration) + .sdkChannelOptions(new SdkChannelOptions()) + .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) + .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) + .protocol(Protocol.HTTP1_1) + .maxStreams(100) + .sslProvider(SslProvider.OPENSSL) + .build(); + + SimpleChannelPoolAwareChannelPool simpleChannelPoolAwareChannelPool = channelPoolMap.newPool( + URI.create("https://some-awesome-service:443")); + + simpleChannelPoolAwareChannelPool.acquire().awaitUninterruptibly(); + + String requests = recorder.requests().toString(); + + assertThat(requests).contains("CONNECT some-awesome-service:443"); + + String authB64 = Base64.getEncoder().encodeToString("myuser:mypassword".getBytes(CharsetUtil.UTF_8)); + String authHeaderValue = String.format("Basic %s", authB64); + assertThat(requests).contains(String.format("proxy-authorization: %s", authHeaderValue)); + } + @Test public void usesProvidedKeyManagersProvider() { TlsKeyManagersProvider provider = mock(TlsKeyManagersProvider.class); diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java index 48e3274f8b82..9603fee7fc99 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java @@ -43,6 +43,7 @@ import java.io.IOException; import java.net.URI; import java.util.List; +import java.util.Map; import java.util.concurrent.CountDownLatch; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; @@ -54,6 +55,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.testng.collections.Maps; /** * Unit tests for {@link Http1TunnelConnectionPool}. @@ -68,6 +70,10 @@ public class Http1TunnelConnectionPoolTest { private static final URI REMOTE_ADDRESS = URI.create("https://s3.amazonaws.com:5678"); + private static final String PROXY_USER = "myuser"; + + private static final String PROXY_PASSWORD = "mypassword"; + @Mock private ChannelPool delegatePool; @@ -248,6 +254,50 @@ public void close_closesDelegatePool() { verify(delegatePool).close(); } + @Test + public void proxyAuthProvided_addInitHandler_withAuth(){ + TestInitHandlerData data = new TestInitHandlerData(); + + Http1TunnelConnectionPool.InitHandlerSupplier supplier = (srcPool, proxyUser, proxyPassword, remoteAddr, initFuture) -> { + initFuture.setSuccess(mockChannel); + data.proxyUser(proxyUser); + data.proxyPassword(proxyPassword); + return mock(ChannelHandler.class); + }; + + Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, + HTTP_PROXY_ADDRESS, PROXY_USER, PROXY_PASSWORD, REMOTE_ADDRESS, mockHandler, supplier); + + tunnelPool.acquire().awaitUninterruptibly(); + + assertThat(data.proxyUser()).isEqualTo(PROXY_USER); + assertThat(data.proxyPassword()).isEqualTo(PROXY_PASSWORD); + + } + + private static class TestInitHandlerData { + + private String proxyUser; + private String proxyPassword; + + public void proxyUser(String proxyUser) { + this.proxyUser = proxyUser; + } + + public String proxyUser() { + return this.proxyUser; + } + + public void proxyPassword(String proxyPassword) { + this.proxyPassword = proxyPassword; + } + + public String proxyPassword(){ + return this.proxyPassword; + } + + } + private static class TestSslContext extends SslContext { private final SslHandler handler; diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java index b68b1abb82b9..ee07b6b3c858 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java @@ -15,14 +15,6 @@ package software.amazon.awssdk.http.nio.netty.internal; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; @@ -30,20 +22,11 @@ import io.netty.channel.DefaultChannelPromise; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.pool.ChannelPool; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.DefaultHttpResponse; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.*; import io.netty.handler.ssl.SslCloseCompletionEvent; import io.netty.handler.ssl.SslHandler; +import io.netty.util.CharsetUtil; import io.netty.util.concurrent.Promise; -import java.io.IOException; -import java.net.URI; -import java.util.function.Supplier; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; @@ -52,6 +35,15 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import java.io.IOException; +import java.net.URI; +import java.util.Base64; +import java.util.function.Supplier; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + /** * Unit tests for {@link ProxyTunnelInitHandler}. */ @@ -60,6 +52,8 @@ public class ProxyTunnelInitHandlerTest { private static final NioEventLoopGroup GROUP = new NioEventLoopGroup(1); private static final URI REMOTE_HOST = URI.create("https://s3.amazonaws.com:1234"); + private static final String PROXY_USER = "myuser"; + private static final String PROXY_PASSWORD = "mypassword"; @Mock private ChannelHandlerContext mockCtx; @@ -197,7 +191,7 @@ public void handlerRemoved_removesCodec() { } @Test - public void handledAdded_writesRequest() { + public void handledAdded_writesRequest_withoutAuth() { Promise promise = GROUP.next().newPromise(); ProxyTunnelInitHandler handler = new ProxyTunnelInitHandler(mockChannelPool, REMOTE_HOST, promise); handler.handlerAdded(mockCtx); @@ -213,6 +207,26 @@ public void handledAdded_writesRequest() { assertThat(requestCaptor.getValue()).isEqualTo(expectedRequest); } + @Test + public void handledAdded_writesRequest_withAuth() { + Promise promise = GROUP.next().newPromise(); + ProxyTunnelInitHandler handler = new ProxyTunnelInitHandler(mockChannelPool, PROXY_USER, PROXY_PASSWORD, REMOTE_HOST, promise); + handler.handlerAdded(mockCtx); + + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpRequest.class); + verify(mockChannel).writeAndFlush(requestCaptor.capture()); + + String uri = REMOTE_HOST.getHost() + ":" + REMOTE_HOST.getPort(); + HttpRequest expectedRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.CONNECT, uri, + Unpooled.EMPTY_BUFFER, false); + expectedRequest.headers().add(HttpHeaderNames.HOST, uri); + + String authB64 = Base64.getEncoder().encodeToString(String.format("%s:%s", PROXY_USER, PROXY_PASSWORD).getBytes(CharsetUtil.UTF_8)); + expectedRequest.headers().add(HttpHeaderNames.PROXY_AUTHORIZATION, String.format("Basic %s", authB64)); + + assertThat(requestCaptor.getValue()).isEqualTo(expectedRequest); + } + private void successResponse(ProxyTunnelInitHandler handler) { DefaultHttpResponse resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); handler.channelRead(mockCtx, resp); From 21bb13470f61112f1b2d80244f46110815988e5a Mon Sep 17 00:00:00 2001 From: Guillermo Priego Date: Tue, 8 Jun 2021 12:21:01 +0200 Subject: [PATCH 3/8] doc: add javadoc to public interface and update changelog --- .../next-release/feature-AWSSDKforJavav2-dd0c4ee.json | 6 ++++++ .../awssdk/http/nio/netty/ProxyConfiguration.java | 10 ++++++++++ 2 files changed, 16 insertions(+) create mode 100644 .changes/next-release/feature-AWSSDKforJavav2-dd0c4ee.json diff --git a/.changes/next-release/feature-AWSSDKforJavav2-dd0c4ee.json b/.changes/next-release/feature-AWSSDKforJavav2-dd0c4ee.json new file mode 100644 index 000000000000..0c8bbbb885ac --- /dev/null +++ b/.changes/next-release/feature-AWSSDKforJavav2-dd0c4ee.json @@ -0,0 +1,6 @@ +{ + "category": "AWS SDK for Java v2", + "contributor": "guillepb10", + "type": "feature", + "description": "Add support for autheticated corporate proxies" +} diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java index 7cbb12ea0ec6..70d07cf46af3 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java @@ -166,8 +166,18 @@ public interface Builder extends CopyableBuilder { */ Builder nonProxyHosts(Set nonProxyHosts); + /** + * Set the username used to authenticate with the proxy server. + * @param username The proxy username. + * @return This object for method chaining. + */ Builder username(String username); + /** + * Set the password used to authenticate with the proxy server. + * @param password The proxy username. + * @return This object for method chaining. + */ Builder password(String password); } From b590b58f92938384def9968f5ba5117a2eff95a3 Mon Sep 17 00:00:00 2001 From: Guillermo Priego Date: Wed, 9 Jun 2021 12:15:16 +0200 Subject: [PATCH 4/8] doc: more javadoc --- .../amazon/awssdk/http/nio/netty/ProxyConfiguration.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java index 70d07cf46af3..203d20f248cf 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java @@ -67,10 +67,16 @@ public int port() { return port; } + /** + * @return The proxy username. + */ public String username() { return username; } + /** + * @return The proxy password. + */ public String password() { return password; } From dee2bb477b500ba7a68a0511c7ca4cb307a70c4b Mon Sep 17 00:00:00 2001 From: Guillermo Priego Date: Wed, 7 Jul 2021 09:56:26 +0200 Subject: [PATCH 5/8] fix: fix pr comments --- .../http/nio/netty/ProxyConfiguration.java | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java index 203d20f248cf..af2865a427ba 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java @@ -46,6 +46,10 @@ private ProxyConfiguration(BuilderImpl builder) { this.nonProxyHosts = Collections.unmodifiableSet(builder.nonProxyHosts); } + public static Builder builder() { + return new BuilderImpl(); + } + /** * @return The proxy scheme. */ @@ -112,6 +116,14 @@ public boolean equals(Object o) { return false; } + if (username != null ? !username.equals(that.host) : that.username != null) { + return false; + } + + if (password != null ? !password.equals(that.host) : that.password != null) { + return false; + } + return nonProxyHosts.equals(that.nonProxyHosts); } @@ -122,6 +134,8 @@ public int hashCode() { result = 31 * result + (host != null ? host.hashCode() : 0); result = 31 * result + port; result = 31 * result + nonProxyHosts.hashCode(); + result = 31 * result + (username != null ? username.hashCode() : 0); + result = 31 * result + (password != null ? password.hashCode() : 0); return result; } @@ -130,10 +144,6 @@ public Builder toBuilder() { return new BuilderImpl(this); } - public static Builder builder() { - return new BuilderImpl(); - } - /** * Builder for {@link ProxyConfiguration}. */ @@ -141,6 +151,7 @@ public interface Builder extends CopyableBuilder { /** * Set the hostname of the proxy. + * * @param host The proxy host. * @return This object for method chaining. */ @@ -148,6 +159,7 @@ public interface Builder extends CopyableBuilder { /** * Set the port that the proxy expects connections on. + * * @param port The proxy port. * @return This object for method chaining. */ @@ -173,14 +185,16 @@ public interface Builder extends CopyableBuilder { Builder nonProxyHosts(Set nonProxyHosts); /** - * Set the username used to authenticate with the proxy server. + * Set the username used to authenticate with the proxy username. + * * @param username The proxy username. * @return This object for method chaining. */ Builder username(String username); /** - * Set the password used to authenticate with the proxy server. + * Set the password used to authenticate with the proxy password. + * * @param password The proxy username. * @return This object for method chaining. */ @@ -203,6 +217,8 @@ private BuilderImpl(ProxyConfiguration proxyConfiguration) { this.host = proxyConfiguration.host; this.port = proxyConfiguration.port; this.nonProxyHosts = new HashSet<>(proxyConfiguration.nonProxyHosts); + this.username = proxyConfiguration.username; + this.password = proxyConfiguration.password; } @Override @@ -224,7 +240,6 @@ public Builder port(int port) { } - @Override public Builder nonProxyHosts(Set nonProxyHosts) { if (nonProxyHosts != null) { From 5d35750950eb9ef04084b53a347452839e19bb2a Mon Sep 17 00:00:00 2001 From: Guillermo Priego Date: Wed, 7 Jul 2021 09:58:21 +0200 Subject: [PATCH 6/8] apply codestyle --- .../nio/netty/ProxyConfigurationTest.java | 41 +++--- .../AwaitCloseChannelPoolMapTest.java | 128 +++++++++--------- 2 files changed, 85 insertions(+), 84 deletions(-) diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyConfigurationTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyConfigurationTest.java index 239754f22e21..ff9034f913bd 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyConfigurationTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyConfigurationTest.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.http.nio.netty; import static org.assertj.core.api.Assertions.assertThat; + import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashSet; @@ -47,8 +48,8 @@ public void toBuilder_roundTrip_producesExactCopy() { @Test public void setNonProxyHostsToNull_createsEmptySet() { ProxyConfiguration cfg = ProxyConfiguration.builder() - .nonProxyHosts(null) - .build(); + .nonProxyHosts(null) + .build(); assertThat(cfg.nonProxyHosts()).isEmpty(); } @@ -68,15 +69,15 @@ private ProxyConfiguration allPropertiesSetConfig() { private ProxyConfiguration.Builder setAllPropertiesToRandomValues(ProxyConfiguration.Builder builder) { Stream.of(builder.getClass().getDeclaredMethods()) - .filter(m -> m.getParameterCount() == 1 && m.getReturnType().equals(ProxyConfiguration.Builder.class)) - .forEach(m -> { - try { - m.setAccessible(true); - setRandomValue(builder, m); - } catch (Exception e) { - throw new RuntimeException("Could not create random proxy config", e); - } - }); + .filter(m -> m.getParameterCount() == 1 && m.getReturnType().equals(ProxyConfiguration.Builder.class)) + .forEach(m -> { + try { + m.setAccessible(true); + setRandomValue(builder, m); + } catch (Exception e) { + throw new RuntimeException("Could not create random proxy config", e); + } + }); return builder; } @@ -96,15 +97,15 @@ private void setRandomValue(Object o, Method setter) throws InvocationTargetExce private void verifyAllPropertiesSet(ProxyConfiguration cfg) { boolean hasNullProperty = Stream.of(cfg.getClass().getDeclaredMethods()) - .filter(m -> !m.getReturnType().equals(Void.class) && m.getParameterCount() == 0) - .anyMatch(m -> { - m.setAccessible(true); - try { - return m.invoke(cfg) == null; - } catch (Exception e) { - return true; - } - }); + .filter(m -> !m.getReturnType().equals(Void.class) && m.getParameterCount() == 0) + .anyMatch(m -> { + m.setAccessible(true); + try { + return m.invoke(cfg) == null; + } catch (Exception e) { + return true; + } + }); if (hasNullProperty) { throw new RuntimeException("Given configuration has unset property"); diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java index 641015b2af77..3b72f71be4db 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java @@ -23,26 +23,25 @@ import static software.amazon.awssdk.http.SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS; import static software.amazon.awssdk.http.SdkHttpConfigurationOption.TLS_KEY_MANAGERS_PROVIDER; +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import io.netty.channel.Channel; +import io.netty.channel.pool.ChannelPool; +import io.netty.handler.ssl.SslProvider; +import io.netty.util.CharsetUtil; +import io.netty.util.concurrent.Future; import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.*; +import java.util.ArrayList; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; - -import com.github.tomakehurst.wiremock.junit.WireMockRule; - -import io.netty.util.CharsetUtil; -import org.apache.commons.lang3.CharSetUtils; import org.apache.commons.lang3.RandomStringUtils; import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; - -import io.netty.channel.Channel; -import io.netty.channel.pool.ChannelPool; -import io.netty.handler.ssl.SslProvider; -import io.netty.util.concurrent.Future; import software.amazon.awssdk.http.Protocol; import software.amazon.awssdk.http.TlsKeyManagersProvider; import software.amazon.awssdk.http.nio.netty.ProxyConfiguration; @@ -58,8 +57,8 @@ public class AwaitCloseChannelPoolMapTest { @Rule public WireMockRule mockProxy = new WireMockRule(wireMockConfig() - .dynamicPort() - .networkTrafficListener(recorder)); + .dynamicPort() + .networkTrafficListener(recorder)); @After public void methodTeardown() { @@ -74,20 +73,20 @@ public void methodTeardown() { @Test public void close_underlyingPoolsShouldBeClosed() { channelPoolMap = AwaitCloseChannelPoolMap.builder() - .sdkChannelOptions(new SdkChannelOptions()) - .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) - .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) - .protocol(Protocol.HTTP1_1) - .maxStreams(100) - .sslProvider(SslProvider.OPENSSL) - .build(); + .sdkChannelOptions(new SdkChannelOptions()) + .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) + .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) + .protocol(Protocol.HTTP1_1) + .maxStreams(100) + .sslProvider(SslProvider.OPENSSL) + .build(); int numberOfChannelPools = 5; List channelPools = new ArrayList<>(); for (int i = 0; i < numberOfChannelPools; i++) { channelPools.add( - channelPoolMap.get(URI.create("http://" + RandomStringUtils.randomAlphabetic(2) + i + "localhost:" + numberOfChannelPools))); + channelPoolMap.get(URI.create("http://" + RandomStringUtils.randomAlphabetic(2) + i + "localhost:" + numberOfChannelPools))); } assertThat(channelPoolMap.pools().size()).isEqualTo(numberOfChannelPools); @@ -130,7 +129,7 @@ public void get_usingProxy_callsInjectedBootstrapProviderCorrectly() { new SdkChannelOptions())); URI targetUri = URI.create("https://some-awesome-service-1234.amazonaws.com:8080"); - Map shouldProxyCache = new HashMap<>(); + Map shouldProxyCache = new HashMap<>(); shouldProxyCache.put(targetUri, true); ProxyConfiguration proxyConfiguration = @@ -159,24 +158,25 @@ public void get_usingProxy_callsInjectedBootstrapProviderCorrectly() { public void usingProxy_usesCachedValueWhenPresent() { URI targetUri = URI.create("https://some-awesome-service-1234.amazonaws.com"); - Map shouldProxyCache = new HashMap<>(); + Map shouldProxyCache = new HashMap<>(); shouldProxyCache.put(targetUri, true); ProxyConfiguration proxyConfiguration = ProxyConfiguration.builder() - .host("localhost") - .port(mockProxy.port()) - // Deliberately set the target host as a non-proxy host to see if it will check the cache first - .nonProxyHosts(Stream.of(targetUri.getHost()).collect(Collectors.toSet())) - .build(); + .host("localhost") + .port(mockProxy.port()) + // Deliberately set the target host as a non-proxy host to + // see if it will check the cache first + .nonProxyHosts(Stream.of(targetUri.getHost()).collect(Collectors.toSet())) + .build(); AwaitCloseChannelPoolMap.Builder builder = AwaitCloseChannelPoolMap.builder() - .proxyConfiguration(proxyConfiguration) - .sdkChannelOptions(new SdkChannelOptions()) - .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) - .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) - .protocol(Protocol.HTTP1_1) - .maxStreams(100) - .sslProvider(SslProvider.OPENSSL); + .proxyConfiguration(proxyConfiguration) + .sdkChannelOptions(new SdkChannelOptions()) + .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) + .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) + .protocol(Protocol.HTTP1_1) + .maxStreams(100) + .sslProvider(SslProvider.OPENSSL); channelPoolMap = new AwaitCloseChannelPoolMap(builder, shouldProxyCache, null); @@ -191,22 +191,22 @@ public void usingProxy_usesCachedValueWhenPresent() { @Test public void usingProxy_noSchemeGiven_defaultsToHttp() { ProxyConfiguration proxyConfiguration = ProxyConfiguration.builder() - .host("localhost") - .port(mockProxy.port()) - .build(); + .host("localhost") + .port(mockProxy.port()) + .build(); channelPoolMap = AwaitCloseChannelPoolMap.builder() - .proxyConfiguration(proxyConfiguration) - .sdkChannelOptions(new SdkChannelOptions()) - .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) - .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) - .protocol(Protocol.HTTP1_1) - .maxStreams(100) - .sslProvider(SslProvider.OPENSSL) - .build(); + .proxyConfiguration(proxyConfiguration) + .sdkChannelOptions(new SdkChannelOptions()) + .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) + .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) + .protocol(Protocol.HTTP1_1) + .maxStreams(100) + .sslProvider(SslProvider.OPENSSL) + .build(); SimpleChannelPoolAwareChannelPool simpleChannelPoolAwareChannelPool = channelPoolMap.newPool( - URI.create("https://some-awesome-service:443")); + URI.create("https://some-awesome-service:443")); simpleChannelPoolAwareChannelPool.acquire().awaitUninterruptibly(); @@ -218,24 +218,24 @@ public void usingProxy_noSchemeGiven_defaultsToHttp() { @Test public void usingProxy_withAuth() { ProxyConfiguration proxyConfiguration = ProxyConfiguration.builder() - .host("localhost") - .port(mockProxy.port()) - .username("myuser") - .password("mypassword") - .build(); + .host("localhost") + .port(mockProxy.port()) + .username("myuser") + .password("mypassword") + .build(); channelPoolMap = AwaitCloseChannelPoolMap.builder() - .proxyConfiguration(proxyConfiguration) - .sdkChannelOptions(new SdkChannelOptions()) - .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) - .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) - .protocol(Protocol.HTTP1_1) - .maxStreams(100) - .sslProvider(SslProvider.OPENSSL) - .build(); + .proxyConfiguration(proxyConfiguration) + .sdkChannelOptions(new SdkChannelOptions()) + .sdkEventLoopGroup(SdkEventLoopGroup.builder().build()) + .configuration(new NettyConfiguration(GLOBAL_HTTP_DEFAULTS)) + .protocol(Protocol.HTTP1_1) + .maxStreams(100) + .sslProvider(SslProvider.OPENSSL) + .build(); SimpleChannelPoolAwareChannelPool simpleChannelPoolAwareChannelPool = channelPoolMap.newPool( - URI.create("https://some-awesome-service:443")); + URI.create("https://some-awesome-service:443")); simpleChannelPoolAwareChannelPool.acquire().awaitUninterruptibly(); @@ -253,8 +253,8 @@ public void usesProvidedKeyManagersProvider() { TlsKeyManagersProvider provider = mock(TlsKeyManagersProvider.class); AttributeMap config = AttributeMap.builder() - .put(TLS_KEY_MANAGERS_PROVIDER, provider) - .build(); + .put(TLS_KEY_MANAGERS_PROVIDER, provider) + .build(); channelPoolMap = AwaitCloseChannelPoolMap.builder() .sdkChannelOptions(new SdkChannelOptions()) From ab976fb0641a49055e910d542132081a9c60785d Mon Sep 17 00:00:00 2001 From: Guillermo Priego Date: Fri, 9 Jul 2021 08:13:42 +0200 Subject: [PATCH 7/8] fix: fix doc and equals into dto and codestyle --- .../http/nio/netty/ProxyConfiguration.java | 6 ++-- .../internal/ProxyTunnelInitHandlerTest.java | 31 +++++++++++++------ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java index af2865a427ba..9ac548ca2eba 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java @@ -116,11 +116,11 @@ public boolean equals(Object o) { return false; } - if (username != null ? !username.equals(that.host) : that.username != null) { + if (username != null ? !username.equals(that.username) : that.username != null) { return false; } - if (password != null ? !password.equals(that.host) : that.password != null) { + if (password != null ? !password.equals(that.password) : that.password != null) { return false; } @@ -195,7 +195,7 @@ public interface Builder extends CopyableBuilder { /** * Set the password used to authenticate with the proxy password. * - * @param password The proxy username. + * @param password The proxy password. * @return This object for method chaining. */ Builder password(String password); diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java index ee07b6b3c858..e084beb44109 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java @@ -15,6 +15,15 @@ package software.amazon.awssdk.http.nio.netty.internal; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; @@ -22,11 +31,22 @@ import io.netty.channel.DefaultChannelPromise; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.pool.ChannelPool; -import io.netty.handler.codec.http.*; +import io.netty.handler.codec.http.DefaultFullHttpRequest; +import io.netty.handler.codec.http.DefaultHttpResponse; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.ssl.SslCloseCompletionEvent; import io.netty.handler.ssl.SslHandler; import io.netty.util.CharsetUtil; import io.netty.util.concurrent.Promise; +import java.io.IOException; +import java.net.URI; +import java.util.Base64; +import java.util.function.Supplier; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; @@ -35,15 +55,6 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import java.io.IOException; -import java.net.URI; -import java.util.Base64; -import java.util.function.Supplier; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.*; - /** * Unit tests for {@link ProxyTunnelInitHandler}. */ From 17df7a484fda6cdbaa0e422925ef149c4469a4e6 Mon Sep 17 00:00:00 2001 From: Guillermo Priego Date: Mon, 6 Sep 2021 12:38:33 +0200 Subject: [PATCH 8/8] fix: fix typo and remove use of this into field access --- .changes/next-release/feature-AWSSDKforJavav2-dd0c4ee.json | 2 +- .../http/nio/netty/internal/Http1TunnelConnectionPool.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changes/next-release/feature-AWSSDKforJavav2-dd0c4ee.json b/.changes/next-release/feature-AWSSDKforJavav2-dd0c4ee.json index 0c8bbbb885ac..5a02a806005a 100644 --- a/.changes/next-release/feature-AWSSDKforJavav2-dd0c4ee.json +++ b/.changes/next-release/feature-AWSSDKforJavav2-dd0c4ee.json @@ -2,5 +2,5 @@ "category": "AWS SDK for Java v2", "contributor": "guillepb10", "type": "feature", - "description": "Add support for autheticated corporate proxies" + "description": "Add support for authenticated corporate proxies" } diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java index 245a4e0c3b8c..06280bc5a243 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java @@ -134,7 +134,7 @@ private void setupChannel(Channel ch, Promise acquirePromise) { if (sslHandler != null) { ch.pipeline().addLast(sslHandler); } - ch.pipeline().addLast(initHandlerSupplier.newInitHandler(delegate, this.proxyUser, this.proxyPassword, remoteAddress, + ch.pipeline().addLast(initHandlerSupplier.newInitHandler(delegate, proxyUser, proxyPassword, remoteAddress, tunnelEstablishedPromise)); tunnelEstablishedPromise.addListener((Future f) -> { if (f.isSuccess()) {