diff --git a/.gitignore b/.gitignore index daccec5c5..b262f25e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.swp *.ipr *.iws *.iml @@ -22,4 +23,4 @@ _site *.versionsBackup -credentials.yml \ No newline at end of file +credentials.yml diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/LocationTransformerObjectSupport.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/LocationTransformerObjectSupport.java index f62e2f42f..f9271c16d 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/LocationTransformerObjectSupport.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/LocationTransformerObjectSupport.java @@ -41,6 +41,9 @@ public abstract class LocationTransformerObjectSupport extends TransformerObject /** Logger available to subclasses. */ private final Log logger = LogFactory.getLog(getClass()); + private boolean checkForwardedHeaders = false; + private String XForwardedHostHeader = "X-Forwarded-Host"; + private String XForwardedProtoHeader = "X-Forwarded-Proto"; /** * Transforms the locations of the given definition document using the given XPath expression. @@ -86,8 +89,12 @@ protected void transformLocations(XPathExpression xPathExpression, *

This method is only called when the {@code transformLocations} property is true. */ protected String transformLocation(String location, HttpServletRequest request) { - StringBuilder url = new StringBuilder(request.getScheme()); - url.append("://").append(request.getServerName()).append(':').append(request.getServerPort()); + StringBuilder url = new StringBuilder(); + if (this.checkForwardedHeaders && this.headersValid(request)) { + url.append(request.getHeader(this.XForwardedProtoHeader)).append("://").append(request.getHeader(this.XForwardedHostHeader)); + } else { + url.append(request.getScheme()).append("://").append(request.getServerName()).append(':').append(request.getServerPort()); + } if (location.startsWith("/")) { // a relative path, prepend the context path url.append(request.getContextPath()).append(location); @@ -108,4 +115,22 @@ protected String transformLocation(String location, HttpServletRequest request) // unknown location, return the original return location; } + + /** + * Helper to check that the headers exist and aren't empty + */ + private boolean headersValid(HttpServletRequest request) { + return request.getHeader(this.XForwardedHostHeader) != null && + !"".equals(request.getHeader(this.XForwardedHostHeader)) && + request.getHeader(this.XForwardedProtoHeader) != null && + !"".equals(request.getHeader(this.XForwardedProtoHeader)); + } + + /** + * Enable checking the X-Forwarded-* headers to build transform the location. + * Defaults to {@code false} + */ + public void setCheckForwardedHeaders(boolean check) { + this.checkForwardedHeaders = check; + } } diff --git a/spring-ws-core/src/test/java/org/springframework/ws/transport/http/WsdlDefinitionHandlerAdapterTest.java b/spring-ws-core/src/test/java/org/springframework/ws/transport/http/WsdlDefinitionHandlerAdapterTest.java index 5ba2216c4..53ecdc5e3 100644 --- a/spring-ws-core/src/test/java/org/springframework/ws/transport/http/WsdlDefinitionHandlerAdapterTest.java +++ b/spring-ws-core/src/test/java/org/springframework/ws/transport/http/WsdlDefinitionHandlerAdapterTest.java @@ -226,4 +226,42 @@ public void handleSimpleWsdl11DefinitionWithTransformLocation() throws Exception assertXMLEqual("Invalid WSDL returned", expectedDocument, resultingDocument); } -} \ No newline at end of file + @Test + public void handleReverseProxyRequestCheckOn() throws Exception { + adapter.setCheckForwardedHeaders(true); + request.setScheme("http"); + request.setServerName("example.com"); + request.setServerPort(8080); + request.setContextPath("/context"); + request.setPathInfo("/service.wsdl"); + request.setRequestURI("/context/service.wsdl"); + request.addHeader("X-Forwarded-Host", "loadbalancer.com"); + request.addHeader("X-Forwarded-Proto", "https"); + String oldLocation = "/service"; + + String result = adapter.transformLocation(oldLocation, request); + Assert.assertNotNull("No result", result); + Assert.assertEquals("Invalid result", new URI("https://loadbalancer.com/context/service"), new URI(result)); + + } + + @Test + public void handleReverseProxyRequestCheckOff() throws Exception { + adapter.setCheckForwardedHeaders(false); + request.setScheme("http"); + request.setServerName("example.com"); + request.setServerPort(8080); + request.setContextPath("/context"); + request.setPathInfo("/service.wsdl"); + request.setRequestURI("/context/service.wsdl"); + request.addHeader("X-Forwarded-Host", "loadbalancer.com"); + request.addHeader("X-Forwarded-Proto", "https"); + String oldLocation = "/service"; + + String result = adapter.transformLocation(oldLocation, request); + Assert.assertNotNull("No result", result); + Assert.assertEquals("Invalid result", new URI("http://example.com:8080/context/service"), new URI(result)); + + } + +}