Issue #5443 - Forwarding Headers are optional

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
This commit is contained in:
Joakim Erdfelt 2020-10-13 05:10:42 -05:00
parent c37c2c59ab
commit 0b646ee6b7
No known key found for this signature in database
GPG Key ID: 2D0E1FB8FE4B68B4
2 changed files with 84 additions and 57 deletions

View File

@ -461,13 +461,17 @@ public class ForwardedRequestCustomizer implements Customizer
// 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,70 @@ public class ForwardedRequestCustomizer implements Customizer
}
}
String proto = "http";
// Is secure status configured from headers?
if (forwarded.isSecure())
if (match)
{
// set default to https
proto = config.getSecureScheme();
}
String proto = "http";
// Set Scheme from configured protocol
if (forwarded._proto != null)
{
proto = forwarded._proto;
request.setScheme(proto);
}
// Is secure status configured from headers?
if (forwarded.isSecure())
{
// set default to https
proto = config.getSecureScheme();
}
// Set authority
String host = null;
int port = -1;
// Set Scheme from configured protocol
if (forwarded._proto != null)
{
proto = forwarded._proto;
request.setScheme(proto);
}
// Use authority from headers, if configured.
if (forwarded._authority != null)
{
host = forwarded._authority._host;
port = forwarded._authority._port;
}
// Set authority
String host = null;
int port = -1;
// 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.
// Use authority from headers, if configured.
if (forwarded._authority != null)
{
host = forwarded._authority._host;
port = forwarded._authority._port;
}
// Update authority if different from metadata
if (!host.equalsIgnoreCase(requestURI.getHost()) ||
port != requestURI.getPort())
{
httpFields.put(new HostPortHttpField(host, port));
request.setAuthority(host, port);
}
// 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.
// Set secure status
if (forwarded.isSecure() ||
proto.equalsIgnoreCase(config.getSecureScheme()) ||
port == getSecurePort(config))
{
request.setSecure(true);
request.setScheme(proto);
}
// 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));
// Set secure status
if (forwarded.isSecure() ||
proto.equalsIgnoreCase(config.getSecureScheme()) ||
port == getSecurePort(config))
{
request.setSecure(true);
request.setScheme(proto);
}
// 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));
}
}
}

View File

@ -135,6 +135,26 @@ public class ForwardedRequestCustomizerTest
public static Stream<Arguments> 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)
.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)
.requestURL("http://0.0.0.0/example")
),
// Host IPv4
Arguments.of(
new Request("IPv4 Host Only")
@ -157,12 +177,12 @@ public class ForwardedRequestCustomizerTest
),
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)
.requestURL("https://1.2.3.4:2222/")
),
Arguments.of(new Request("IPv6 in Request Line")
.headers(
@ -931,7 +951,7 @@ public class ForwardedRequestCustomizerTest
public void accept(Actual actual)
{
assertThat("scheme", actual.scheme.get(), is(expectedScheme));
if (actual.scheme.get().equals("https"))
if (expectedScheme.equals("https"))
{
assertTrue(actual.wasSecure.get(), "wasSecure");
}