diff --git a/spring-cloud-function-gateway/src/main/java/org/springframework/cloud/function/gateway/ProxyExchange.java b/spring-cloud-function-gateway/src/main/java/org/springframework/cloud/function/gateway/ProxyExchange.java index 525866101..a8764f7e9 100644 --- a/spring-cloud-function-gateway/src/main/java/org/springframework/cloud/function/gateway/ProxyExchange.java +++ b/spring-cloud-function-gateway/src/main/java/org/springframework/cloud/function/gateway/ProxyExchange.java @@ -366,6 +366,7 @@ public class ProxyExchange { if (sensitive == null) { sensitive = DEFAULT_SENSITIVE; } + proxy(); for (String name : headers.keySet()) { if (sensitive.contains(name.toLowerCase())) { continue; @@ -375,6 +376,53 @@ public class ProxyExchange { return builder; } + private void proxy() { + try { + URI uri = new URI(webRequest.getNativeRequest(HttpServletRequest.class) + .getRequestURL().toString()); + appendForwarded(uri); + appendXForwarded(uri); + } + catch (URISyntaxException e) { + throw new IllegalStateException("Cannot create URI for request: " + webRequest + .getNativeRequest(HttpServletRequest.class).getRequestURL()); + } + } + + private void appendXForwarded(URI uri) { + // Append the legacy headers if they were already added upstream + String host = headers.getFirst("x-forwarded-host"); + if (host == null) { + return; + } + host = host + "," + uri.getHost(); + headers.set("x-forwarded-host", host); + String proto = headers.getFirst("x-forwarded-proto"); + if (proto == null) { + return; + } + proto = proto + "," + uri.getScheme(); + headers.set("x-forwarded-proto", proto); + } + + private void appendForwarded(URI uri) { + String forwarded = headers.getFirst("forwarded"); + if (forwarded != null) { + forwarded = forwarded + ","; + } else { + forwarded = ""; + } + forwarded = forwarded + forwarded(uri); + headers.set("forwarded", forwarded); + } + + private String forwarded(URI uri) { + if ("http".equals(uri.getScheme())) { + return "host=" + uri.getHost(); + } + return String.format("host=%s;proto=%s", uri.getHost(), uri.getScheme()); + } + private Object body() { if (body != null) { return body; diff --git a/spring-cloud-function-gateway/src/test/java/org/springframework/cloud/function/web/gateway/ProductionConfigurationTests.java b/spring-cloud-function-gateway/src/test/java/org/springframework/cloud/function/web/gateway/ProductionConfigurationTests.java index 0edfd95cf..ec2772920 100644 --- a/spring-cloud-function-gateway/src/test/java/org/springframework/cloud/function/web/gateway/ProductionConfigurationTests.java +++ b/spring-cloud-function-gateway/src/test/java/org/springframework/cloud/function/web/gateway/ProductionConfigurationTests.java @@ -111,7 +111,7 @@ public class ProductionConfigurationTests { @Test public void post() throws Exception { assertThat(rest.postForObject("/proxy/0", Collections.singletonMap("name", "foo"), - Bar.class).getName()).isEqualTo("foo"); + Bar.class).getName()).isEqualTo("host=localhost;foo"); } @Test @@ -186,13 +186,13 @@ public class ProductionConfigurationTests { "/proxy")) .body(Collections.singletonList(Collections.singletonMap("name", "foo"))), new ParameterizedTypeReference>() { - }).getBody().iterator().next().getName()).isEqualTo("foo"); + }).getBody().iterator().next().getName()).isEqualTo("host=localhost;foo"); } @Test public void bodyless() throws Exception { assertThat(rest.postForObject("/proxy/0", Collections.singletonMap("name", "foo"), - Bar.class).getName()).isEqualTo("foo"); + Bar.class).getName()).isEqualTo("host=localhost;foo"); } @Test @@ -203,7 +203,7 @@ public class ProductionConfigurationTests { .expand("/proxy/entity")) .body(Collections.singletonMap("name", "foo")), new ParameterizedTypeReference>() { - }).getBody().iterator().next().getName()).isEqualTo("foo"); + }).getBody().iterator().next().getName()).isEqualTo("host=localhost;foo"); } @Test @@ -214,21 +214,21 @@ public class ProductionConfigurationTests { .expand("/proxy/type")) .body(Collections.singletonMap("name", "foo")), new ParameterizedTypeReference>() { - }).getBody().iterator().next().getName()).isEqualTo("foo"); + }).getBody().iterator().next().getName()).isEqualTo("host=localhost;foo"); } @Test public void single() throws Exception { assertThat(rest.postForObject("/proxy/single", Collections.singletonMap("name", "foobar"), Bar.class).getName()) - .isEqualTo("foobar"); + .isEqualTo("host=localhost;foobar"); } @Test public void converter() throws Exception { assertThat(rest.postForObject("/proxy/converter", Collections.singletonMap("name", "foobar"), Bar.class).getName()) - .isEqualTo("foobar"); + .isEqualTo("host=localhost;foobar"); } @SpringBootApplication @@ -394,6 +394,7 @@ public class ProductionConfigurationTests { @RequestHeader HttpHeaders headers) { String custom = headers.getFirst("X-Custom"); custom = custom == null ? "" : custom; + custom = headers.getFirst("forwarded")==null ? custom : headers.getFirst("forwarded") + ";" + custom; return Arrays.asList(new Bar(custom + foos.iterator().next().getName())); }