diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
index 3e20cece188a..f43ddfecfaba 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
@@ -461,13 +461,17 @@ public void customize(Connector connector, HttpConfiguration config, Request req
// Do a single pass through the header fields as it is a more efficient single iteration.
Forwarded forwarded = new Forwarded(request, config);
+ boolean match = false;
for (HttpField field : httpFields)
{
try
{
MethodHandle handle = _handles.get(field.getName());
if (handle != null)
+ {
+ match = true;
handle.invoke(forwarded, field);
+ }
}
catch (Throwable t)
{
@@ -475,67 +479,64 @@ public void customize(Connector connector, HttpConfiguration config, Request req
}
}
- String proto = "http";
-
- // Is secure status configured from headers?
- if (forwarded.isSecure())
+ if (match)
{
- // set default to https
- proto = config.getSecureScheme();
- }
+ // Is secure status configured from headers?
+ if (forwarded.isSecure())
+ {
+ request.setSecure(true);
+ }
- // Set Scheme from configured protocol
- if (forwarded._proto != null)
- {
- proto = forwarded._proto;
- request.setScheme(proto);
- }
+ // Set Scheme from configured protocol
+ if (forwarded._proto != null)
+ {
+ request.setScheme(forwarded._proto);
+ }
+ // Set scheme if header implies secure scheme is to be used (see #isSslIsSecure())
+ else if (forwarded._secureScheme)
+ {
+ request.setScheme(config.getSecureScheme());
+ }
- // Set authority
- String host = null;
- int port = -1;
+ // Use authority from headers, if configured.
+ if (forwarded._authority != null)
+ {
+ String host = forwarded._authority._host;
+ int port = forwarded._authority._port;
- // Use authority from headers, if configured.
- if (forwarded._authority != null)
- {
- host = forwarded._authority._host;
- port = forwarded._authority._port;
- }
+ HttpURI requestURI = request.getMetaData().getURI();
- // Fall back to request metadata if needed.
- HttpURI requestURI = request.getMetaData().getURI();
- if (host == null)
- {
- host = requestURI.getHost();
- }
- if (port == MutableHostPort.UNSET) // is unset by headers
- {
- port = requestURI.getPort();
- }
- // Don't change port if port == IMPLIED.
+ if (requestURI != null)
+ {
+ // Fall back to request metadata if needed.
+ if (host == null)
+ {
+ host = requestURI.getHost();
+ }
- // Update authority if different from metadata
- if (!host.equalsIgnoreCase(requestURI.getHost()) ||
- port != requestURI.getPort())
- {
- httpFields.put(new HostPortHttpField(host, port));
- request.setAuthority(host, port);
- }
+ if (port == MutableHostPort.UNSET) // is unset by headers
+ {
+ port = requestURI.getPort();
+ }
- // Set secure status
- if (forwarded.isSecure() ||
- proto.equalsIgnoreCase(config.getSecureScheme()) ||
- port == getSecurePort(config))
- {
- request.setSecure(true);
- request.setScheme(proto);
- }
+ // Don't change port if port == IMPLIED.
- // Set Remote Address
- if (forwarded.hasFor())
- {
- int forPort = forwarded._for._port > 0 ? forwarded._for._port : request.getRemotePort();
- request.setRemoteAddr(InetSocketAddress.createUnresolved(forwarded._for._host, forPort));
+ // Update authority if different from metadata
+ if (!host.equalsIgnoreCase(requestURI.getHost()) ||
+ port != requestURI.getPort())
+ {
+ httpFields.put(new HostPortHttpField(host, port));
+ request.setAuthority(host, port);
+ }
+ }
+ }
+
+ // Set Remote Address
+ if (forwarded.hasFor())
+ {
+ int forPort = forwarded._for._port > 0 ? forwarded._for._port : request.getRemotePort();
+ request.setRemoteAddr(InetSocketAddress.createUnresolved(forwarded._for._host, forPort));
+ }
}
}
@@ -744,6 +745,7 @@ private class Forwarded extends QuotedCSVParser
String _proto;
Source _protoSource = Source.UNSET;
Boolean _secure;
+ boolean _secureScheme = false;
public Forwarded(Request request, HttpConfiguration config)
{
@@ -787,40 +789,58 @@ private MutableHostPort getFor()
return _for;
}
- @SuppressWarnings("unused")
+ /**
+ * Called if header is Proxy-auth-cert
+ */
public void handleCipherSuite(HttpField field)
{
_request.setAttribute("javax.servlet.request.cipher_suite", field.getValue());
+
+ // Is ForwardingRequestCustomizer configured to trigger isSecure and scheme change on this header?
if (isSslIsSecure())
{
_secure = true;
+ // track desire for secure scheme, actual protocol will be resolved later.
+ _secureScheme = true;
}
}
- @SuppressWarnings("unused")
+ /**
+ * Called if header is Proxy-Ssl-Id
+ */
public void handleSslSessionId(HttpField field)
{
_request.setAttribute("javax.servlet.request.ssl_session_id", field.getValue());
+
+ // Is ForwardingRequestCustomizer configured to trigger isSecure and scheme change on this header?
if (isSslIsSecure())
{
_secure = true;
+ // track desire for secure scheme, actual protocol will be resolved later.
+ _secureScheme = true;
}
}
- @SuppressWarnings("unused")
+ /**
+ * Called if header is X-Forwarded-Host
+ */
public void handleForwardedHost(HttpField field)
{
updateAuthority(getLeftMost(field.getValue()), Source.XFORWARDED_HOST);
}
- @SuppressWarnings("unused")
+ /**
+ * Called if header is X-Forwarded-For
+ */
public void handleForwardedFor(HttpField field)
{
HostPort hostField = new HostPort(getLeftMost(field.getValue()));
getFor().setHostPort(hostField, Source.XFORWARDED_FOR);
}
- @SuppressWarnings("unused")
+ /**
+ * Called if header is X-Forwarded-Server
+ */
public void handleForwardedServer(HttpField field)
{
if (getProxyAsAuthority())
@@ -828,7 +848,9 @@ public void handleForwardedServer(HttpField field)
updateAuthority(getLeftMost(field.getValue()), Source.XFORWARDED_SERVER);
}
- @SuppressWarnings("unused")
+ /**
+ * Called if header is X-Forwarded-Port
+ */
public void handleForwardedPort(HttpField field)
{
int port = HostPort.parsePort(getLeftMost(field.getValue()));
@@ -836,13 +858,17 @@ public void handleForwardedPort(HttpField field)
updatePort(port, Source.XFORWARDED_PORT);
}
- @SuppressWarnings("unused")
+ /**
+ * Called if header is X-Forwarded-Proto
+ */
public void handleProto(HttpField field)
{
updateProto(getLeftMost(field.getValue()), Source.XFORWARDED_PROTO);
}
- @SuppressWarnings("unused")
+ /**
+ * Called if header is X-Proxied-Https
+ */
public void handleHttps(HttpField field)
{
if ("on".equalsIgnoreCase(field.getValue()) || "true".equalsIgnoreCase(field.getValue()))
@@ -851,9 +877,21 @@ public void handleHttps(HttpField field)
updateProto(HttpScheme.HTTPS.asString(), Source.XPROXIED_HTTPS);
updatePort(getSecurePort(_config), Source.XPROXIED_HTTPS);
}
+ else if ("off".equalsIgnoreCase(field.getValue()) || "false".equalsIgnoreCase(field.getValue()))
+ {
+ _secure = false;
+ updateProto(HttpScheme.HTTP.asString(), Source.XPROXIED_HTTPS);
+ updatePort(MutableHostPort.IMPLIED, Source.XPROXIED_HTTPS);
+ }
+ else
+ {
+ throw new BadMessageException("Invalid value for " + field.getName());
+ }
}
- @SuppressWarnings("unused")
+ /**
+ * Called if header is Forwarded
+ */
public void handleRFC7239(HttpField field)
{
addValue(field.getValue());
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java
index d425e894c16f..b5e90fad16ec 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java
@@ -32,7 +32,6 @@
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -135,6 +134,51 @@ public void destroy() throws Exception
public static Stream cases()
{
return Stream.of(
+ // HTTP 1.0
+ Arguments.of(
+ new Request("HTTP/1.0 - no Host header")
+ .headers(
+ "GET /example HTTP/1.0"
+ ),
+ new Expectations()
+ .scheme("http").serverName("0.0.0.0").serverPort(80)
+ .secure(false)
+ .requestURL("http://0.0.0.0/example")
+ ),
+ Arguments.of(
+ new Request("HTTP/1.0 - Empty Host header")
+ .headers(
+ "GET /example HTTP/1.0",
+ "Host:"
+ ),
+ new Expectations()
+ .scheme("http").serverName("0.0.0.0").serverPort(80)
+ .secure(false)
+ .requestURL("http://0.0.0.0/example")
+ ),
+ Arguments.of(
+ new Request("HTTP/1.0 - No Host header, with X-Forwarded-Host")
+ .headers(
+ "GET /example HTTP/1.0",
+ "X-Forwarded-Host: alt.example.net:7070"
+ ),
+ new Expectations()
+ .scheme("http").serverName("alt.example.net").serverPort(7070)
+ .secure(false)
+ .requestURL("http://alt.example.net:7070/example")
+ ),
+ Arguments.of(
+ new Request("HTTP/1.0 - Empty Host header, with X-Forwarded-Host")
+ .headers(
+ "GET /example HTTP/1.0",
+ "Host:",
+ "X-Forwarded-Host: alt.example.net:7070"
+ ),
+ new Expectations()
+ .scheme("http").serverName("alt.example.net").serverPort(7070)
+ .secure(false)
+ .requestURL("http://alt.example.net:7070/example")
+ ),
// Host IPv4
Arguments.of(
new Request("IPv4 Host Only")
@@ -144,6 +188,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("1.2.3.4").serverPort(2222)
+ .secure(false)
.requestURL("http://1.2.3.4:2222/")
),
Arguments.of(new Request("IPv6 Host Only")
@@ -153,16 +198,18 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("[::1]").serverPort(2222)
+ .secure(false)
.requestURL("http://[::1]:2222/")
),
Arguments.of(new Request("IPv4 in Request Line")
.headers(
- "GET http://1.2.3.4:2222/ HTTP/1.1",
+ "GET https://1.2.3.4:2222/ HTTP/1.1",
"Host: wrong"
),
new Expectations()
- .scheme("http").serverName("1.2.3.4").serverPort(2222)
- .requestURL("http://1.2.3.4:2222/")
+ .scheme("https").serverName("1.2.3.4").serverPort(2222)
+ .secure(true)
+ .requestURL("https://1.2.3.4:2222/")
),
Arguments.of(new Request("IPv6 in Request Line")
.headers(
@@ -171,6 +218,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("[::1]").serverPort(2222)
+ .secure(false)
.requestURL("http://[::1]:2222/")
),
@@ -187,6 +235,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("[2001:db8:cafe::17]").remotePort(4711)
),
@@ -200,6 +249,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("192.0.2.43").remotePort(0)
),
@@ -213,6 +263,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("192.0.2.43").remotePort(0)
),
@@ -227,6 +278,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("192.0.2.43").remotePort(0)
),
@@ -240,6 +292,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("192.0.2.43").remotePort(0)
),
@@ -251,6 +304,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("192.0.2.43").remotePort(0)
),
@@ -264,6 +318,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("example.com").serverPort(80)
+ .secure(false)
.requestURL("http://example.com/")
.remoteAddr("192.0.2.43").remotePort(0)
),
@@ -277,6 +332,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("myhost").serverPort(443)
+ .secure(true)
.requestURL("https://myhost/")
),
@@ -291,6 +347,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("example.com").serverPort(80)
+ .secure(false)
.remoteAddr("10.20.30.40")
.requestURL("http://example.com/")
),
@@ -305,6 +362,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("example.com").serverPort(81)
+ .secure(true)
.remoteAddr("10.20.30.40")
.requestURL("https://example.com:81/")
),
@@ -317,6 +375,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("example.com").serverPort(443)
+ .secure(true)
.requestURL("https://example.com/")
),
Arguments.of(new Request("ProxyPass (IPv6 from [::1]:80 to localhost:8080)")
@@ -328,6 +387,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("[::1]").serverPort(80)
+ .secure(false)
.remoteAddr("10.20.30.40")
.requestURL("http://[::1]/")
),
@@ -340,6 +400,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("[::1]").serverPort(8888)
+ .secure(false)
.remoteAddr("10.20.30.40")
.requestURL("http://[::1]:8888/")
),
@@ -354,6 +415,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("example.com").serverPort(443)
+ .secure(true)
.remoteAddr("10.20.30.40")
.requestURL("https://example.com/")
),
@@ -367,6 +429,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("myhost").serverPort(443)
+ .secure(true)
.requestURL("https://myhost/")
),
Arguments.of(new Request("X-Forwarded-For (multiple headers)")
@@ -378,6 +441,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("10.9.8.7").remotePort(0)
),
@@ -389,6 +453,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("10.9.8.7").remotePort(1111)
),
@@ -400,6 +465,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("[2001:db8:cafe::17]").remotePort(1111)
),
@@ -412,6 +478,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(2222)
+ .secure(false)
.requestURL("http://myhost:2222/")
.remoteAddr("[1:2:3:4:5:6:7:8]").remotePort(0)
),
@@ -426,6 +493,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(2222)
+ .secure(false)
.requestURL("http://myhost:2222/")
.remoteAddr("[1:2:3:4:5:6:7:8]").remotePort(0)
),
@@ -438,6 +506,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(2222)
+ .secure(false)
.requestURL("http://myhost:2222/")
.remoteAddr("[1:2:3:4:5:6:7:8]").remotePort(0)
),
@@ -450,6 +519,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(4444)
+ .secure(false)
.requestURL("http://myhost:4444/")
.remoteAddr("192.168.1.200").remotePort(0)
),
@@ -463,6 +533,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("192.168.1.200").remotePort(4444)
),
@@ -475,6 +546,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(4444)
+ .secure(false)
.requestURL("http://myhost:4444/")
.remoteAddr("192.168.1.200").remotePort(0)
),
@@ -489,6 +561,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("www.example.com").serverPort(4333)
+ .secure(true)
.requestURL("https://www.example.com:4333/")
.remoteAddr("8.5.4.3").remotePort(2222)
),
@@ -503,6 +576,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("www.example.com").serverPort(4333)
+ .secure(true)
.requestURL("https://www.example.com:4333/")
.remoteAddr("8.5.4.3").remotePort(2222)
),
@@ -518,6 +592,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("www.example.com").serverPort(4333)
+ .secure(true)
.requestURL("https://www.example.com:4333/")
.remoteAddr("8.5.4.3").remotePort(2222)
),
@@ -533,6 +608,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("www.example.com").serverPort(4333)
+ .secure(true)
.requestURL("https://www.example.com:4333/")
.remoteAddr("8.5.4.3").remotePort(2222)
),
@@ -548,6 +624,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("www.example.com").serverPort(4333)
+ .secure(true)
.requestURL("https://www.example.com:4333/")
.remoteAddr("8.5.4.3").remotePort(2222)
),
@@ -561,6 +638,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("fw.example.com").serverPort(4333)
+ .secure(false)
.requestURL("http://fw.example.com:4333/")
.remoteAddr("8.5.4.3").remotePort(2222)
),
@@ -574,6 +652,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("fw.example.com").serverPort(4333)
+ .secure(false)
.requestURL("http://fw.example.com:4333/")
.remoteAddr("8.5.4.3").remotePort(2222)
),
@@ -589,6 +668,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("sub1.example.com").serverPort(10003)
+ .secure(true)
.requestURL("https://sub1.example.com:10003/")
.remoteAddr("127.0.0.1").remotePort(8888)
),
@@ -604,6 +684,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("sub1.example.com").serverPort(10003)
+ .secure(true)
.requestURL("https://sub1.example.com:10003/")
.remoteAddr("127.0.0.1").remotePort(8888)
),
@@ -620,6 +701,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("sub1.example.com").serverPort(10003)
+ .secure(true)
.requestURL("https://sub1.example.com:10003/")
.remoteAddr("127.0.0.1").remotePort(8888)
),
@@ -635,6 +717,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("sub1.example.com").serverPort(10003)
+ .secure(true)
.requestURL("https://sub1.example.com:10003/")
.remoteAddr("127.0.0.1").remotePort(8888)
),
@@ -651,9 +734,35 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("example.com").serverPort(80)
+ .secure(false)
.requestURL("http://example.com/")
.remoteAddr("192.0.2.43").remotePort(0)
),
+ Arguments.of(
+ new Request("RFC7239 - mixed with HTTP/1.0 - No Host header")
+ .headers(
+ "GET /example HTTP/1.0",
+ "Forwarded: for=1.1.1.1:6060,proto=http;host=alt.example.net:7070"
+ ),
+ new Expectations()
+ .scheme("http").serverName("alt.example.net").serverPort(7070)
+ .secure(false)
+ .requestURL("http://alt.example.net:7070/example")
+ .remoteAddr("1.1.1.1").remotePort(6060)
+ ),
+ Arguments.of(
+ new Request("RFC7239 - mixed with HTTP/1.0 - Empty Host header")
+ .headers(
+ "GET /example HTTP/1.0",
+ "Host:",
+ "Forwarded: for=1.1.1.1:6060,proto=http;host=alt.example.net:7070"
+ ),
+ new Expectations()
+ .scheme("http").serverName("alt.example.net").serverPort(7070)
+ .secure(false)
+ .requestURL("http://alt.example.net:7070/example")
+ .remoteAddr("1.1.1.1").remotePort(6060)
+ ),
// =================================================================
// Forced Behavior
Arguments.of(new Request("Forced Host (no port)")
@@ -666,6 +775,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("always.example.com").serverPort(80)
+ .secure(false)
.requestURL("http://always.example.com/")
.remoteAddr("11.9.8.7").remotePort(1111)
),
@@ -679,6 +789,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("always.example.com").serverPort(9090)
+ .secure(false)
.requestURL("http://always.example.com:9090/")
.remoteAddr("11.9.8.7").remotePort(1111)
),
@@ -692,6 +803,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("myhost").serverPort(443)
+ .secure(true)
.requestURL("https://myhost/")
.remoteAddr("0.0.0.0").remotePort(0)
),
@@ -704,6 +816,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("0.0.0.0").remotePort(0)
.sslSession("Wibble")
@@ -717,6 +830,7 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("myhost").serverPort(443)
+ .secure(true)
.requestURL("https://myhost/")
.remoteAddr("0.0.0.0").remotePort(0)
.sslSession("0123456789abcdef")
@@ -730,6 +844,7 @@ public static Stream cases()
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
.requestURL("http://myhost/")
.remoteAddr("0.0.0.0").remotePort(0)
.sslCertificate("Wibble")
@@ -743,9 +858,121 @@ public static Stream cases()
),
new Expectations()
.scheme("https").serverName("myhost").serverPort(443)
+ .secure(true)
.requestURL("https://myhost/")
.remoteAddr("0.0.0.0").remotePort(0)
.sslCertificate("0123456789abcdef")
+ ),
+ // =================================================================
+ // Complicated scenarios
+ Arguments.of(new Request("No initial authority, X-Forwarded-Proto on http, Proxy-Ssl-Id exists (setSslIsSecure==true)")
+ .configureCustomizer((customizer) -> customizer.setSslIsSecure(true))
+ .headers(
+ "GET /foo HTTP/1.1",
+ "Host: myhost",
+ "X-Forwarded-Proto: http",
+ "Proxy-Ssl-Id: Wibble"
+ ),
+ new Expectations()
+ .scheme("http").serverName("myhost").serverPort(80)
+ .secure(true)
+ .requestURL("http://myhost/foo")
+ .remoteAddr("0.0.0.0").remotePort(0)
+ .sslSession("Wibble")
+ ),
+ Arguments.of(new Request("https initial authority, X-Forwarded-Proto on http, Proxy-Ssl-Id exists (setSslIsSecure==false)")
+ .configureCustomizer((customizer) -> customizer.setSslIsSecure(false))
+ .headers(
+ "GET https://alt.example.net/foo HTTP/1.1",
+ "Host: myhost",
+ "X-Forwarded-Proto: http",
+ "Proxy-Ssl-Id: Wibble"
+ ),
+ new Expectations()
+ .scheme("http").serverName("alt.example.net").serverPort(80)
+ .secure(false)
+ .requestURL("http://alt.example.net/foo")
+ .remoteAddr("0.0.0.0").remotePort(0)
+ .sslSession("Wibble")
+ ),
+ Arguments.of(new Request("No initial authority, X-Proxied-Https off, Proxy-Ssl-Id exists (setSslIsSecure==true)")
+ .configureCustomizer((customizer) -> customizer.setSslIsSecure(true))
+ .headers(
+ "GET /foo HTTP/1.1",
+ "Host: myhost",
+ "X-Proxied-Https: off", // this wins for scheme and secure
+ "Proxy-Ssl-Id: Wibble"
+ ),
+ new Expectations()
+ .scheme("http").serverName("myhost").serverPort(80)
+ .secure(false)
+ .requestURL("http://myhost/foo")
+ .remoteAddr("0.0.0.0").remotePort(0)
+ .sslSession("Wibble")
+ ),
+ Arguments.of(new Request("Https initial authority, X-Proxied-Https off, Proxy-Ssl-Id exists (setSslIsSecure==true)")
+ .configureCustomizer((customizer) -> customizer.setSslIsSecure(true))
+ .headers(
+ "GET https://alt.example.net/foo HTTP/1.1",
+ "Host: myhost",
+ "X-Proxied-Https: off", // this wins for scheme and secure
+ "Proxy-Ssl-Id: Wibble"
+ ),
+ new Expectations()
+ .scheme("http").serverName("alt.example.net").serverPort(80)
+ .secure(false)
+ .requestURL("http://alt.example.net/foo")
+ .remoteAddr("0.0.0.0").remotePort(0)
+ .sslSession("Wibble")
+ ),
+ Arguments.of(new Request("Https initial authority, X-Proxied-Https off, Proxy-Ssl-Id exists (setSslIsSecure==true) (alt order)")
+ .configureCustomizer((customizer) -> customizer.setSslIsSecure(true))
+ .headers(
+ "GET https://alt.example.net/foo HTTP/1.1",
+ "Host: myhost",
+ "Proxy-Ssl-Id: Wibble",
+ "X-Proxied-Https: off" // this wins for scheme and secure
+ ),
+ new Expectations()
+ .scheme("http").serverName("alt.example.net").serverPort(80)
+ .secure(false)
+ .requestURL("http://alt.example.net/foo")
+ .remoteAddr("0.0.0.0").remotePort(0)
+ .sslSession("Wibble")
+ ),
+ Arguments.of(new Request("Http initial authority, X-Proxied-Https off, Proxy-Ssl-Id exists (setSslIsSecure==false)")
+ .configureCustomizer((customizer) -> customizer.setSslIsSecure(false))
+ .headers(
+ "GET https://alt.example.net/foo HTTP/1.1",
+ "Host: myhost",
+ "X-Proxied-Https: off",
+ "Proxy-Ssl-Id: Wibble",
+ "Proxy-auth-cert: 0123456789abcdef"
+ ),
+ new Expectations()
+ .scheme("http").serverName("alt.example.net").serverPort(80)
+ .secure(false)
+ .requestURL("http://alt.example.net/foo")
+ .remoteAddr("0.0.0.0").remotePort(0)
+ .sslSession("Wibble")
+ .sslCertificate("0123456789abcdef")
+ ),
+ Arguments.of(new Request("Http initial authority, X-Proxied-Https off, Proxy-Ssl-Id exists (setSslIsSecure==false) (alt)")
+ .configureCustomizer((customizer) -> customizer.setSslIsSecure(false))
+ .headers(
+ "GET https://alt.example.net/foo HTTP/1.1",
+ "Host: myhost",
+ "Proxy-Ssl-Id: Wibble",
+ "Proxy-auth-cert: 0123456789abcdef",
+ "X-Proxied-Https: off"
+ ),
+ new Expectations()
+ .scheme("http").serverName("alt.example.net").serverPort(80)
+ .secure(false)
+ .requestURL("http://alt.example.net/foo")
+ .remoteAddr("0.0.0.0").remotePort(0)
+ .sslSession("Wibble")
+ .sslCertificate("0123456789abcdef")
)
);
}
@@ -848,20 +1075,31 @@ public void testNonStandardPortBehavior(Request request, Expectations expectatio
expectations.accept(actual);
}
- @Test
- public void testBadInput() throws Exception
+ public static Stream badRequestCases()
{
- Request request = new Request("Bad port value")
- .headers(
- "GET / HTTP/1.1",
- "Host: myhost",
- "X-Forwarded-Port: "
- );
+ return Stream.of(
+ new Request("Bad port value")
+ .headers(
+ "GET / HTTP/1.1",
+ "Host: myhost",
+ "X-Forwarded-Port: "
+ ),
+ new Request("Invalid X-Proxied-Https value")
+ .headers(
+ "GET / HTTP/1.1",
+ "Host: myhost",
+ "X-Proxied-Https: foo"
+ )
+ );
+ }
+ @ParameterizedTest
+ @MethodSource("badRequestCases")
+ public void testBadInput(Request request) throws Exception
+ {
request.configure(customizer);
String rawRequest = request.getRawRequest((header) -> header);
- // System.out.println(rawRequest);
HttpTester.Response response = HttpTester.parseResponse(connector.getResponse(rawRequest));
assertThat("status", response.getStatus(), is(400));
@@ -926,12 +1164,13 @@ private static class Expectations implements Consumer
int expectedRemotePort = 0;
String expectedSslSession;
String expectedSslCertificate;
+ Boolean secure;
@Override
public void accept(Actual actual)
{
assertThat("scheme", actual.scheme.get(), is(expectedScheme));
- if (actual.scheme.get().equals("https"))
+ if (secure != null && secure)
{
assertTrue(actual.wasSecure.get(), "wasSecure");
}
@@ -953,6 +1192,12 @@ public void accept(Actual actual)
}
}
+ public Expectations secure(boolean flag)
+ {
+ this.secure = flag;
+ return this;
+ }
+
public Expectations scheme(String scheme)
{
this.expectedScheme = scheme;