Use host header when constructing the forwarded header. Fixes #1333

This commit is contained in:
Ryan Baxter
2019-11-20 17:52:10 -05:00
parent c21af28986
commit e803b3a89f
4 changed files with 60 additions and 18 deletions

View File

@@ -52,6 +52,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.bind.annotation.RequestBody;
@@ -405,11 +406,14 @@ public class ProxyExchange<T> {
else {
forwarded = "";
}
forwarded = forwarded + forwarded(uri);
forwarded = forwarded + forwarded(uri, webRequest.getHeader("host"));
headers.set("forwarded", forwarded);
}
private String forwarded(URI uri) {
private String forwarded(URI uri, String hostHeader) {
if (!StringUtils.isEmpty(hostHeader)) {
return "host=" + hostHeader;
}
if ("http".equals(uri.getScheme())) {
return "host=" + uri.getHost();
}

View File

@@ -110,7 +110,7 @@ public class ProductionConfigurationTests {
@Test
public void post() throws Exception {
assertThat(rest.postForObject("/proxy/0", Collections.singletonMap("name", "foo"),
Bar.class).getName()).isEqualTo("host=localhost;foo");
Bar.class).getName()).isEqualTo("host=localhost:" + port + ";foo");
}
@Test
@@ -190,13 +190,14 @@ public class ProductionConfigurationTests {
.body(Collections
.singletonList(Collections.singletonMap("name", "foo"))),
new ParameterizedTypeReference<List<Bar>>() {
}).getBody().iterator().next().getName()).isEqualTo("host=localhost;foo");
}).getBody().iterator().next().getName())
.isEqualTo("host=localhost:" + port + ";foo");
}
@Test
public void bodyless() throws Exception {
assertThat(rest.postForObject("/proxy/0", Collections.singletonMap("name", "foo"),
Bar.class).getName()).isEqualTo("host=localhost;foo");
Bar.class).getName()).isEqualTo("host=localhost:" + port + ";foo");
}
@Test
@@ -207,7 +208,8 @@ public class ProductionConfigurationTests {
.expand("/proxy/entity"))
.body(Collections.singletonMap("name", "foo")),
new ParameterizedTypeReference<List<Bar>>() {
}).getBody().iterator().next().getName()).isEqualTo("host=localhost;foo");
}).getBody().iterator().next().getName())
.isEqualTo("host=localhost:" + port + ";foo");
}
@Test
@@ -218,21 +220,22 @@ public class ProductionConfigurationTests {
.expand("/proxy/type"))
.body(Collections.singletonMap("name", "foo")),
new ParameterizedTypeReference<List<Bar>>() {
}).getBody().iterator().next().getName()).isEqualTo("host=localhost;foo");
}).getBody().iterator().next().getName())
.isEqualTo("host=localhost:" + port + ";foo");
}
@Test
public void single() throws Exception {
assertThat(rest.postForObject("/proxy/single",
Collections.singletonMap("name", "foobar"), Bar.class).getName())
.isEqualTo("host=localhost;foobar");
.isEqualTo("host=localhost:" + port + ";foobar");
}
@Test
public void converter() throws Exception {
assertThat(rest.postForObject("/proxy/converter",
Collections.singletonMap("name", "foobar"), Bar.class).getName())
.isEqualTo("host=localhost;foobar");
.isEqualTo("host=localhost:" + port + ";foobar");
}
@Test
@@ -255,6 +258,20 @@ public class ProductionConfigurationTests {
assertThat(headers.get("abc")).containsOnly("123");
}
@Test
public void forwardedHeaderUsesHost() throws Exception {
Map<String, List<String>> headers = rest
.exchange(RequestEntity
.get(rest.getRestTemplate().getUriTemplateHandler()
.expand("/proxy/headers"))
.header("host", "foo:1234").build(), Map.class)
.getBody();
assertThat(headers).containsKey("forwarded");
assertThat(headers.get("forwarded").size()).isEqualTo(1);
assertThat(headers.get("forwarded").get(0)).isEqualTo("host=localhost:" + port);
}
@SpringBootApplication
static class TestApplication {

View File

@@ -35,6 +35,7 @@ import org.springframework.http.RequestEntity;
import org.springframework.http.RequestEntity.BodyBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
@@ -396,11 +397,15 @@ public class ProxyExchange<T> {
else {
forwarded = "";
}
forwarded = forwarded + forwarded(uri);
forwarded = forwarded
+ forwarded(uri, exchange.getRequest().getHeaders().getFirst("host"));
headers.set("forwarded", forwarded);
}
private String forwarded(URI uri) {
private String forwarded(URI uri, String hostHeader) {
if (!StringUtils.isEmpty(hostHeader)) {
return "host=" + hostHeader;
}
if ("http".equals(uri.getScheme())) {
return "host=" + uri.getHost();
}

View File

@@ -114,7 +114,7 @@ public class ProductionConfigurationTests {
@Test
public void post() throws Exception {
assertThat(rest.postForObject("/proxy/0", Collections.singletonMap("name", "foo"),
Bar.class).getName()).isEqualTo("host=localhost;foo");
Bar.class).getName()).isEqualTo("host=localhost:" + port + ";foo");
}
@Test
@@ -130,13 +130,13 @@ public class ProductionConfigurationTests {
new ParameterizedTypeReference<List<Bar>>() {
});
assertThat(result.getBody().iterator().next().getName())
.isEqualTo("host=localhost;foo");
.isEqualTo("host=localhost:" + port + ";foo");
}
@Test
public void bodyless() throws Exception {
assertThat(rest.postForObject("/proxy/0", Collections.singletonMap("name", "foo"),
Bar.class).getName()).isEqualTo("host=localhost;foo");
Bar.class).getName()).isEqualTo("host=localhost:" + port + ";foo");
}
@Test
@@ -147,7 +147,8 @@ public class ProductionConfigurationTests {
.expand("/proxy/entity"))
.body(Collections.singletonMap("name", "foo")),
new ParameterizedTypeReference<List<Bar>>() {
}).getBody().iterator().next().getName()).isEqualTo("host=localhost;foo");
}).getBody().iterator().next().getName())
.isEqualTo("host=localhost:" + port + ";foo");
}
@Test
@@ -158,21 +159,22 @@ public class ProductionConfigurationTests {
.expand("/proxy/type"))
.body(Collections.singletonMap("name", "foo")),
new ParameterizedTypeReference<List<Bar>>() {
}).getBody().iterator().next().getName()).isEqualTo("host=localhost;foo");
}).getBody().iterator().next().getName())
.isEqualTo("host=localhost:" + port + ";foo");
}
@Test
public void single() throws Exception {
assertThat(rest.postForObject("/proxy/single",
Collections.singletonMap("name", "foobar"), Bar.class).getName())
.isEqualTo("host=localhost;foobar");
.isEqualTo("host=localhost:" + port + ";foobar");
}
@Test
public void converter() throws Exception {
assertThat(rest.postForObject("/proxy/converter",
Collections.singletonMap("name", "foobar"), Bar.class).getName())
.isEqualTo("host=localhost;foobar");
.isEqualTo("host=localhost:" + port + ";foobar");
}
@Test
@@ -189,6 +191,20 @@ public class ProductionConfigurationTests {
assertThat(headers.get("abc")).containsOnly("123");
}
@Test
public void forwardedHeaderUsesHost() throws Exception {
Map<String, List<String>> headers = rest
.exchange(RequestEntity
.get(rest.getRestTemplate().getUriTemplateHandler()
.expand("/proxy/headers"))
.header("host", "foo:1234").build(), Map.class)
.getBody();
assertThat(headers).containsKey("forwarded");
assertThat(headers.get("forwarded").size()).isEqualTo(1);
assertThat(headers.get("forwarded").get(0)).isEqualTo("host=localhost:" + port);
}
@SpringBootApplication
static class TestApplication {