Skip to content
This repository was archived by the owner on Feb 24, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import io.netty.handler.codec.http.HttpVersion;
import org.littleshoot.proxy.impl.ProxyUtils;

public class BadGatewayFailureHttpResponseComposer implements FailureHttpResponseComposer {
public class DefaultFailureHttpResponseComposer implements FailureHttpResponseComposer {

/**
* Tells the client that something went wrong trying to proxy its request. If the Bad Gateway is a response to
Expand All @@ -20,8 +20,9 @@ public class BadGatewayFailureHttpResponseComposer implements FailureHttpRespons
@Override
public FullHttpResponse compose(HttpRequest httpRequest, Throwable cause) {
String body = provideCustomMessage(httpRequest, cause);
HttpResponseStatus status = provideCustomStatus(httpRequest, cause);

FullHttpResponse response = ProxyUtils.createFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_GATEWAY, body);
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
Expand All @@ -39,4 +40,8 @@ public FullHttpResponse compose(HttpRequest httpRequest, Throwable cause) {
protected String provideCustomMessage(HttpRequest httpRequest, Throwable cause) {
return "Bad Gateway: " + httpRequest.getUri();
}

protected HttpResponseStatus provideCustomStatus(HttpRequest httpRequest, Throwable cause) {
return HttpResponseStatus.BAD_GATEWAY;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ HttpProxyServerBootstrap withFiltersSource(
* </p>
*
* <p>
* Default = {@link BadGatewayFailureHttpResponseComposer}
* Default = {@link DefaultFailureHttpResponseComposer}
* </p>
*
* @param unrecoverableFailureHttpResponseComposer custom response message composer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
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.DefaultFailureHttpResponseComposer;
import org.littleshoot.proxy.ExceptionHandler;
import org.littleshoot.proxy.FailureHttpResponseComposer;
import org.littleshoot.proxy.FlowContext;
Expand Down Expand Up @@ -1215,7 +1215,7 @@ private void stripHopByHopHeaders(HttpHeaders headers) {
* @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);
FullHttpResponse badGatewayResponse = new DefaultFailureHttpResponseComposer().compose(httpRequest, null);
return respondWithShortCircuitResponse(badGatewayResponse);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +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.DefaultFailureHttpResponseComposer;
import org.littleshoot.proxy.ChainedProxyManager;
import org.littleshoot.proxy.DefaultHostResolver;
import org.littleshoot.proxy.DnsSecServerResolver;
Expand Down Expand Up @@ -641,7 +641,7 @@ private static class DefaultHttpProxyServerBootstrap implements HttpProxyServerB
private ExceptionHandler clientToProxyExHandler = null;
private ExceptionHandler proxyToServerExHandler = null;
private HttpFiltersSource filtersSource = new HttpFiltersSourceAdapter();
private FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = new BadGatewayFailureHttpResponseComposer();
private FailureHttpResponseComposer unrecoverableFailureHttpResponseComposer = new DefaultFailureHttpResponseComposer();
private boolean transparent = false;
private int idleConnectionTimeout = 70;
private Collection<ActivityTracker> activityTrackers = new ConcurrentLinkedQueue<ActivityTracker>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.junit.Test;

import java.io.IOException;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

public class BadGatewayFailureHttpResponseComposerTest {
public class DefaultFailureHttpResponseComposerTest {

private static final String REQUEST_URI = "https://localhost/hi";

@Test
public void testDefault() throws IOException {
FailureHttpResponseComposer badGatewayResponseComposer = new BadGatewayFailureHttpResponseComposer();
FailureHttpResponseComposer badGatewayResponseComposer = new DefaultFailureHttpResponseComposer();

HttpRequest initialRequest = mock(HttpRequest.class);
when(initialRequest.getUri()).thenReturn(REQUEST_URI);
Expand All @@ -29,27 +30,32 @@ public void testDefault() throws IOException {
}

@Test
public void testCustomMessage() throws IOException {
FailureHttpResponseComposer badGatewayResponseComposer = new BadGatewayFailureHttpResponseComposer() {
public void testCustomMessageAndStatus() throws IOException {
FailureHttpResponseComposer badGatewayResponseComposer = new DefaultFailureHttpResponseComposer() {
@Override
protected String provideCustomMessage(HttpRequest httpRequest, Throwable cause) {
return "Invalid certificate: " + httpRequest.getUri();
}

@Override
protected HttpResponseStatus provideCustomStatus(HttpRequest httpRequest, Throwable cause) {
return new HttpResponseStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR.code(), "Something is wrong");
}
};

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(500, response.getStatus().code());
assertEquals("Something is wrong", response.getStatus().reasonPhrase());
assertEquals("Invalid certificate: " + REQUEST_URI, new String(response.content().array()));
}

@Test
public void testClearedContent() throws IOException {
FailureHttpResponseComposer badGatewayResponseComposer = new BadGatewayFailureHttpResponseComposer();
FailureHttpResponseComposer badGatewayResponseComposer = new DefaultFailureHttpResponseComposer();

HttpRequest initialRequest = mock(HttpRequest.class);
when(initialRequest.getUri()).thenReturn(REQUEST_URI);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
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.DefaultFailureHttpResponseComposer;
import org.littleshoot.proxy.FailureHttpResponseComposer;

import static org.junit.Assert.assertTrue;
Expand All @@ -13,7 +13,7 @@ public class DefaultHttpProxyServerTest {
@Test
public void testDefaultUnrecoverableFailureHttpResponseComposer() {
DefaultHttpProxyServer httpProxyServer = (DefaultHttpProxyServer) DefaultHttpProxyServer.bootstrap().start();
assertTrue(httpProxyServer.getUnrecoverableFailureHttpResponseComposer() instanceof BadGatewayFailureHttpResponseComposer);
assertTrue(httpProxyServer.getUnrecoverableFailureHttpResponseComposer() instanceof DefaultFailureHttpResponseComposer);
httpProxyServer.stop();
}

Expand Down