From f54b6825283468ddbef6e9eaff2082e3511b180b Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Sun, 16 Jun 2019 11:12:40 +0200 Subject: [PATCH 1/8] Fixes #3786 - ALPN support for Java 14. Signed-off-by: Simone Bordet --- .../src/main/config/modules/alpn-impl/alpn-14.mod | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-14.mod diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-14.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-14.mod new file mode 100644 index 00000000000..689601a4197 --- /dev/null +++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn-impl/alpn-14.mod @@ -0,0 +1,4 @@ +DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html + +[depend] +alpn-impl/alpn-9 From 1550d4f59a7d36ba9f18cf8191eec614e2312efe Mon Sep 17 00:00:00 2001 From: olivier lamy Date: Sat, 15 Jun 2019 11:09:36 +1000 Subject: [PATCH 2/8] avoid depending on a range dependency from a transitive dependency Signed-off-by: olivier lamy --- jetty-gcloud/jetty-gcloud-session-manager/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/jetty-gcloud/jetty-gcloud-session-manager/pom.xml b/jetty-gcloud/jetty-gcloud-session-manager/pom.xml index 15c103fd57e..f9088835f35 100644 --- a/jetty-gcloud/jetty-gcloud-session-manager/pom.xml +++ b/jetty-gcloud/jetty-gcloud-session-manager/pom.xml @@ -33,6 +33,13 @@ + + + io.grpc + grpc-core + 1.0.1 + compile + com.google.auto.value auto-value From a18bd12ada2aabbb72cd142b05fffb0af6cabd6d Mon Sep 17 00:00:00 2001 From: Lachlan Date: Thu, 13 Jun 2019 15:43:19 +1000 Subject: [PATCH 3/8] Issue #3762 - use the default port of 0 for WebSocket tests Signed-off-by: Lachlan Roberts --- .../tests/WebSocketConnectionStatsTest.java | 72 +++---------------- .../tests/client/BadNetworkTest.java | 1 - .../tests/client/ClientCloseTest.java | 1 - .../tests/client/ClientSessionsTest.java | 1 - .../tests/client/SlowClientTest.java | 1 - .../tests/server/ServerCloseTest.java | 1 - .../tests/server/SlowServerTest.java | 1 - 7 files changed, 10 insertions(+), 68 deletions(-) diff --git a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketConnectionStatsTest.java b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketConnectionStatsTest.java index 68b16d1d909..a17eb1a7089 100644 --- a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketConnectionStatsTest.java +++ b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/WebSocketConnectionStatsTest.java @@ -33,15 +33,9 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.websocket.api.CloseStatus; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; -import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; -import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; -import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; -import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.client.WebSocketClient; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.Generator; @@ -60,52 +54,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class WebSocketConnectionStatsTest { - - @WebSocket - public static class ClientSocket - { - CountDownLatch closed = new CountDownLatch(1); - int closeStatus; - String closeReason; - String behavior; - - @OnWebSocketConnect - public void onOpen(Session session) - { - behavior = session.getPolicy().getBehavior().name(); - } - - @OnWebSocketClose - public void onClose(int statusCode, String reason) - { - closeStatus = statusCode; - closeReason = reason; - closed.countDown(); - } - - @OnWebSocketError - public void onError(Throwable cause) - { - cause.printStackTrace(System.err); - } - - @Override - public String toString() - { - return String.format("[%s@%s]", behavior, Integer.toHexString(hashCode())); - } - } - - @WebSocket - public static class EchoSocket extends ClientSocket - { - @OnWebSocketMessage - public void onMessage(Session session, String message) - { - session.getRemote().sendString(message, null); - } - } - public static class MyWebSocketServlet extends WebSocketServlet { @Override @@ -115,11 +63,12 @@ public class WebSocketConnectionStatsTest } } - Server server; - WebSocketClient client; - ConnectionStatistics statistics; - CountDownLatch wsUpgradeComplete = new CountDownLatch(1); - CountDownLatch wsConnectionClosed = new CountDownLatch(1); + private Server server; + private ServerConnector connector; + private WebSocketClient client; + private ConnectionStatistics statistics; + private CountDownLatch wsUpgradeComplete = new CountDownLatch(1); + private CountDownLatch wsConnectionClosed = new CountDownLatch(1); @BeforeEach public void start() throws Exception @@ -139,8 +88,7 @@ public class WebSocketConnectionStatsTest }; server = new Server(); - ServerConnector connector = new ServerConnector(server); - connector.setPort(8080); + connector = new ServerConnector(server); connector.addBean(statistics); server.addConnector(connector); @@ -175,8 +123,8 @@ public class WebSocketConnectionStatsTest @Test public void echoStatsTest() throws Exception { - URI uri = URI.create("ws://localhost:8080/testPath"); - ClientSocket socket = new ClientSocket(); + URI uri = URI.create("ws://localhost:"+connector.getLocalPort()+"/testPath"); + EventSocket socket = new EventSocket(); Future connect = client.connect(socket, uri); final long numMessages = 10000; @@ -208,7 +156,7 @@ public class WebSocketConnectionStatsTest assertThat(statistics.getReceivedMessages(), is(numMessages + 2L)); WebSocketFrame textFrame = new TextFrame().setPayload(msgText); - WebSocketFrame closeFrame = new CloseInfo(socket.closeStatus, socket.closeReason).asFrame(); + WebSocketFrame closeFrame = new CloseInfo(socket.closeCode, socket.closeReason).asFrame(); final long textFrameSize = getFrameByteSize(textFrame); final long closeFrameSize = getFrameByteSize(closeFrame); diff --git a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/BadNetworkTest.java b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/BadNetworkTest.java index 2b51caf95d6..fe6df99bec0 100644 --- a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/BadNetworkTest.java +++ b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/BadNetworkTest.java @@ -80,7 +80,6 @@ public class BadNetworkTest server = new Server(); connector = new ServerConnector(server); - connector.setPort(0); server.addConnector(connector); context = new ServletContextHandler(); diff --git a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientCloseTest.java b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientCloseTest.java index c28d5aadae1..cd858295826 100644 --- a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientCloseTest.java +++ b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientCloseTest.java @@ -119,7 +119,6 @@ public class ClientCloseTest server = new Server(); ServerConnector connector = new ServerConnector(server); - connector.setPort(0); server.addConnector(connector); ServletContextHandler context = new ServletContextHandler(); diff --git a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientSessionsTest.java b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientSessionsTest.java index 8ce7e34a8da..dda19b04604 100644 --- a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientSessionsTest.java +++ b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/ClientSessionsTest.java @@ -63,7 +63,6 @@ public class ClientSessionsTest server = new Server(); ServerConnector connector = new ServerConnector(server); - connector.setPort(0); server.addConnector(connector); ServletContextHandler context = new ServletContextHandler(); diff --git a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/SlowClientTest.java b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/SlowClientTest.java index 27045eb17aa..f2bbde10ef5 100644 --- a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/SlowClientTest.java +++ b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/client/SlowClientTest.java @@ -65,7 +65,6 @@ public class SlowClientTest server = new Server(); ServerConnector connector = new ServerConnector(server); - connector.setPort(0); server.addConnector(connector); ServletContextHandler context = new ServletContextHandler(); diff --git a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerCloseTest.java b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerCloseTest.java index 017482187ce..66260942988 100644 --- a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerCloseTest.java +++ b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/ServerCloseTest.java @@ -65,7 +65,6 @@ public class ServerCloseTest server = new Server(); ServerConnector connector = new ServerConnector(server); - connector.setPort(0); server.addConnector(connector); ServletContextHandler context = new ServletContextHandler(); diff --git a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerTest.java b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerTest.java index 19fb2cae723..2e8000be152 100644 --- a/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerTest.java +++ b/jetty-websocket/jetty-websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/SlowServerTest.java @@ -64,7 +64,6 @@ public class SlowServerTest server = new Server(); ServerConnector connector = new ServerConnector(server); - connector.setPort(0); server.addConnector(connector); ServletContextHandler context = new ServletContextHandler(); From 2f3eed86049600b9da385112168f7f8b658fd582 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Fri, 14 Jun 2019 11:20:08 -0500 Subject: [PATCH 4/8] Issue #3782 - reducing noise during testing Signed-off-by: Joakim Erdfelt --- jetty-server/src/test/resources/jetty-logging.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/jetty-server/src/test/resources/jetty-logging.properties b/jetty-server/src/test/resources/jetty-logging.properties index 21db0759fe3..1ba30af5c5f 100644 --- a/jetty-server/src/test/resources/jetty-logging.properties +++ b/jetty-server/src/test/resources/jetty-logging.properties @@ -1,4 +1,5 @@ org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog +org.eclipse.jetty.LEVEL=WARN #org.eclipse.jetty.LEVEL=DEBUG #org.eclipse.jetty.server.LEVEL=DEBUG #org.eclipse.jetty.server.ConnectionLimit.LEVEL=DEBUG From a1fe57a654db6a44449c0c7e40acb8217cc7eb28 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Fri, 14 Jun 2019 11:20:31 -0500 Subject: [PATCH 5/8] Issue #3782 - updating existing testcases Signed-off-by: Joakim Erdfelt --- .../ForwardedRequestCustomizerTest.java | 682 ++++++++++-------- 1 file changed, 377 insertions(+), 305 deletions(-) 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 db8a9ad64e0..5c38e601d52 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 @@ -19,25 +19,20 @@ package org.eclipse.jetty.server; import java.io.IOException; -import java.util.ArrayDeque; -import java.util.Deque; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; - import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.server.handler.AbstractHandler; -import org.eclipse.jetty.util.IO; -import org.hamcrest.Matchers; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -46,11 +41,15 @@ public class ForwardedRequestCustomizerTest private Server _server; private LocalConnector _connector; private RequestHandler _handler; - final Deque _results = new ArrayDeque<>(); final AtomicBoolean _wasSecure = new AtomicBoolean(false); final AtomicReference _sslSession = new AtomicReference<>(); final AtomicReference _sslCertificate = new AtomicReference<>(); - + final AtomicReference _scheme = new AtomicReference<>(); + final AtomicReference _serverName = new AtomicReference<>(); + final AtomicReference _serverPort = new AtomicReference<>(); + final AtomicReference _remoteAddr = new AtomicReference<>(); + final AtomicReference _remotePort = new AtomicReference<>(); + ForwardedRequestCustomizer _customizer; @BeforeEach @@ -62,29 +61,25 @@ public class ForwardedRequestCustomizerTest http.getHttpConfiguration().setRequestHeaderSize(512); http.getHttpConfiguration().setResponseHeaderSize(512); http.getHttpConfiguration().setOutputBufferSize(2048); - http.getHttpConfiguration().addCustomizer(_customizer=new ForwardedRequestCustomizer()); - _connector = new LocalConnector(_server,http); + http.getHttpConfiguration().addCustomizer(_customizer = new ForwardedRequestCustomizer()); + _connector = new LocalConnector(_server, http); _server.addConnector(_connector); _handler = new RequestHandler(); _server.setHandler(_handler); - _handler._checker = new RequestTester() + _handler._checker = (request, response) -> { - @Override - public boolean check(HttpServletRequest request,HttpServletResponse response) - { - _wasSecure.set(request.isSecure()); - _sslSession.set(String.valueOf(request.getAttribute("javax.servlet.request.ssl_session_id"))); - _sslCertificate.set(String.valueOf(request.getAttribute("javax.servlet.request.cipher_suite"))); - _results.add(request.getScheme()); - _results.add(request.getServerName()); - _results.add(Integer.toString(request.getServerPort())); - _results.add(request.getRemoteAddr()); - _results.add(Integer.toString(request.getRemotePort())); - return true; - } + _wasSecure.set(request.isSecure()); + _sslSession.set(String.valueOf(request.getAttribute("javax.servlet.request.ssl_session_id"))); + _sslCertificate.set(String.valueOf(request.getAttribute("javax.servlet.request.cipher_suite"))); + _scheme.set(request.getScheme()); + _serverName.set(request.getServerName()); + _serverPort.set(request.getServerPort()); + _remoteAddr.set(request.getRemoteAddr()); + _remotePort.set(request.getRemotePort()); + return true; }; - + _server.start(); } @@ -92,391 +87,468 @@ public class ForwardedRequestCustomizerTest public void destroy() throws Exception { _server.stop(); - _server.join(); } @Test public void testHostIpv4() throws Exception { - String response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: 1.2.3.4:2222\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("1.2.3.4",_results.poll()); - assertEquals("2222",_results.poll()); - assertEquals("0.0.0.0",_results.poll()); - assertEquals("0",_results.poll()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: 1.2.3.4:2222\n" + + "\n")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("1.2.3.4")); + assertThat("serverPort", _serverPort.get(), is(2222)); } @Test public void testHostIpv6() throws Exception { - String response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: [::1]:2222\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("[::1]",_results.poll()); - assertEquals("2222",_results.poll()); - assertEquals("0.0.0.0",_results.poll()); - assertEquals("0",_results.poll()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: [::1]:2222\n" + + "\n")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("[::1]")); + assertThat("serverPort", _serverPort.get(), is(2222)); } - - @Test public void testURIIpv4() throws Exception { - String response=_connector.getResponse( - "GET http://1.2.3.4:2222/ HTTP/1.1\n"+ - "Host: wrong\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("1.2.3.4",_results.poll()); - assertEquals("2222",_results.poll()); - assertEquals("0.0.0.0",_results.poll()); - assertEquals("0",_results.poll()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET http://1.2.3.4:2222/ HTTP/1.1\n" + + "Host: wrong\n" + + "\n")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("1.2.3.4")); + assertThat("serverPort", _serverPort.get(), is(2222)); } @Test public void testURIIpv6() throws Exception { - String response=_connector.getResponse( - "GET http://[::1]:2222/ HTTP/1.1\n"+ - "Host: wrong\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("[::1]",_results.poll()); - assertEquals("2222",_results.poll()); - assertEquals("0.0.0.0",_results.poll()); - assertEquals("0",_results.poll()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET http://[::1]:2222/ HTTP/1.1\n" + + "Host: wrong\n" + + "\n")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("[::1]")); + assertThat("serverPort", _serverPort.get(), is(2222)); } - + /** + * RFC 7239: Section 4 + * + * Examples of syntax. + */ @Test public void testRFC7239_Examples_4() throws Exception { - String response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "Forwarded: for=\"_gazonk\"\n"+ - "Forwarded: For=\"[2001:db8:cafe::17]:4711\"\n"+ - "Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43\n"+ - "Forwarded: for=192.0.2.43, for=198.51.100.17\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("[2001:db8:cafe::17]",_results.poll()); - assertEquals("4711",_results.poll()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "Forwarded: for=\"_gazonk\"\n" + + "Forwarded: For=\"[2001:db8:cafe::17]:4711\"\n" + + "Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43\n" + + "Forwarded: for=192.0.2.43, for=198.51.100.17\n" + + "\n")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("[2001:db8:cafe::17]")); + assertThat("remotePort", _remotePort.get(), is(4711)); } - + + /** + * RFC 7239: Section 7.1 + * + * Examples of syntax with regards to HTTP header fields + */ @Test public void testRFC7239_Examples_7_1() throws Exception { - _connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "Forwarded: for=192.0.2.43,for=\"[2001:db8:cafe::17]\",for=unknown\n"+ - "\n"); - _connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "Forwarded: for=192.0.2.43, for=\"[2001:db8:cafe::17]\", for=unknown\n"+ - "\n"); - _connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "Forwarded: for=192.0.2.43\n"+ - "Forwarded: for=\"[2001:db8:cafe::17]\", for=unknown\n"+ - "\n"); + // Without spaces + HttpTester.Response response1 = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "Forwarded: for=192.0.2.43,for=\"[2001:db8:cafe::17]\",for=unknown\n" + + "\n")); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("192.0.2.43",_results.poll()); - assertEquals("0",_results.poll()); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("192.0.2.43",_results.poll()); - assertEquals("0",_results.poll()); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("192.0.2.43",_results.poll()); - assertEquals("0",_results.poll()); + assertThat("status", response1.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); + assertThat("remotePort", _remotePort.get(), is(0)); + + // With spaces + HttpTester.Response response2 = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "Forwarded: for=192.0.2.43, for=\"[2001:db8:cafe::17]\", for=unknown\n" + + "\n")); + assertThat("status", response2.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); + assertThat("remotePort", _remotePort.get(), is(0)); + + // As multiple headers + HttpTester.Response response3 = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "Forwarded: for=192.0.2.43\n" + + "Forwarded: for=\"[2001:db8:cafe::17]\", for=unknown\n" + + "\n")); + + assertThat("status", response3.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); + assertThat("remotePort", _remotePort.get(), is(0)); } + /** + * RFC 7239: Section 7.4 + * + * Transition + */ @Test public void testRFC7239_Examples_7_4() throws Exception { - _connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "Forwarded: for=192.0.2.43, for=\"[2001:db8:cafe::17]\"\n"+ - "\n"); + // Old syntax + HttpTester.Response response1 = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "X-Forwarded-For: 192.0.2.43, 2001:db8:cafe::17\n" + + "\n")); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("192.0.2.43",_results.poll()); - assertEquals("0",_results.poll()); + assertThat("status", response1.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); + assertThat("remotePort", _remotePort.get(), is(0)); + + // New syntax + HttpTester.Response response2 = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "Forwarded: for=192.0.2.43, for=\"[2001:db8:cafe::17]\"\n" + + "\n")); + + assertThat("status", response2.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); + assertThat("remotePort", _remotePort.get(), is(0)); } + /** + * RFC 7239: Section 7.5 + * + * Example Usage + */ @Test public void testRFC7239_Examples_7_5() throws Exception { - _connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "Forwarded: for=192.0.2.43,for=198.51.100.17;by=203.0.113.60;proto=http;host=example.com\n"+ - "\n"); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "Forwarded: for=192.0.2.43,for=198.51.100.17;by=203.0.113.60;proto=http;host=example.com\n" + + "\n")); - assertEquals("http",_results.poll()); - assertEquals("example.com",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("192.0.2.43",_results.poll()); - assertEquals("0",_results.poll()); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("example.com")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); + assertThat("remotePort", _remotePort.get(), is(0)); } @Test - public void testProto() throws Exception + public void testProto_OldSyntax() throws Exception { - String response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "X-Forwarded-Proto: foobar\n"+ - "Forwarded: proto=https\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("https",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("443",_results.poll()); - assertEquals("0.0.0.0",_results.poll()); - assertEquals("0",_results.poll()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "X-Forwarded-Proto: https\n" + + "\n")); + + assertTrue(_wasSecure.get(), "wasSecure"); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("https")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(443)); + assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); + assertThat("remotePort", _remotePort.get(), is(0)); + } + + @Test + public void testRFC7239_Proto() throws Exception + { + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "Forwarded: proto=https\n" + + "\n")); + + assertTrue(_wasSecure.get(), "wasSecure"); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("https")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(443)); + assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); + assertThat("remotePort", _remotePort.get(), is(0)); } @Test public void testFor() throws Exception { - String response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "X-Forwarded-For: 10.9.8.7,6.5.4.3\n"+ - "X-Forwarded-For: 8.9.8.7,7.5.4.3\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("10.9.8.7",_results.poll()); - assertEquals("0",_results.poll()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "X-Forwarded-For: 10.9.8.7,6.5.4.3\n" + + "X-Forwarded-For: 8.9.8.7,7.5.4.3\n" + + "\n")); + + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("10.9.8.7")); + assertThat("remotePort", _remotePort.get(), is(0)); } @Test public void testForIpv4WithPort() throws Exception { - String response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "X-Forwarded-For: 10.9.8.7:1111,6.5.4.3:2222\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("10.9.8.7",_results.poll()); - assertEquals("1111",_results.poll()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "X-Forwarded-For: 10.9.8.7:1111,6.5.4.3:2222\n" + + "\n")); + + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("10.9.8.7")); + assertThat("remotePort", _remotePort.get(), is(1111)); } @Test public void testForIpv6WithPort() throws Exception { - String response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "X-Forwarded-For: [2001:db8:cafe::17]:1111,6.5.4.3:2222\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("[2001:db8:cafe::17]",_results.poll()); - assertEquals("1111",_results.poll()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "X-Forwarded-For: [2001:db8:cafe::17]:1111,6.5.4.3:2222\n" + + "\n")); + + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("[2001:db8:cafe::17]")); + assertThat("remotePort", _remotePort.get(), is(1111)); } @Test public void testForIpv6AndPort() throws Exception { - String response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "X-Forwarded-For: 1:2:3:4:5:6:7:8\n"+ - "X-Forwarded-Port: 2222\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("[1:2:3:4:5:6:7:8]",_results.poll()); - assertEquals("2222",_results.poll()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "X-Forwarded-For: 1:2:3:4:5:6:7:8\n" + + "X-Forwarded-Port: 2222\n" + + "\n")); - response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "X-Forwarded-Port: 2222\n"+ - "X-Forwarded-For: 1:2:3:4:5:6:7:8\n"+ - "X-Forwarded-For: 7:7:7:7:7:7:7:7\n"+ - "X-Forwarded-Port: 3333\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("[1:2:3:4:5:6:7:8]",_results.poll()); - assertEquals("2222",_results.poll()); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("[1:2:3:4:5:6:7:8]")); + assertThat("remotePort", _remotePort.get(), is(2222)); + } + + @Test + public void testForIpv6AndPort_MultiField() throws Exception + { + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "X-Forwarded-Port: 2222\n" + + "X-Forwarded-For: 1:2:3:4:5:6:7:8\n" + + "X-Forwarded-For: 7:7:7:7:7:7:7:7\n" + + "X-Forwarded-Port: 3333\n" + + "\n")); + + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("[1:2:3:4:5:6:7:8]")); + assertThat("remotePort", _remotePort.get(), is(2222)); } @Test public void testLegacyProto() throws Exception { - String response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "X-Proxied-Https: on\n"+ - "\n"); - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("https",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("443",_results.poll()); - assertEquals("0.0.0.0",_results.poll()); - assertEquals("0",_results.poll()); - assertTrue(_wasSecure.get()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "X-Proxied-Https: on\n" + + "\n")); + assertTrue(_wasSecure.get(), "wasSecure"); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("https")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(443)); + assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); + assertThat("remotePort", _remotePort.get(), is(0)); } @Test public void testSslSession() throws Exception { _customizer.setSslIsSecure(false); - String response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "Proxy-Ssl-Id: Wibble\n"+ - "\n"); - - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("0.0.0.0",_results.poll()); - assertEquals("0",_results.poll()); - assertFalse(_wasSecure.get()); - assertEquals("Wibble",_sslSession.get()); - - _customizer.setSslIsSecure(true); - response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "Proxy-Ssl-Id: 0123456789abcdef\n"+ - "\n"); - - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("https",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("443",_results.poll()); - assertEquals("0.0.0.0",_results.poll()); - assertEquals("0",_results.poll()); - assertTrue(_wasSecure.get()); - assertEquals("0123456789abcdef",_sslSession.get()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "Proxy-Ssl-Id: Wibble\n" + + "\n")); + + assertFalse(_wasSecure.get(), "wasSecure"); + assertThat("sslSession", _sslSession.get(), is("Wibble")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); + assertThat("remotePort", _remotePort.get(), is(0)); + + _customizer.setSslIsSecure(true); + response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "Proxy-Ssl-Id: 0123456789abcdef\n" + + "\n")); + + assertTrue(_wasSecure.get(), "wasSecure"); + assertThat("sslSession", _sslSession.get(), is("0123456789abcdef")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("https")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(443)); + assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); + assertThat("remotePort", _remotePort.get(), is(0)); } - + @Test public void testSslCertificate() throws Exception { _customizer.setSslIsSecure(false); - String response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "Proxy-auth-cert: Wibble\n"+ - "\n"); - - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("http",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("0.0.0.0",_results.poll()); - assertEquals("0",_results.poll()); - assertFalse(_wasSecure.get()); - assertEquals("Wibble",_sslCertificate.get()); - - - _customizer.setSslIsSecure(true); - response=_connector.getResponse( - "GET / HTTP/1.1\n"+ - "Host: myhost\n"+ - "Proxy-auth-cert: 0123456789abcdef\n"+ - "\n"); - - assertThat(response, Matchers.containsString("200 OK")); - assertEquals("https",_results.poll()); - assertEquals("myhost",_results.poll()); - assertEquals("443",_results.poll()); - assertEquals("0.0.0.0",_results.poll()); - assertEquals("0",_results.poll()); - assertTrue(_wasSecure.get()); - assertEquals("0123456789abcdef",_sslCertificate.get()); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "Proxy-auth-cert: Wibble\n" + + "\n")); + + assertFalse(_wasSecure.get(), "wasSecure"); + assertThat("sslCertificate", _sslCertificate.get(), is("Wibble")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); + assertThat("remotePort", _remotePort.get(), is(0)); + + _customizer.setSslIsSecure(true); + response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "Proxy-auth-cert: 0123456789abcdef\n" + + "\n")); + + assertTrue(_wasSecure.get(), "wasSecure"); + assertThat("sslCertificate", _sslCertificate.get(), is("0123456789abcdef")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("https")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(443)); + assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); + assertThat("remotePort", _remotePort.get(), is(0)); } - @Test - public void testMixed() throws Exception + public void testMixed_For_Port_RFC_For() throws Exception { - String response = _connector.getResponse( + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( "GET / HTTP/1.1\n" + "Host: myhost\n" + "X-Forwarded-For: 11.9.8.7:1111,8.5.4.3:2222\n" + "X-Forwarded-Port: 3333\n" + - "Forwarded: for=192.0.2.43,for=198.51.100.17;by=203.0.113.60;proto=http;host=example.com\n"+ + "Forwarded: for=192.0.2.43,for=198.51.100.17;by=203.0.113.60;proto=http;host=example.com\n" + "X-Forwarded-For: 11.9.8.7:1111,8.5.4.3:2222\n" + - "\n"); + "\n")); - assertEquals("http",_results.poll()); - assertEquals("example.com",_results.poll()); - assertEquals("80",_results.poll()); - assertEquals("192.0.2.43",_results.poll()); - assertEquals("0",_results.poll()); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("example.com")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); + assertThat("remotePort", _remotePort.get(), is(0)); } - - + interface RequestTester { - boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException; + boolean check(HttpServletRequest request, HttpServletResponse response) throws IOException; } private class RequestHandler extends AbstractHandler { private RequestTester _checker; - @SuppressWarnings("unused") - private String _content; @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - ((Request)request).setHandled(true); + baseRequest.setHandled(true); - if (request.getContentLength()>0 - && !MimeTypes.Type.FORM_ENCODED.asString().equals(request.getContentType()) - && !request.getContentType().startsWith("multipart/form-data")) - _content=IO.toString(request.getInputStream()); - - if (_checker!=null && _checker.check(request,response)) + if (_checker != null && _checker.check(request, response)) response.setStatus(200); else response.sendError(500); From 345750f9fdc6673fdbf01545d4b0cad074e4d694 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Fri, 14 Jun 2019 12:28:58 -0500 Subject: [PATCH 6/8] Issue #3782 - X-Forwarded-Port refers to node listening port + Updating testcases to test requestURL as well. + Adding new testcases for X-Forwarded-Port modifying only the port of an existing `Host:` header. Signed-off-by: Joakim Erdfelt --- .../server/ForwardedRequestCustomizer.java | 24 ++++-- .../ForwardedRequestCustomizerTest.java | 78 ++++++++++++++++++- 2 files changed, 93 insertions(+), 9 deletions(-) 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 e098a68e635..e9320300153 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 @@ -22,7 +22,6 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.net.InetSocketAddress; - import javax.servlet.ServletRequest; import org.eclipse.jetty.http.HostPortHttpField; @@ -448,6 +447,8 @@ public class ForwardedRequestCustomizer implements Customizer size += 128; _handles = new ArrayTrie<>(size); + _handles.put(HttpHeader.HOST.toString(), lookup.findVirtual(Forwarded.class, "handleHttpHost", type)); + if (_forwardedCipherSuiteHeader != null && !_handles.put(_forwardedCipherSuiteHeader, lookup.findVirtual(Forwarded.class, "handleCipherSuite", type))) continue; if (_forwardedSslSessionIdHeader != null && !_handles.put(_forwardedSslSessionIdHeader, lookup.findVirtual(Forwarded.class, "handleSslSessionId", type))) @@ -513,6 +514,7 @@ public class ForwardedRequestCustomizer implements Customizer String _proto; HostPort _for; HostPort _host; + HostPort _httpHost; public Forwarded(Request request, HttpConfiguration config) { @@ -523,6 +525,13 @@ public class ForwardedRequestCustomizer implements Customizer _host = _forcedHost.getHostPort(); } + public void handleHttpHost(HttpField field) + { + _httpHost = new HostPort(field.getValue()); + if (_host != null && _host instanceof XHostPort && "unknown".equals(_host.getHost())) + _host = new XHostPort(_httpHost.getHost(), _host.getPort()); + } + public void handleCipherSuite(HttpField field) { _request.setAttribute("javax.servlet.request.cipher_suite", field.getValue()); @@ -547,6 +556,8 @@ public class ForwardedRequestCustomizer implements Customizer { if (_host==null) _host = new XHostPort(getLeftMost(field.getValue())); + else if (_host instanceof XHostPort && "unknown".equals(_host.getHost())) + _host = new XHostPort(getLeftMost(field.getValue()), _host.getPort()); } public void handleServer(HttpField field) @@ -571,10 +582,13 @@ public class ForwardedRequestCustomizer implements Customizer public void handlePort(HttpField field) { - if (_for == null) - _for = new XHostPort("unknown", field.getIntValue()); - else if (_for instanceof XHostPort && _for.getPort()<=0) - _for = new XHostPort(HostPort.normalizeHost(_for.getHost()), field.getIntValue()); + if (_host == null) + { + String hostname = _httpHost != null ? _httpHost.getHost() : "unknown"; + _host = new XHostPort(hostname, field.getIntValue()); + } + else if (_host instanceof XHostPort && _host.getPort()<=0) + _host = new XHostPort(HostPort.normalizeHost(_host.getHost()), field.getIntValue()); } public void handleHttps(HttpField field) 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 5c38e601d52..8f5ef3b0f81 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 @@ -49,6 +49,7 @@ public class ForwardedRequestCustomizerTest final AtomicReference _serverPort = new AtomicReference<>(); final AtomicReference _remoteAddr = new AtomicReference<>(); final AtomicReference _remotePort = new AtomicReference<>(); + final AtomicReference _requestURL = new AtomicReference<>(); ForwardedRequestCustomizer _customizer; @@ -77,6 +78,7 @@ public class ForwardedRequestCustomizerTest _serverPort.set(request.getServerPort()); _remoteAddr.set(request.getRemoteAddr()); _remotePort.set(request.getRemotePort()); + _requestURL.set(request.getRequestURL().toString()); return true; }; @@ -101,6 +103,7 @@ public class ForwardedRequestCustomizerTest assertThat("scheme", _scheme.get(), is("http")); assertThat("serverName", _serverName.get(), is("1.2.3.4")); assertThat("serverPort", _serverPort.get(), is(2222)); + assertThat("requestURL", _requestURL.get(), is("http://1.2.3.4:2222/")); } @Test @@ -115,6 +118,7 @@ public class ForwardedRequestCustomizerTest assertThat("scheme", _scheme.get(), is("http")); assertThat("serverName", _serverName.get(), is("[::1]")); assertThat("serverPort", _serverPort.get(), is(2222)); + assertThat("requestURL", _requestURL.get(), is("http://[::1]:2222/")); } @Test @@ -129,6 +133,7 @@ public class ForwardedRequestCustomizerTest assertThat("scheme", _scheme.get(), is("http")); assertThat("serverName", _serverName.get(), is("1.2.3.4")); assertThat("serverPort", _serverPort.get(), is(2222)); + assertThat("requestURL", _requestURL.get(), is("http://1.2.3.4:2222/")); } @Test @@ -143,6 +148,7 @@ public class ForwardedRequestCustomizerTest assertThat("scheme", _scheme.get(), is("http")); assertThat("serverName", _serverName.get(), is("[::1]")); assertThat("serverPort", _serverPort.get(), is(2222)); + assertThat("requestURL", _requestURL.get(), is("http://[::1]:2222/")); } /** @@ -168,6 +174,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("[2001:db8:cafe::17]")); assertThat("remotePort", _remotePort.get(), is(4711)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); } /** @@ -192,6 +199,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); // With spaces HttpTester.Response response2 = HttpTester.parseResponse( @@ -206,6 +214,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); // As multiple headers HttpTester.Response response3 = HttpTester.parseResponse( @@ -222,6 +231,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); } /** @@ -246,6 +256,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); // New syntax HttpTester.Response response2 = HttpTester.parseResponse( @@ -261,6 +272,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); } /** @@ -284,6 +296,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://example.com/")); } @Test @@ -303,6 +316,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(443)); assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("https://myhost/")); } @Test @@ -322,6 +336,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(443)); assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("https://myhost/")); } @Test @@ -341,6 +356,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("10.9.8.7")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); } @Test @@ -359,6 +375,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("10.9.8.7")); assertThat("remotePort", _remotePort.get(), is(1111)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); } @Test @@ -377,6 +394,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("[2001:db8:cafe::17]")); assertThat("remotePort", _remotePort.get(), is(1111)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); } @Test @@ -393,9 +411,10 @@ public class ForwardedRequestCustomizerTest assertThat("status", response.getStatus(), is(200)); assertThat("scheme", _scheme.get(), is("http")); assertThat("serverName", _serverName.get(), is("myhost")); - assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("serverPort", _serverPort.get(), is(2222)); assertThat("remoteAddr", _remoteAddr.get(), is("[1:2:3:4:5:6:7:8]")); - assertThat("remotePort", _remotePort.get(), is(2222)); + assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost:2222/")); } @Test @@ -414,9 +433,10 @@ public class ForwardedRequestCustomizerTest assertThat("status", response.getStatus(), is(200)); assertThat("scheme", _scheme.get(), is("http")); assertThat("serverName", _serverName.get(), is("myhost")); - assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("serverPort", _serverPort.get(), is(2222)); assertThat("remoteAddr", _remoteAddr.get(), is("[1:2:3:4:5:6:7:8]")); - assertThat("remotePort", _remotePort.get(), is(2222)); + assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost:2222/")); } @Test @@ -435,6 +455,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(443)); assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("https://myhost/")); } @Test @@ -456,6 +477,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); _customizer.setSslIsSecure(true); response = HttpTester.parseResponse( @@ -473,6 +495,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(443)); assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("https://myhost/")); } @Test @@ -494,6 +517,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); _customizer.setSslIsSecure(true); response = HttpTester.parseResponse( @@ -511,6 +535,51 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(443)); assertThat("remoteAddr", _remoteAddr.get(), is("0.0.0.0")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("https://myhost/")); + } + + /** + * Resetting the server port via a forwarding header + */ + @Test + public void testPort_For() throws Exception + { + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "X-Forwarded-Port: 4444\n" + + "X-Forwarded-For: 192.168.1.200\n" + + "\n")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(4444)); + assertThat("remoteAddr", _remoteAddr.get(), is("192.168.1.200")); + assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost:4444/")); + } + + /** + * Test setting the server Port before the "Host" header has been seen. + */ + @Test + public void testPort_For_LateHost() throws Exception + { + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "X-Forwarded-Port: 4444\n" + // this order is intentional + "X-Forwarded-For: 192.168.1.200\n" + + "Host: myhost\n" + // leave this as the last header + "\n")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(4444)); + assertThat("remoteAddr", _remoteAddr.get(), is("192.168.1.200")); + assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://myhost:4444/")); } @Test @@ -532,6 +601,7 @@ public class ForwardedRequestCustomizerTest assertThat("serverPort", _serverPort.get(), is(80)); assertThat("remoteAddr", _remoteAddr.get(), is("192.0.2.43")); assertThat("remotePort", _remotePort.get(), is(0)); + assertThat("requestURL", _requestURL.get(), is("http://example.com/")); } interface RequestTester From 9cf8cf3c0d60c7e92cf0239730183168e90a663b Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 17 Jun 2019 11:35:40 +0200 Subject: [PATCH 7/8] Issue #3782 X-Forwarded-Port can be remote or local Added option for X-Forwarded-Port to be remote or local with default being local. Signed-off-by: Greg Wilkins --- .../main/config/etc/jetty-http-forwarded.xml | 1 + .../main/config/modules/http-forwarded.mod | 1 + .../server/ForwardedRequestCustomizer.java | 93 ++++++++++++------- .../ForwardedRequestCustomizerTest.java | 25 +++++ 4 files changed, 89 insertions(+), 31 deletions(-) diff --git a/jetty-server/src/main/config/etc/jetty-http-forwarded.xml b/jetty-server/src/main/config/etc/jetty-http-forwarded.xml index 648d6c6a94f..8d0047cc54d 100644 --- a/jetty-server/src/main/config/etc/jetty-http-forwarded.xml +++ b/jetty-server/src/main/config/etc/jetty-http-forwarded.xml @@ -12,6 +12,7 @@ + diff --git a/jetty-server/src/main/config/modules/http-forwarded.mod b/jetty-server/src/main/config/modules/http-forwarded.mod index f67822065a4..7e6545a5902 100644 --- a/jetty-server/src/main/config/modules/http-forwarded.mod +++ b/jetty-server/src/main/config/modules/http-forwarded.mod @@ -24,6 +24,7 @@ etc/jetty-http-forwarded.xml # jetty.httpConfig.forwardedProtoHeader=X-Forwarded-Proto # jetty.httpConfig.forwardedForHeader=X-Forwarded-For # jetty.httpConfig.forwardedPortHeader=X-Forwarded-Port +# jetty.httpConfig.forwardedPortHeaderRemote=false # jetty.httpConfig.forwardedHttpsHeader=X-Proxied-Https # jetty.httpConfig.forwardedSslSessionIdHeader=Proxy-ssl-id # jetty.httpConfig.forwardedCipherSuiteHeader=Proxy-auth-cert 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 e9320300153..171384bd672 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 @@ -73,6 +73,7 @@ public class ForwardedRequestCustomizer implements Customizer private String _forwardedProtoHeader = HttpHeader.X_FORWARDED_PROTO.toString(); private String _forwardedForHeader = HttpHeader.X_FORWARDED_FOR.toString(); private String _forwardedPortHeader = HttpHeader.X_FORWARDED_PORT.toString(); + private boolean _forwardedPortHeaderRemote = false; private String _forwardedHttpsHeader = "X-Proxied-Https"; private String _forwardedCipherSuiteHeader = "Proxy-auth-cert"; private String _forwardedSslSessionIdHeader = "Proxy-ssl-id"; @@ -251,6 +252,16 @@ public class ForwardedRequestCustomizer implements Customizer } } + public boolean isForwardedPortHeaderRemote() + { + return _forwardedPortHeaderRemote; + } + + public void setForwardedPortHeaderRemote(boolean forwardedPortHeaderRemote) + { + _forwardedPortHeaderRemote = forwardedPortHeaderRemote; + } + /** * Get the forwardedProtoHeader. * @@ -447,8 +458,6 @@ public class ForwardedRequestCustomizer implements Customizer size += 128; _handles = new ArrayTrie<>(size); - _handles.put(HttpHeader.HOST.toString(), lookup.findVirtual(Forwarded.class, "handleHttpHost", type)); - if (_forwardedCipherSuiteHeader != null && !_handles.put(_forwardedCipherSuiteHeader, lookup.findVirtual(Forwarded.class, "handleCipherSuite", type))) continue; if (_forwardedSslSessionIdHeader != null && !_handles.put(_forwardedSslSessionIdHeader, lookup.findVirtual(Forwarded.class, "handleSslSessionId", type))) @@ -484,14 +493,22 @@ public class ForwardedRequestCustomizer implements Customizer } } - private static class XHostPort extends HostPort + private static class PossiblyPartialHostPort extends HostPort { - XHostPort(String authority) + PossiblyPartialHostPort(String authority) { super(authority); } - XHostPort(String host, int port) + protected PossiblyPartialHostPort(String host, int port) + { + super(host, port); + } + } + + private static class PortSetHostPort extends PossiblyPartialHostPort + { + PortSetHostPort(String host, int port) { super(host, port); } @@ -514,7 +531,6 @@ public class ForwardedRequestCustomizer implements Customizer String _proto; HostPort _for; HostPort _host; - HostPort _httpHost; public Forwarded(Request request, HttpConfiguration config) { @@ -525,13 +541,6 @@ public class ForwardedRequestCustomizer implements Customizer _host = _forcedHost.getHostPort(); } - public void handleHttpHost(HttpField field) - { - _httpHost = new HostPort(field.getValue()); - if (_host != null && _host instanceof XHostPort && "unknown".equals(_host.getHost())) - _host = new XHostPort(_httpHost.getHost(), _host.getPort()); - } - public void handleCipherSuite(HttpField field) { _request.setAttribute("javax.servlet.request.cipher_suite", field.getValue()); @@ -554,16 +563,24 @@ public class ForwardedRequestCustomizer implements Customizer public void handleHost(HttpField field) { - if (_host==null) - _host = new XHostPort(getLeftMost(field.getValue())); - else if (_host instanceof XHostPort && "unknown".equals(_host.getHost())) - _host = new XHostPort(getLeftMost(field.getValue()), _host.getPort()); + if (!_forwardedPortHeaderRemote && !StringUtil.isEmpty(_forwardedPortHeader)) + { + if (_host == null) + _host = new PossiblyPartialHostPort(getLeftMost(field.getValue())); + else if (_for instanceof PortSetHostPort) + _host = new HostPort(HostPort.normalizeHost(getLeftMost(field.getValue())), _host.getPort()); + } + else if (_host==null) + { + _host = new HostPort(getLeftMost(field.getValue())); + } } public void handleServer(HttpField field) { - if (_proxyAsAuthority && _host==null) - _host = new XHostPort(getLeftMost(field.getValue())); + if (_proxyAsAuthority) + return; + handleHost(field); } public void handleProto(HttpField field) @@ -574,21 +591,35 @@ public class ForwardedRequestCustomizer implements Customizer public void handleFor(HttpField field) { - if (_for==null) - _for = new XHostPort(getLeftMost(field.getValue())); - else if (_for instanceof XHostPort && "unknown".equals(_for.getHost())) - _for = new XHostPort(HostPort.normalizeHost(getLeftMost(field.getValue())),_for.getPort()); + if (_forwardedPortHeaderRemote && !StringUtil.isEmpty(_forwardedPortHeader)) + { + if (_for == null) + _for = new PossiblyPartialHostPort(getLeftMost(field.getValue())); + else if (_for instanceof PortSetHostPort) + _for = new HostPort(HostPort.normalizeHost(getLeftMost(field.getValue())), _for.getPort()); + } + else if (_for == null) + { + _for = new HostPort(getLeftMost(field.getValue())); + } } public void handlePort(HttpField field) { - if (_host == null) + if (_forwardedPortHeaderRemote) { - String hostname = _httpHost != null ? _httpHost.getHost() : "unknown"; - _host = new XHostPort(hostname, field.getIntValue()); + if (_for == null) + _for = new PortSetHostPort(_request.getRemoteHost(), field.getIntValue()); + else if (_for instanceof PossiblyPartialHostPort && _for.getPort() <= 0) + _for = new HostPort(HostPort.normalizeHost(_for.getHost()), field.getIntValue()); + } + else + { + if (_host == null) + _host = new PortSetHostPort(_request.getServerName(), field.getIntValue()); + else if (_host instanceof PossiblyPartialHostPort && _host.getPort() <= 0) + _host = new HostPort(HostPort.normalizeHost(_host.getHost()), field.getIntValue()); } - else if (_host instanceof XHostPort && _host.getPort()<=0) - _host = new XHostPort(HostPort.normalizeHost(_host.getHost()), field.getIntValue()); } public void handleHttps(HttpField field) @@ -616,19 +647,19 @@ public class ForwardedRequestCustomizer implements Customizer break; if (value.startsWith("_") || "unknown".equals(value)) break; - if (_host == null || _host instanceof XHostPort) + if (_host == null || !(_host instanceof Rfc7239HostPort)) _host = new Rfc7239HostPort(value); break; case "for": if (value.startsWith("_") || "unknown".equals(value)) break; - if (_for == null || _for instanceof XHostPort) + if (_for == null || !(_for instanceof Rfc7239HostPort)) _for = new Rfc7239HostPort(value); break; case "host": if (value.startsWith("_") || "unknown".equals(value)) break; - if (_host == null || _host instanceof XHostPort) + if (_host == null || !(_host instanceof Rfc7239HostPort)) _host = new Rfc7239HostPort(value); break; case "proto": 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 8f5ef3b0f81..61181da2efc 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 @@ -560,6 +560,31 @@ public class ForwardedRequestCustomizerTest assertThat("requestURL", _requestURL.get(), is("http://myhost:4444/")); } + + + /** + * Resetting the server port via a forwarding header + */ + @Test + public void testRemote_Port_For() throws Exception + { + _customizer.setForwardedPortHeaderRemote(true); + HttpTester.Response response = HttpTester.parseResponse( + _connector.getResponse( + "GET / HTTP/1.1\n" + + "Host: myhost\n" + + "X-Forwarded-Port: 4444\n" + + "X-Forwarded-For: 192.168.1.200\n" + + "\n")); + assertThat("status", response.getStatus(), is(200)); + assertThat("scheme", _scheme.get(), is("http")); + assertThat("serverName", _serverName.get(), is("myhost")); + assertThat("serverPort", _serverPort.get(), is(80)); + assertThat("remoteAddr", _remoteAddr.get(), is("192.168.1.200")); + assertThat("remotePort", _remotePort.get(), is(4444)); + assertThat("requestURL", _requestURL.get(), is("http://myhost/")); + } + /** * Test setting the server Port before the "Host" header has been seen. */ From e7e63a5617ffca484a1b1349f8c90eb826605023 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 17 Jun 2019 14:00:30 +0200 Subject: [PATCH 8/8] Issue #3782 X-Forwarded-Port can be remote or local Improved names and javadoc after review. Signed-off-by: Greg Wilkins --- .../main/config/etc/jetty-http-forwarded.xml | 2 +- .../main/config/modules/http-forwarded.mod | 8 ++++- .../server/ForwardedRequestCustomizer.java | 29 ++++++++++++------- .../ForwardedRequestCustomizerTest.java | 2 +- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/jetty-server/src/main/config/etc/jetty-http-forwarded.xml b/jetty-server/src/main/config/etc/jetty-http-forwarded.xml index 8d0047cc54d..2c843733c2a 100644 --- a/jetty-server/src/main/config/etc/jetty-http-forwarded.xml +++ b/jetty-server/src/main/config/etc/jetty-http-forwarded.xml @@ -6,13 +6,13 @@ + - diff --git a/jetty-server/src/main/config/modules/http-forwarded.mod b/jetty-server/src/main/config/modules/http-forwarded.mod index 7e6545a5902..e6303cd992e 100644 --- a/jetty-server/src/main/config/modules/http-forwarded.mod +++ b/jetty-server/src/main/config/modules/http-forwarded.mod @@ -16,15 +16,21 @@ etc/jetty-http-forwarded.xml [ini-template] ### ForwardedRequestCustomizer Configuration +## If true, only the RFC7239 Forwarded header is accepted # jetty.httpConfig.forwardedOnly=false + +## if true, the proxy address obtained from X-Forwarded-Server or RFC7239 is used as the request authority. # jetty.httpConfig.forwardedProxyAsAuthority=false + +## if true, the X-Forwarded-Port header applies to the authority, else it applies to the remote client address +# jetty.httpConfig.forwardedPortAsAuthority=true + # jetty.httpConfig.forwardedHeader=Forwarded # jetty.httpConfig.forwardedHostHeader=X-Forwarded-Host # jetty.httpConfig.forwardedServerHeader=X-Forwarded-Server # jetty.httpConfig.forwardedProtoHeader=X-Forwarded-Proto # jetty.httpConfig.forwardedForHeader=X-Forwarded-For # jetty.httpConfig.forwardedPortHeader=X-Forwarded-Port -# jetty.httpConfig.forwardedPortHeaderRemote=false # jetty.httpConfig.forwardedHttpsHeader=X-Proxied-Https # jetty.httpConfig.forwardedSslSessionIdHeader=Proxy-ssl-id # jetty.httpConfig.forwardedCipherSuiteHeader=Proxy-auth-cert 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 171384bd672..141af6eaaf4 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 @@ -67,17 +67,17 @@ public class ForwardedRequestCustomizer implements Customizer private static final Logger LOG = Log.getLogger(ForwardedRequestCustomizer.class); private HostPortHttpField _forcedHost; + private boolean _proxyAsAuthority = false; + private boolean _forwardedPortAsAuthority = true; private String _forwardedHeader = HttpHeader.FORWARDED.toString(); private String _forwardedHostHeader = HttpHeader.X_FORWARDED_HOST.toString(); private String _forwardedServerHeader = HttpHeader.X_FORWARDED_SERVER.toString(); private String _forwardedProtoHeader = HttpHeader.X_FORWARDED_PROTO.toString(); private String _forwardedForHeader = HttpHeader.X_FORWARDED_FOR.toString(); private String _forwardedPortHeader = HttpHeader.X_FORWARDED_PORT.toString(); - private boolean _forwardedPortHeaderRemote = false; private String _forwardedHttpsHeader = "X-Proxied-Https"; private String _forwardedCipherSuiteHeader = "Proxy-auth-cert"; private String _forwardedSslSessionIdHeader = "Proxy-ssl-id"; - private boolean _proxyAsAuthority = false; private boolean _sslIsSecure = true; private Trie _handles; @@ -252,14 +252,23 @@ public class ForwardedRequestCustomizer implements Customizer } } - public boolean isForwardedPortHeaderRemote() + /** + * @return if true, the X-Forwarded-Port header applies to the authority, + * else it applies to the remote client address + */ + public boolean getForwardedPortAsAuthority() { - return _forwardedPortHeaderRemote; + return _forwardedPortAsAuthority; } - public void setForwardedPortHeaderRemote(boolean forwardedPortHeaderRemote) + /** + * Set if the X-Forwarded-Port header will be used for Authority + * @param forwardedPortAsAuthority if true, the X-Forwarded-Port header applies to the authority, + * else it applies to the remote client address + */ + public void setForwardedPortAsAuthority(boolean forwardedPortAsAuthority) { - _forwardedPortHeaderRemote = forwardedPortHeaderRemote; + _forwardedPortAsAuthority = forwardedPortAsAuthority; } /** @@ -563,7 +572,7 @@ public class ForwardedRequestCustomizer implements Customizer public void handleHost(HttpField field) { - if (!_forwardedPortHeaderRemote && !StringUtil.isEmpty(_forwardedPortHeader)) + if (_forwardedPortAsAuthority && !StringUtil.isEmpty(_forwardedPortHeader)) { if (_host == null) _host = new PossiblyPartialHostPort(getLeftMost(field.getValue())); @@ -591,7 +600,7 @@ public class ForwardedRequestCustomizer implements Customizer public void handleFor(HttpField field) { - if (_forwardedPortHeaderRemote && !StringUtil.isEmpty(_forwardedPortHeader)) + if (!_forwardedPortAsAuthority && !StringUtil.isEmpty(_forwardedPortHeader)) { if (_for == null) _for = new PossiblyPartialHostPort(getLeftMost(field.getValue())); @@ -606,7 +615,7 @@ public class ForwardedRequestCustomizer implements Customizer public void handlePort(HttpField field) { - if (_forwardedPortHeaderRemote) + if (!_forwardedPortAsAuthority) { if (_for == null) _for = new PortSetHostPort(_request.getRemoteHost(), field.getIntValue()); @@ -647,7 +656,7 @@ public class ForwardedRequestCustomizer implements Customizer break; if (value.startsWith("_") || "unknown".equals(value)) break; - if (_host == null || !(_host instanceof Rfc7239HostPort)) + if (_proxyAsAuthority && (_host == null || !(_host instanceof Rfc7239HostPort))) _host = new Rfc7239HostPort(value); break; case "for": 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 61181da2efc..c5537eaa2e0 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 @@ -568,7 +568,7 @@ public class ForwardedRequestCustomizerTest @Test public void testRemote_Port_For() throws Exception { - _customizer.setForwardedPortHeaderRemote(true); + _customizer.setForwardedPortAsAuthority(false); HttpTester.Response response = HttpTester.parseResponse( _connector.getResponse( "GET / HTTP/1.1\n" +