From c7b71d4fe635b2ed17ce017141b96921db0ba764 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Tue, 30 May 2017 17:14:26 +0300 Subject: [PATCH 01/10] Adds custom message when there is a problem with upstream server certificate --- .../proxy/impl/ClientToProxyConnection.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java index 32d8d01ec..a1d9dfad6 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java @@ -32,6 +32,7 @@ import org.littleshoot.proxy.ProxyAuthenticator; import org.littleshoot.proxy.SslEngineSource; +import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSession; import java.io.IOException; import java.net.InetSocketAddress; @@ -616,22 +617,22 @@ protected boolean serverConnectionFailed( serverConnection.getRemoteAddress(), lastStateBeforeFailure, cause); - connectionFailedUnrecoverably(initialRequest, serverConnection); + connectionFailedUnrecoverably(initialRequest, serverConnection, cause); return false; } } catch (UnknownHostException uhe) { - connectionFailedUnrecoverably(initialRequest, serverConnection); + connectionFailedUnrecoverably(initialRequest, serverConnection, cause); return false; } } - private void connectionFailedUnrecoverably(HttpRequest initialRequest, ProxyToServerConnection serverConnection) { + private void connectionFailedUnrecoverably(HttpRequest initialRequest, ProxyToServerConnection serverConnection, Throwable cause) { // the connection to the server failed, so disconnect the server and remove the ProxyToServerConnection from the // map of open server connections serverConnection.disconnect(); this.serverConnectionsByHostAndPort.remove(serverConnection.getServerHostAndPort()); - boolean keepAlive = writeBadGateway(initialRequest); + boolean keepAlive = writeBadGateway(initialRequest, cause); if (keepAlive) { become(AWAITING_INITIAL); } else { @@ -1202,9 +1203,17 @@ private void stripHopByHopHeaders(HttpHeaders headers) { * @param httpRequest the HttpRequest that is resulting in the Bad Gateway response * @return true if the connection will be kept open, or false if it will be disconnected */ - private boolean writeBadGateway(HttpRequest httpRequest) { + private boolean writeBadGateway(HttpRequest httpRequest, Throwable cause) { String body = "Bad Gateway: " + httpRequest.getUri(); - FullHttpResponse response = ProxyUtils.createFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_GATEWAY, body); + HttpResponseStatus status = HttpResponseStatus.BAD_GATEWAY; + + if (cause instanceof SSLHandshakeException) { + final String message = "There was a problem with upstream server certificate"; + body = message + ": " + httpRequest.getUri(); + status = new HttpResponseStatus(HttpResponseStatus.BAD_GATEWAY.code(), message); + } + + FullHttpResponse response = ProxyUtils.createFullHttpResponse(HttpVersion.HTTP_1_1, status, body); if (ProxyUtils.isHEAD(httpRequest)) { // don't allow any body content in response to a HEAD request @@ -1214,6 +1223,10 @@ private boolean writeBadGateway(HttpRequest httpRequest) { return respondWithShortCircuitResponse(response); } + private boolean writeBadGateway (HttpRequest httpRequest) { + return writeBadGateway(httpRequest, null); + } + /** * Tells the client that the request was malformed or erroneous. If the Bad Request is a response to * an HTTP HEAD request, the response will contain no body, but the Content-Length header will be set to the From 0895f965d3fb08a4a70cc48ab3e6bd910236b397 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Wed, 31 May 2017 14:20:22 +0300 Subject: [PATCH 02/10] Makes the implementation generic. --- ...BadGatewayFailureHttpResponseComposer.java | 37 ++++++++++++++++++ .../proxy/FailureHttpResponseComposer.java | 9 +++++ .../proxy/HttpProxyServerBootstrap.java | 8 ++++ .../proxy/impl/ClientToProxyConnection.java | 39 ++++--------------- .../proxy/impl/DefaultHttpProxyServer.java | 25 +++++++++++- 5 files changed, 86 insertions(+), 32 deletions(-) create mode 100644 src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java create mode 100644 src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java diff --git a/src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java b/src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java new file mode 100644 index 000000000..3d8f4fd33 --- /dev/null +++ b/src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java @@ -0,0 +1,37 @@ +package org.littleshoot.proxy; + +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; +import org.littleshoot.proxy.impl.ProxyUtils; + + +public final class BadGatewayFailureHttpResponseComposer implements FailureHttpResponseComposer { + + /** + * Tells the client that something went wrong trying to proxy its request. If the Bad Gateway is a response to + * an HTTP HEAD request, the response will contain no body, but the Content-Length header will be set to the + * value it would have been if this 502 Bad Gateway were in response to a GET. + * + * @param httpRequest the HttpRequest that is resulting in the Bad Gateway response + * @param cause raised exception + * @return true if the connection will be kept open, or false if it will be disconnected + */ + @Override + public FullHttpResponse compose(HttpRequest httpRequest, Throwable cause) { + String body = "Bad Gateway: " + httpRequest.getUri(); + + FullHttpResponse response = ProxyUtils.createFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_GATEWAY, body); + + if (ProxyUtils.isHEAD(httpRequest)) { + // don't allow any body content in response to a HEAD request + response.content().clear(); + } + return response; + } + + public FullHttpResponse compose(HttpRequest httpRequest) { + return this.compose(httpRequest, null); + } +} diff --git a/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java b/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java new file mode 100644 index 000000000..9967329a1 --- /dev/null +++ b/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java @@ -0,0 +1,9 @@ +package org.littleshoot.proxy; + + +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; + +public interface FailureHttpResponseComposer { + FullHttpResponse compose(HttpRequest httpRequest, Throwable cause); +} diff --git a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java index 367dc8dd1..858429979 100644 --- a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java +++ b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java @@ -197,6 +197,14 @@ HttpProxyServerBootstrap withManInTheMiddle( HttpProxyServerBootstrap withFiltersSource( HttpFiltersSource filtersSource); + /** + * + * @param unrecoverableFailureHttpResponseComposer + * @return + */ + HttpProxyServerBootstrap withUnrecoverableFailureHttpResponseComposer( + FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer); + /** *

* Specify whether or not to use secure DNS lookups for outbound diff --git a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java index a1d9dfad6..c39814538 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java @@ -25,6 +25,8 @@ import io.netty.util.concurrent.GenericFutureListener; import org.apache.commons.lang3.StringUtils; import org.littleshoot.proxy.ActivityTracker; +import org.littleshoot.proxy.BadGatewayFailureHttpResponseComposer; +import org.littleshoot.proxy.FailureHttpResponseComposer; import org.littleshoot.proxy.FlowContext; import org.littleshoot.proxy.FullFlowContext; import org.littleshoot.proxy.HttpFilters; @@ -32,7 +34,6 @@ import org.littleshoot.proxy.ProxyAuthenticator; import org.littleshoot.proxy.SslEngineSource; -import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSession; import java.io.IOException; import java.net.InetSocketAddress; @@ -632,7 +633,10 @@ private void connectionFailedUnrecoverably(HttpRequest initialRequest, ProxyToSe serverConnection.disconnect(); this.serverConnectionsByHostAndPort.remove(serverConnection.getServerHostAndPort()); - boolean keepAlive = writeBadGateway(initialRequest, cause); + FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = proxyServer.getUnrecoverableFailureHttpResponseComposer(); + FullHttpResponse failureResponse = unrecoverableFailureHttpResponseComposer.compose(initialRequest, cause); + + boolean keepAlive = respondWithShortCircuitResponse(failureResponse); if (keepAlive) { become(AWAITING_INITIAL); } else { @@ -1195,36 +1199,9 @@ private void stripHopByHopHeaders(HttpHeaders headers) { * Miscellaneous **************************************************************************/ - /** - * Tells the client that something went wrong trying to proxy its request. If the Bad Gateway is a response to - * an HTTP HEAD request, the response will contain no body, but the Content-Length header will be set to the - * value it would have been if this 502 Bad Gateway were in response to a GET. - * - * @param httpRequest the HttpRequest that is resulting in the Bad Gateway response - * @return true if the connection will be kept open, or false if it will be disconnected - */ - private boolean writeBadGateway(HttpRequest httpRequest, Throwable cause) { - String body = "Bad Gateway: " + httpRequest.getUri(); - HttpResponseStatus status = HttpResponseStatus.BAD_GATEWAY; - - if (cause instanceof SSLHandshakeException) { - final String message = "There was a problem with upstream server certificate"; - body = message + ": " + httpRequest.getUri(); - status = new HttpResponseStatus(HttpResponseStatus.BAD_GATEWAY.code(), message); - } - - FullHttpResponse response = ProxyUtils.createFullHttpResponse(HttpVersion.HTTP_1_1, status, body); - - if (ProxyUtils.isHEAD(httpRequest)) { - // don't allow any body content in response to a HEAD request - response.content().clear(); - } - - return respondWithShortCircuitResponse(response); - } - private boolean writeBadGateway (HttpRequest httpRequest) { - return writeBadGateway(httpRequest, null); + FullHttpResponse badGatewayResponse = new BadGatewayFailureHttpResponseComposer().compose(httpRequest); + return respondWithShortCircuitResponse(badGatewayResponse); } /** diff --git a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java index 1891532e4..65fe650cd 100644 --- a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java +++ b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java @@ -17,6 +17,7 @@ import io.netty.handler.traffic.GlobalTrafficShapingHandler; import io.netty.util.concurrent.GlobalEventExecutor; import org.littleshoot.proxy.ActivityTracker; +import org.littleshoot.proxy.BadGatewayFailureHttpResponseComposer; import org.littleshoot.proxy.ChainedProxyManager; import org.littleshoot.proxy.DefaultHostResolver; import org.littleshoot.proxy.DnsSecServerResolver; @@ -26,6 +27,7 @@ import org.littleshoot.proxy.HttpFiltersSourceAdapter; import org.littleshoot.proxy.HttpProxyServer; import org.littleshoot.proxy.HttpProxyServerBootstrap; +import org.littleshoot.proxy.FailureHttpResponseComposer; import org.littleshoot.proxy.MitmManager; import org.littleshoot.proxy.ProxyAuthenticator; import org.littleshoot.proxy.SslEngineSource; @@ -108,6 +110,7 @@ public class DefaultHttpProxyServer implements HttpProxyServer { private final ChainedProxyManager chainProxyManager; private final MitmManager mitmManager; private final HttpFiltersSource filtersSource; + private final FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer; private final boolean transparent; private volatile int connectTimeout; private volatile int idleConnectionTimeout; @@ -240,6 +243,7 @@ private DefaultHttpProxyServer(ServerGroup serverGroup, ChainedProxyManager chainProxyManager, MitmManager mitmManager, HttpFiltersSource filtersSource, + FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, boolean transparent, int idleConnectionTimeout, Collection activityTrackers, @@ -262,6 +266,11 @@ private DefaultHttpProxyServer(ServerGroup serverGroup, this.chainProxyManager = chainProxyManager; this.mitmManager = mitmManager; this.filtersSource = filtersSource; + if (unrecoverableFailureHttpResponseComposer == null) { + this.unrecoverableFailureHttpResponseComposer = new BadGatewayFailureHttpResponseComposer(); + } else { + this.unrecoverableFailureHttpResponseComposer = unrecoverableFailureHttpResponseComposer; + } this.transparent = transparent; this.idleConnectionTimeout = idleConnectionTimeout; if (activityTrackers != null) { @@ -396,6 +405,7 @@ public HttpProxyServerBootstrap clone() { chainProxyManager, mitmManager, filtersSource, + unrecoverableFailureHttpResponseComposer, transparent, idleConnectionTimeout, activityTrackers, @@ -581,6 +591,10 @@ public HttpFiltersSource getFiltersSource() { return filtersSource; } + public FailureHttpResponseComposer getUnrecoverableFailureHttpResponseComposer() { + return unrecoverableFailureHttpResponseComposer; + } + protected Collection getActivityTrackers() { return activityTrackers; } @@ -608,6 +622,7 @@ private static class DefaultHttpProxyServerBootstrap implements HttpProxyServerB private ChainedProxyManager chainProxyManager = null; private MitmManager mitmManager = null; private HttpFiltersSource filtersSource = new HttpFiltersSourceAdapter(); + private FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = new BadGatewayFailureHttpResponseComposer(); private boolean transparent = false; private int idleConnectionTimeout = 70; private Collection activityTrackers = new ConcurrentLinkedQueue(); @@ -638,6 +653,7 @@ private DefaultHttpProxyServerBootstrap( ChainedProxyManager chainProxyManager, MitmManager mitmManager, HttpFiltersSource filtersSource, + FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, boolean transparent, int idleConnectionTimeout, Collection activityTrackers, int connectTimeout, HostResolver serverResolver, @@ -659,6 +675,7 @@ private DefaultHttpProxyServerBootstrap( this.chainProxyManager = chainProxyManager; this.mitmManager = mitmManager; this.filtersSource = filtersSource; + this.unrecoverableFailureHttpResponseComposer = unrecoverableFailureHttpResponseComposer; this.transparent = transparent; this.idleConnectionTimeout = idleConnectionTimeout; if (activityTrackers != null) { @@ -797,6 +814,12 @@ public HttpProxyServerBootstrap withFiltersSource( return this; } + public HttpProxyServerBootstrap withUnrecoverableFailureHttpResponseComposer( + FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer) { + this.unrecoverableFailureHttpResponseComposer = unrecoverableFailureHttpResponseComposer; + return this; + } + @Override public HttpProxyServerBootstrap withUseDnsSec(boolean useDnsSec) { if (useDnsSec) { @@ -900,7 +923,7 @@ private DefaultHttpProxyServer build() { transportProtocol, determineListenAddress(), sslEngineSource, authenticateSslClients, proxyAuthenticator, chainProxyManager, mitmManager, - filtersSource, transparent, + filtersSource, unrecoverableFailureHttpResponseComposer, transparent, idleConnectionTimeout, activityTrackers, connectTimeout, serverResolver, readThrottleBytesPerSecond, writeThrottleBytesPerSecond, localAddress, proxyAlias, maxInitialLineLength, maxHeaderSize, maxChunkSize, From f793f47510492ea03c5b09f8bd1a9edb03bb835b Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Wed, 31 May 2017 14:26:47 +0300 Subject: [PATCH 03/10] Renamed interface --- .../BadGatewayFailureHttpResponseComposer.java | 2 +- .../proxy/HttpProxyServerBootstrap.java | 2 +- ...rverConnectionFailureHttpResponseComposer.java} | 2 +- .../proxy/impl/ClientToProxyConnection.java | 4 ++-- .../proxy/impl/DefaultHttpProxyServer.java | 14 +++++++------- 5 files changed, 12 insertions(+), 12 deletions(-) rename src/main/java/org/littleshoot/proxy/{FailureHttpResponseComposer.java => ServerConnectionFailureHttpResponseComposer.java} (76%) diff --git a/src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java b/src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java index 3d8f4fd33..26bcd7814 100644 --- a/src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java +++ b/src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java @@ -7,7 +7,7 @@ import org.littleshoot.proxy.impl.ProxyUtils; -public final class BadGatewayFailureHttpResponseComposer implements FailureHttpResponseComposer { +public final class BadGatewayFailureHttpResponseComposer implements ServerConnectionFailureHttpResponseComposer { /** * Tells the client that something went wrong trying to proxy its request. If the Bad Gateway is a response to diff --git a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java index 858429979..940fbe5fb 100644 --- a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java +++ b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java @@ -203,7 +203,7 @@ HttpProxyServerBootstrap withFiltersSource( * @return */ HttpProxyServerBootstrap withUnrecoverableFailureHttpResponseComposer( - FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer); + ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer); /** *

diff --git a/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java b/src/main/java/org/littleshoot/proxy/ServerConnectionFailureHttpResponseComposer.java similarity index 76% rename from src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java rename to src/main/java/org/littleshoot/proxy/ServerConnectionFailureHttpResponseComposer.java index 9967329a1..effc990d0 100644 --- a/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java +++ b/src/main/java/org/littleshoot/proxy/ServerConnectionFailureHttpResponseComposer.java @@ -4,6 +4,6 @@ import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpRequest; -public interface FailureHttpResponseComposer { +public interface ServerConnectionFailureHttpResponseComposer { FullHttpResponse compose(HttpRequest httpRequest, Throwable cause); } diff --git a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java index c39814538..6478b3956 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java @@ -26,7 +26,7 @@ import org.apache.commons.lang3.StringUtils; import org.littleshoot.proxy.ActivityTracker; import org.littleshoot.proxy.BadGatewayFailureHttpResponseComposer; -import org.littleshoot.proxy.FailureHttpResponseComposer; +import org.littleshoot.proxy.ServerConnectionFailureHttpResponseComposer; import org.littleshoot.proxy.FlowContext; import org.littleshoot.proxy.FullFlowContext; import org.littleshoot.proxy.HttpFilters; @@ -633,7 +633,7 @@ private void connectionFailedUnrecoverably(HttpRequest initialRequest, ProxyToSe serverConnection.disconnect(); this.serverConnectionsByHostAndPort.remove(serverConnection.getServerHostAndPort()); - FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = proxyServer.getUnrecoverableFailureHttpResponseComposer(); + ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = proxyServer.getUnrecoverableFailureHttpResponseComposer(); FullHttpResponse failureResponse = unrecoverableFailureHttpResponseComposer.compose(initialRequest, cause); boolean keepAlive = respondWithShortCircuitResponse(failureResponse); diff --git a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java index 65fe650cd..15b1b04f6 100644 --- a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java +++ b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java @@ -27,7 +27,7 @@ import org.littleshoot.proxy.HttpFiltersSourceAdapter; import org.littleshoot.proxy.HttpProxyServer; import org.littleshoot.proxy.HttpProxyServerBootstrap; -import org.littleshoot.proxy.FailureHttpResponseComposer; +import org.littleshoot.proxy.ServerConnectionFailureHttpResponseComposer; import org.littleshoot.proxy.MitmManager; import org.littleshoot.proxy.ProxyAuthenticator; import org.littleshoot.proxy.SslEngineSource; @@ -110,7 +110,7 @@ public class DefaultHttpProxyServer implements HttpProxyServer { private final ChainedProxyManager chainProxyManager; private final MitmManager mitmManager; private final HttpFiltersSource filtersSource; - private final FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer; + private final ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer; private final boolean transparent; private volatile int connectTimeout; private volatile int idleConnectionTimeout; @@ -243,7 +243,7 @@ private DefaultHttpProxyServer(ServerGroup serverGroup, ChainedProxyManager chainProxyManager, MitmManager mitmManager, HttpFiltersSource filtersSource, - FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, + ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, boolean transparent, int idleConnectionTimeout, Collection activityTrackers, @@ -591,7 +591,7 @@ public HttpFiltersSource getFiltersSource() { return filtersSource; } - public FailureHttpResponseComposer getUnrecoverableFailureHttpResponseComposer() { + public ServerConnectionFailureHttpResponseComposer getUnrecoverableFailureHttpResponseComposer() { return unrecoverableFailureHttpResponseComposer; } @@ -622,7 +622,7 @@ private static class DefaultHttpProxyServerBootstrap implements HttpProxyServerB private ChainedProxyManager chainProxyManager = null; private MitmManager mitmManager = null; private HttpFiltersSource filtersSource = new HttpFiltersSourceAdapter(); - private FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = new BadGatewayFailureHttpResponseComposer(); + private ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = new BadGatewayFailureHttpResponseComposer(); private boolean transparent = false; private int idleConnectionTimeout = 70; private Collection activityTrackers = new ConcurrentLinkedQueue(); @@ -653,7 +653,7 @@ private DefaultHttpProxyServerBootstrap( ChainedProxyManager chainProxyManager, MitmManager mitmManager, HttpFiltersSource filtersSource, - FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, + ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, boolean transparent, int idleConnectionTimeout, Collection activityTrackers, int connectTimeout, HostResolver serverResolver, @@ -815,7 +815,7 @@ public HttpProxyServerBootstrap withFiltersSource( } public HttpProxyServerBootstrap withUnrecoverableFailureHttpResponseComposer( - FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer) { + ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer) { this.unrecoverableFailureHttpResponseComposer = unrecoverableFailureHttpResponseComposer; return this; } From 08295fc8ba0553d079fef28d0541352ff6b55b52 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Wed, 31 May 2017 14:29:08 +0300 Subject: [PATCH 04/10] Removes unnecesssary if statement --- .../org/littleshoot/proxy/impl/DefaultHttpProxyServer.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java index 15b1b04f6..a0f5d3c57 100644 --- a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java +++ b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java @@ -266,11 +266,7 @@ private DefaultHttpProxyServer(ServerGroup serverGroup, this.chainProxyManager = chainProxyManager; this.mitmManager = mitmManager; this.filtersSource = filtersSource; - if (unrecoverableFailureHttpResponseComposer == null) { - this.unrecoverableFailureHttpResponseComposer = new BadGatewayFailureHttpResponseComposer(); - } else { - this.unrecoverableFailureHttpResponseComposer = unrecoverableFailureHttpResponseComposer; - } + this.unrecoverableFailureHttpResponseComposer = unrecoverableFailureHttpResponseComposer; this.transparent = transparent; this.idleConnectionTimeout = idleConnectionTimeout; if (activityTrackers != null) { From bef40d77fd278a97c6d16c826937d63d4264cb73 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Wed, 31 May 2017 18:34:32 +0300 Subject: [PATCH 05/10] Adds tests --- .../impl/DefaultHttpProxyServerTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/test/java/org/littleshoot/proxy/impl/DefaultHttpProxyServerTest.java diff --git a/src/test/java/org/littleshoot/proxy/impl/DefaultHttpProxyServerTest.java b/src/test/java/org/littleshoot/proxy/impl/DefaultHttpProxyServerTest.java new file mode 100644 index 000000000..9a7e3fc91 --- /dev/null +++ b/src/test/java/org/littleshoot/proxy/impl/DefaultHttpProxyServerTest.java @@ -0,0 +1,38 @@ +package org.littleshoot.proxy.impl; + +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import org.junit.Test; +import org.littleshoot.proxy.BadGatewayFailureHttpResponseComposer; +import org.littleshoot.proxy.ServerConnectionFailureHttpResponseComposer; + +import static org.junit.Assert.assertTrue; + +public class DefaultHttpProxyServerTest { + + @Test + public void testDefaultUnrecoverableFailureHttpResponseComposer() { + DefaultHttpProxyServer httpProxyServer = (DefaultHttpProxyServer) DefaultHttpProxyServer.bootstrap().start(); + assertTrue(httpProxyServer.getUnrecoverableFailureHttpResponseComposer() instanceof BadGatewayFailureHttpResponseComposer); + httpProxyServer.stop(); + } + + @Test + public void testCustomUnrecoverableFailureHttpResponseComposer() { + + class CustomUnrecoverableFailureHttpResponseComposer implements ServerConnectionFailureHttpResponseComposer { + @Override + public FullHttpResponse compose(HttpRequest httpRequest, Throwable cause) { + return null; + } + } + + DefaultHttpProxyServer httpProxyServer = (DefaultHttpProxyServer) DefaultHttpProxyServer + .bootstrap() + .withUnrecoverableFailureHttpResponseComposer(new CustomUnrecoverableFailureHttpResponseComposer()) + .start(); + assertTrue(httpProxyServer.getUnrecoverableFailureHttpResponseComposer() instanceof CustomUnrecoverableFailureHttpResponseComposer); + httpProxyServer.stop(); + } + +} \ No newline at end of file From 05fcfca4feaa774caea239d718cc580ac9443eb3 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Thu, 1 Jun 2017 14:03:29 +0300 Subject: [PATCH 06/10] Addresses code review comments --- ...BadGatewayFailureHttpResponseComposer.java | 15 ++++-- .../proxy/FailureHttpResponseComposer.java | 18 +++++++ .../proxy/HttpProxyServerBootstrap.java | 12 ++++- ...ConnectionFailureHttpResponseComposer.java | 9 ---- .../proxy/impl/ClientToProxyConnection.java | 16 ++++-- .../proxy/impl/DefaultHttpProxyServer.java | 14 +++--- ...atewayFailureHttpResponseComposerTest.java | 49 +++++++++++++++++++ .../impl/DefaultHttpProxyServerTest.java | 4 +- 8 files changed, 108 insertions(+), 29 deletions(-) create mode 100644 src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java delete mode 100644 src/main/java/org/littleshoot/proxy/ServerConnectionFailureHttpResponseComposer.java create mode 100644 src/test/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposerTest.java diff --git a/src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java b/src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java index 26bcd7814..f115332cb 100644 --- a/src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java +++ b/src/main/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposer.java @@ -6,8 +6,7 @@ import io.netty.handler.codec.http.HttpVersion; import org.littleshoot.proxy.impl.ProxyUtils; - -public final class BadGatewayFailureHttpResponseComposer implements ServerConnectionFailureHttpResponseComposer { +public class BadGatewayFailureHttpResponseComposer implements FailureHttpResponseComposer { /** * Tells the client that something went wrong trying to proxy its request. If the Bad Gateway is a response to @@ -20,7 +19,7 @@ public final class BadGatewayFailureHttpResponseComposer implements ServerConnec */ @Override public FullHttpResponse compose(HttpRequest httpRequest, Throwable cause) { - String body = "Bad Gateway: " + httpRequest.getUri(); + String body = provideCustomMessage(httpRequest, cause); FullHttpResponse response = ProxyUtils.createFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_GATEWAY, body); @@ -31,7 +30,13 @@ public FullHttpResponse compose(HttpRequest httpRequest, Throwable cause) { return response; } - public FullHttpResponse compose(HttpRequest httpRequest) { - return this.compose(httpRequest, null); + /** + * The method can be overridden to provide a custom message along with 502 code + * @param httpRequest initial request + * @param cause an exception thrown on a failure + * @return custom message + */ + protected String provideCustomMessage(HttpRequest httpRequest, Throwable cause) { + return "Bad Gateway: " + httpRequest.getUri(); } } diff --git a/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java b/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java new file mode 100644 index 000000000..54e1e40fa --- /dev/null +++ b/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java @@ -0,0 +1,18 @@ +package org.littleshoot.proxy; + +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; + +/** + * Interface for objects that can provide a custom http response on a specific failure. + */ +public interface FailureHttpResponseComposer { + + /** + * Creates an {@link FullHttpResponse} based on initial request and failure cause + * @param httpRequest initial request + * @param cause an exception thrown during a failure + * @return failure http response + */ + FullHttpResponse compose(HttpRequest httpRequest, Throwable cause); +} diff --git a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java index 940fbe5fb..3993d420d 100644 --- a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java +++ b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java @@ -198,12 +198,20 @@ HttpProxyServerBootstrap withFiltersSource( HttpFiltersSource filtersSource); /** + *

+ * Specify a {@link FailureHttpResponseComposer} to use for composing + * custom response message on unrecoverable failure + *

+ * + *

+ * Default = {@link BadGatewayFailureHttpResponseComposer} + *

* - * @param unrecoverableFailureHttpResponseComposer + * @param unrecoverableFailureHttpResponseComposer custom response message composer * @return */ HttpProxyServerBootstrap withUnrecoverableFailureHttpResponseComposer( - ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer); + FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer); /** *

diff --git a/src/main/java/org/littleshoot/proxy/ServerConnectionFailureHttpResponseComposer.java b/src/main/java/org/littleshoot/proxy/ServerConnectionFailureHttpResponseComposer.java deleted file mode 100644 index effc990d0..000000000 --- a/src/main/java/org/littleshoot/proxy/ServerConnectionFailureHttpResponseComposer.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.littleshoot.proxy; - - -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpRequest; - -public interface ServerConnectionFailureHttpResponseComposer { - FullHttpResponse compose(HttpRequest httpRequest, Throwable cause); -} diff --git a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java index 6478b3956..8bf49b107 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ClientToProxyConnection.java @@ -26,7 +26,7 @@ import org.apache.commons.lang3.StringUtils; import org.littleshoot.proxy.ActivityTracker; import org.littleshoot.proxy.BadGatewayFailureHttpResponseComposer; -import org.littleshoot.proxy.ServerConnectionFailureHttpResponseComposer; +import org.littleshoot.proxy.FailureHttpResponseComposer; import org.littleshoot.proxy.FlowContext; import org.littleshoot.proxy.FullFlowContext; import org.littleshoot.proxy.HttpFilters; @@ -633,7 +633,7 @@ private void connectionFailedUnrecoverably(HttpRequest initialRequest, ProxyToSe serverConnection.disconnect(); this.serverConnectionsByHostAndPort.remove(serverConnection.getServerHostAndPort()); - ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = proxyServer.getUnrecoverableFailureHttpResponseComposer(); + FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = proxyServer.getUnrecoverableFailureHttpResponseComposer(); FullHttpResponse failureResponse = unrecoverableFailureHttpResponseComposer.compose(initialRequest, cause); boolean keepAlive = respondWithShortCircuitResponse(failureResponse); @@ -1199,8 +1199,16 @@ private void stripHopByHopHeaders(HttpHeaders headers) { * Miscellaneous **************************************************************************/ - private boolean writeBadGateway (HttpRequest httpRequest) { - FullHttpResponse badGatewayResponse = new BadGatewayFailureHttpResponseComposer().compose(httpRequest); + /** + * Tells the client that something went wrong trying to proxy its request. If the Bad Gateway is a response to + * an HTTP HEAD request, the response will contain no body, but the Content-Length header will be set to the + * value it would have been if this 502 Bad Gateway were in response to a GET. + * + * @param httpRequest the HttpRequest that is resulting in the Bad Gateway response + * @return true if the connection will be kept open, or false if it will be disconnected + */ + private boolean writeBadGateway(HttpRequest httpRequest) { + FullHttpResponse badGatewayResponse = new BadGatewayFailureHttpResponseComposer().compose(httpRequest, null); return respondWithShortCircuitResponse(badGatewayResponse); } diff --git a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java index a0f5d3c57..72d3c4a26 100644 --- a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java +++ b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java @@ -27,7 +27,7 @@ import org.littleshoot.proxy.HttpFiltersSourceAdapter; import org.littleshoot.proxy.HttpProxyServer; import org.littleshoot.proxy.HttpProxyServerBootstrap; -import org.littleshoot.proxy.ServerConnectionFailureHttpResponseComposer; +import org.littleshoot.proxy.FailureHttpResponseComposer; import org.littleshoot.proxy.MitmManager; import org.littleshoot.proxy.ProxyAuthenticator; import org.littleshoot.proxy.SslEngineSource; @@ -110,7 +110,7 @@ public class DefaultHttpProxyServer implements HttpProxyServer { private final ChainedProxyManager chainProxyManager; private final MitmManager mitmManager; private final HttpFiltersSource filtersSource; - private final ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer; + private final FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer; private final boolean transparent; private volatile int connectTimeout; private volatile int idleConnectionTimeout; @@ -243,7 +243,7 @@ private DefaultHttpProxyServer(ServerGroup serverGroup, ChainedProxyManager chainProxyManager, MitmManager mitmManager, HttpFiltersSource filtersSource, - ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, + FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, boolean transparent, int idleConnectionTimeout, Collection activityTrackers, @@ -587,7 +587,7 @@ public HttpFiltersSource getFiltersSource() { return filtersSource; } - public ServerConnectionFailureHttpResponseComposer getUnrecoverableFailureHttpResponseComposer() { + public FailureHttpResponseComposer getUnrecoverableFailureHttpResponseComposer() { return unrecoverableFailureHttpResponseComposer; } @@ -618,7 +618,7 @@ private static class DefaultHttpProxyServerBootstrap implements HttpProxyServerB private ChainedProxyManager chainProxyManager = null; private MitmManager mitmManager = null; private HttpFiltersSource filtersSource = new HttpFiltersSourceAdapter(); - private ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = new BadGatewayFailureHttpResponseComposer(); + private FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = new BadGatewayFailureHttpResponseComposer(); private boolean transparent = false; private int idleConnectionTimeout = 70; private Collection activityTrackers = new ConcurrentLinkedQueue(); @@ -649,7 +649,7 @@ private DefaultHttpProxyServerBootstrap( ChainedProxyManager chainProxyManager, MitmManager mitmManager, HttpFiltersSource filtersSource, - ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, + FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer, boolean transparent, int idleConnectionTimeout, Collection activityTrackers, int connectTimeout, HostResolver serverResolver, @@ -811,7 +811,7 @@ public HttpProxyServerBootstrap withFiltersSource( } public HttpProxyServerBootstrap withUnrecoverableFailureHttpResponseComposer( - ServerConnectionFailureHttpResponseComposer unrecoverableFailureHttpResponseComposer) { + FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer) { this.unrecoverableFailureHttpResponseComposer = unrecoverableFailureHttpResponseComposer; return this; } diff --git a/src/test/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposerTest.java b/src/test/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposerTest.java new file mode 100644 index 000000000..da5325122 --- /dev/null +++ b/src/test/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposerTest.java @@ -0,0 +1,49 @@ +package org.littleshoot.proxy; + +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpRequest; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class BadGatewayFailureHttpResponseComposerTest { + + private static final String REQUEST_URI = "https://localhost/hi"; + + @Test + public void testDefault() throws IOException { + FailureHttpResponseComposer badGatewayResponseComposer = new BadGatewayFailureHttpResponseComposer(); + + HttpRequest initialRequest = mock(HttpRequest.class); + when(initialRequest.getUri()).thenReturn(REQUEST_URI); + + FullHttpResponse response = badGatewayResponseComposer.compose(initialRequest, new RuntimeException()); + + assertEquals(502, response.getStatus().code()); + assertEquals("Bad Gateway", response.getStatus().reasonPhrase()); + assertEquals("Bad Gateway: " + REQUEST_URI, new String(response.content().array())); + } + + @Test + public void testCustomMessage() throws IOException { + FailureHttpResponseComposer badGatewayResponseComposer = new BadGatewayFailureHttpResponseComposer() { + @Override + protected String provideCustomMessage(HttpRequest httpRequest, Throwable cause) { + return "Invalid certificate: " + httpRequest.getUri(); + } + }; + + HttpRequest initialRequest = mock(HttpRequest.class); + when(initialRequest.getUri()).thenReturn(REQUEST_URI); + + FullHttpResponse response = badGatewayResponseComposer.compose(initialRequest, new RuntimeException()); + + assertEquals(502, response.getStatus().code()); + assertEquals("Bad Gateway", response.getStatus().reasonPhrase()); + assertEquals("Invalid certificate: " + REQUEST_URI, new String(response.content().array())); + } + +} \ No newline at end of file diff --git a/src/test/java/org/littleshoot/proxy/impl/DefaultHttpProxyServerTest.java b/src/test/java/org/littleshoot/proxy/impl/DefaultHttpProxyServerTest.java index 9a7e3fc91..eb370fc51 100644 --- a/src/test/java/org/littleshoot/proxy/impl/DefaultHttpProxyServerTest.java +++ b/src/test/java/org/littleshoot/proxy/impl/DefaultHttpProxyServerTest.java @@ -4,7 +4,7 @@ import io.netty.handler.codec.http.HttpRequest; import org.junit.Test; import org.littleshoot.proxy.BadGatewayFailureHttpResponseComposer; -import org.littleshoot.proxy.ServerConnectionFailureHttpResponseComposer; +import org.littleshoot.proxy.FailureHttpResponseComposer; import static org.junit.Assert.assertTrue; @@ -20,7 +20,7 @@ public void testDefaultUnrecoverableFailureHttpResponseComposer() { @Test public void testCustomUnrecoverableFailureHttpResponseComposer() { - class CustomUnrecoverableFailureHttpResponseComposer implements ServerConnectionFailureHttpResponseComposer { + class CustomUnrecoverableFailureHttpResponseComposer implements FailureHttpResponseComposer { @Override public FullHttpResponse compose(HttpRequest httpRequest, Throwable cause) { return null; From 48c70b8fc7babd1842ea1c924de7735fe7f48543 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Thu, 1 Jun 2017 14:58:55 +0300 Subject: [PATCH 07/10] trigger build --- .../java/org/littleshoot/proxy/FailureHttpResponseComposer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java b/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java index 54e1e40fa..98257c87c 100644 --- a/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java +++ b/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java @@ -12,7 +12,7 @@ public interface FailureHttpResponseComposer { * Creates an {@link FullHttpResponse} based on initial request and failure cause * @param httpRequest initial request * @param cause an exception thrown during a failure - * @return failure http response + * @return failure http response */ FullHttpResponse compose(HttpRequest httpRequest, Throwable cause); } From 5cb5124cd10c1da2dcfdabb49dd2c6a39827ac99 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Thu, 1 Jun 2017 15:09:46 +0300 Subject: [PATCH 08/10] trigger build 2 --- .../java/org/littleshoot/proxy/FailureHttpResponseComposer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java b/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java index 98257c87c..54e1e40fa 100644 --- a/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java +++ b/src/main/java/org/littleshoot/proxy/FailureHttpResponseComposer.java @@ -12,7 +12,7 @@ public interface FailureHttpResponseComposer { * Creates an {@link FullHttpResponse} based on initial request and failure cause * @param httpRequest initial request * @param cause an exception thrown during a failure - * @return failure http response + * @return failure http response */ FullHttpResponse compose(HttpRequest httpRequest, Throwable cause); } From 0790a6fa41ef757ceb92e1bafd2783f38894e9a6 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Thu, 1 Jun 2017 16:14:10 +0300 Subject: [PATCH 09/10] Adds clear content on head request test --- ...atewayFailureHttpResponseComposerTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/test/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposerTest.java b/src/test/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposerTest.java index da5325122..8a7333e0c 100644 --- a/src/test/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposerTest.java +++ b/src/test/java/org/littleshoot/proxy/BadGatewayFailureHttpResponseComposerTest.java @@ -1,6 +1,7 @@ package org.littleshoot.proxy; import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpRequest; import org.junit.Test; @@ -46,4 +47,28 @@ protected String provideCustomMessage(HttpRequest httpRequest, Throwable cause) assertEquals("Invalid certificate: " + REQUEST_URI, new String(response.content().array())); } + @Test + public void testClearedContent() throws IOException { + FailureHttpResponseComposer badGatewayResponseComposer = new BadGatewayFailureHttpResponseComposer(); + + HttpRequest initialRequest = mock(HttpRequest.class); + when(initialRequest.getUri()).thenReturn(REQUEST_URI); + + FullHttpResponse response = badGatewayResponseComposer.compose(initialRequest, new RuntimeException()); + + assertEquals(502, response.getStatus().code()); + + assertEquals(0, response.content().readerIndex()); + assertNotEquals(0, response.content().writerIndex()); + + when(initialRequest.getMethod()).thenReturn(HttpMethod.HEAD); + + response = badGatewayResponseComposer.compose(initialRequest, new RuntimeException()); + + assertEquals(502, response.getStatus().code()); + + assertEquals(0, response.content().readerIndex()); + assertEquals(0, response.content().writerIndex()); + } + } \ No newline at end of file From a3978a67c6ca062b882c719995849ba58bbc6393 Mon Sep 17 00:00:00 2001 From: Slava Fomin Date: Thu, 1 Jun 2017 19:23:01 +0300 Subject: [PATCH 10/10] Added minor version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 09c407e29..52691c1c9 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.littleshoot littleproxy jar - 1.1.3-VGS-SNAPSHOT + 1.1.3.1-VGS-SNAPSHOT LittleProxy LittleProxy is a high performance HTTP proxy written in Java and using the Netty networking framework.