From 2c77de10dd820c94e0ae48836991f6943d62a600 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Fri, 11 Jul 2014 00:55:17 +0200 Subject: [PATCH] Fix X-Forwarded-* behavior in ServletUriComponentsBuilder When using ServletUriComponentsBuilder.fromRequest, this change makes sure that: * the default port is used when the "X-Forwarded-Host" header is set and no port is defined in that header value * to use the scheme defined in the "X-Forwarded-Proto" header if set Issue: SPR-11872 --- .../support/ServletUriComponentsBuilder.java | 6 +++++ .../ServletUriComponentsBuilderTests.java | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/ServletUriComponentsBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/ServletUriComponentsBuilder.java index d9879dbe6f..47110b2ba5 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/ServletUriComponentsBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/ServletUriComponentsBuilder.java @@ -111,6 +111,7 @@ public class ServletUriComponentsBuilder extends UriComponentsBuilder { } else { host = hostToUse; + port = -1; } } @@ -119,6 +120,11 @@ public class ServletUriComponentsBuilder extends UriComponentsBuilder { port = Integer.parseInt(portHeader); } + String protocolHeader = request.getHeader("X-Forwarded-Proto"); + if (StringUtils.hasText(protocolHeader)) { + scheme = protocolHeader; + } + ServletUriComponentsBuilder builder = new ServletUriComponentsBuilder(); builder.scheme(scheme); builder.host(host); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/support/ServletUriComponentsBuilderTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/support/ServletUriComponentsBuilderTests.java index 16560cec29..5933cc4022 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/support/ServletUriComponentsBuilderTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/support/ServletUriComponentsBuilderTests.java @@ -133,6 +133,33 @@ public class ServletUriComponentsBuilderTests { assertEquals(9090, uriComponents.getPort()); } + // SPR-11872 + + @Test + public void fromRequestWithForwardedHostWithDefaultPort() { + this.request.setServerPort(10080); + this.request.addHeader("X-Forwarded-Host", "example.org"); + UriComponents result = ServletUriComponentsBuilder.fromRequest(request).build(); + + assertEquals("example.org", result.getHost()); + assertEquals("should have used the default port of the forwarded request", + -1, result.getPort()); + } + + @Test + public void fromRequestWithForwardedHostWithForwardedScheme() { + this.request.setServerPort(10080); + this.request.addHeader("X-Forwarded-Proto", "https"); + this.request.addHeader("X-Forwarded-Host", "example.org"); + UriComponents result = ServletUriComponentsBuilder.fromRequest(request).build(); + + assertEquals("example.org", result.getHost()); + assertEquals("should have derived scheme from header", + "https", result.getScheme()); + assertEquals("should have used the default port of the forwarded request", + -1, result.getPort()); + } + @Test public void fromContextPath() { request.setRequestURI("/mvc-showcase/data/param");