From 79b7635a6fbe99ca4c84d60ee25496e49c09317b Mon Sep 17 00:00:00 2001 From: Zbynek Vavros Date: Mon, 20 May 2019 18:08:17 +0200 Subject: [PATCH] Apply X-Forwarded headers during location transformation. To support SOAP services behind load balancers and proxies, honor the de facto X-Forwarded-Proto, X-Forwarded-Host, and X-Forwarded-Port headers. Resolves #150. Related: #132. --- .../LocationTransformerObjectSupport.java | 13 ++++++- .../WsdlDefinitionHandlerAdapterTest.java | 39 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) 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 05a97b8b..f97a2695 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 @@ -87,8 +87,17 @@ public abstract class LocationTransformerObjectSupport extends TransformerObject * 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()); + + String xForwardedProto = request.getHeader("X-Forwarded-Proto"); + String xForwardedHost = request.getHeader("X-Forwarded-Host"); + String xForwardedPort = request.getHeader("X-Forwarded-Port"); + + String scheme = StringUtils.hasText(xForwardedProto) ? xForwardedProto : request.getScheme(); + String serverName = StringUtils.hasText(xForwardedHost) ? xForwardedHost : request.getServerName(); + int serverPort = StringUtils.hasText(xForwardedPort) ? Integer.valueOf(xForwardedPort) : request.getServerPort(); + + StringBuilder url = new StringBuilder(scheme); + url.append("://").append(serverName).append(':').append(serverPort); if (location.startsWith("/")) { // a relative path, prepend the context path url.append(request.getContextPath()).append(location); 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 8e4c28ea..b1312455 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 @@ -244,4 +244,43 @@ public class WsdlDefinitionHandlerAdapterTest { XmlAssert.assertThat(resultingDocument).and(expectedDocument).ignoreWhitespace().areIdentical(); } + + @Test + public void handlesForwardedHeadersInRequest() { + + // given + request.setScheme("http"); + request.setServerName("example.com"); + request.setServerPort(80); + request.setContextPath("/context"); + request.setPathInfo("/service.wsdl"); + + request.addHeader("X-Forwarded-Proto", "https"); + request.addHeader("X-Forwarded-Host", "loadbalancer.com"); + request.addHeader("X-Forwarded-Port", "8080"); + + // when + String result = adapter.transformLocation("/service", request); + + // then + assertThat(URI.create("https://loadbalancer.com:8080/context/service")).isEqualTo(URI.create(result)); + } + + @Test + public void handlesNoForwardedHeadersInRequest() { + + // given + request.setScheme("http"); + request.setServerName("example.com"); + request.setServerPort(80); + request.setContextPath("/context"); + request.setPathInfo("/service.wsdl"); + + // when + String result = adapter.transformLocation("/service", request); + + // then + assertThat(URI.create("http://example.com:80/context/service")).isEqualTo(URI.create(result)); + } + }