diff --git a/pom.xml b/pom.xml
index e5df2f0b..75cd33a2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,6 +57,12 @@
spring-boot-starter-test
test
+
+ io.projectreactor.addons
+ reactor-test
+ ${reactor.version}
+ test
+
diff --git a/src/main/java/org/springframework/cloud/gateway/GatewayConfiguration.java b/src/main/java/org/springframework/cloud/gateway/GatewayAutoConfiguration.java
similarity index 97%
rename from src/main/java/org/springframework/cloud/gateway/GatewayConfiguration.java
rename to src/main/java/org/springframework/cloud/gateway/GatewayAutoConfiguration.java
index 807e5459..5227494b 100644
--- a/src/main/java/org/springframework/cloud/gateway/GatewayConfiguration.java
+++ b/src/main/java/org/springframework/cloud/gateway/GatewayAutoConfiguration.java
@@ -13,7 +13,7 @@ import org.springframework.web.client.reactive.WebClient;
*/
@Configuration
@EnableConfigurationProperties
-public class GatewayConfiguration {
+public class GatewayAutoConfiguration {
@Bean
@ConditionalOnMissingBean
diff --git a/src/main/java/org/springframework/cloud/gateway/GatewayFilter.java b/src/main/java/org/springframework/cloud/gateway/GatewayFilter.java
index ed04cdfb..0b93f83f 100644
--- a/src/main/java/org/springframework/cloud/gateway/GatewayFilter.java
+++ b/src/main/java/org/springframework/cloud/gateway/GatewayFilter.java
@@ -33,6 +33,7 @@ public interface GatewayFilter {
String GATEWAY_ROUTE_ATTR = "gatewayRoute";
String GATEWAY_REQUEST_URL_ATTR = "requestUrl";
+ String GATEWAY_HANDLER_MAPPER_ATTR = "gatewayHandlerMapper";
/**
* Process the Web request and (optionally) delegate to the next
diff --git a/src/main/java/org/springframework/cloud/gateway/GatewayHostHandlerMapping.java b/src/main/java/org/springframework/cloud/gateway/GatewayHostHandlerMapping.java
index 0f9a6e2b..e6f7aac4 100644
--- a/src/main/java/org/springframework/cloud/gateway/GatewayHostHandlerMapping.java
+++ b/src/main/java/org/springframework/cloud/gateway/GatewayHostHandlerMapping.java
@@ -45,6 +45,7 @@ public class GatewayHostHandlerMapping extends AbstractHandlerMapping {
@Override
protected Mono> getHandlerInternal(ServerWebExchange exchange) {
+ exchange.getAttributes().put(GatewayFilter.GATEWAY_HANDLER_MAPPER_ATTR, getClass().getSimpleName());
String host = exchange.getRequest().getHeaders().getFirst("Host");
Object handler;
try {
diff --git a/src/main/java/org/springframework/cloud/gateway/GatewayUrlHandlerMapping.java b/src/main/java/org/springframework/cloud/gateway/GatewayUrlHandlerMapping.java
index e06f493e..df288515 100644
--- a/src/main/java/org/springframework/cloud/gateway/GatewayUrlHandlerMapping.java
+++ b/src/main/java/org/springframework/cloud/gateway/GatewayUrlHandlerMapping.java
@@ -35,6 +35,8 @@ public class GatewayUrlHandlerMapping extends AbstractUrlHandlerMapping {
return super.getHandler(exchange).map(o -> {
if (o instanceof RouteHolder) {
RouteHolder holder = (RouteHolder) o;
+ exchange.getAttributes().put(GatewayFilter.GATEWAY_HANDLER_MAPPER_ATTR,
+ GatewayUrlHandlerMapping.this.getClass().getSimpleName());
exchange.getAttributes().put(GatewayFilter.GATEWAY_ROUTE_ATTR, holder.route);
return holder.webHandler;
}
diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..a1d57170
--- /dev/null
+++ b/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.springframework.cloud.gateway.GatewayAutoConfiguration
diff --git a/src/test/java/org/springframework/cloud/gateway/GatewayApplication.java b/src/test/java/org/springframework/cloud/gateway/GatewayApplication.java
index 8adcaeb3..d473c787 100644
--- a/src/test/java/org/springframework/cloud/gateway/GatewayApplication.java
+++ b/src/test/java/org/springframework/cloud/gateway/GatewayApplication.java
@@ -1,50 +1,13 @@
package org.springframework.cloud.gateway;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Import;
-import org.springframework.core.annotation.Order;
-import org.springframework.web.server.ServerWebExchange;
-import reactor.core.publisher.Mono;
-
-//TODO: move to autoconfig
-@Import(GatewayConfiguration.class)
@SpringBootConfiguration
@EnableAutoConfiguration
public class GatewayApplication {
- private static final Log log = LogFactory.getLog(GatewayApplication.class);
-
- @Bean
- @Order(501)
- public GatewayFilter modifyResponseFilter() {
- return (exchange, chain) -> {
- log.info("modifyResponseFilter start");
- exchange.getResponse().getHeaders().add("X-My-Custom", "MyCustomValue");
- return chain.filter(exchange);
- };
- }
-
- @Bean
- @Order(502)
- public GatewayFilter postFilter() {
- return (exchange, chain) -> {
- log.info("postFilter start");
- return chain.filter(exchange).then(postFilterWork(exchange));
- };
- }
-
- private static Mono postFilterWork(ServerWebExchange exchange) {
- log.info("postFilterWork");
- exchange.getResponse().getHeaders().add("X-Post-Header", "AddedAfterRoute");
- return Mono.empty();
- }
-
public static void main(String[] args) {
new SpringApplicationBuilder()
.sources(GatewayApplication.class)
diff --git a/src/test/java/org/springframework/cloud/gateway/GatewayApplicationTests.java b/src/test/java/org/springframework/cloud/gateway/GatewayApplicationTests.java
index 2bbc595b..d235103e 100644
--- a/src/test/java/org/springframework/cloud/gateway/GatewayApplicationTests.java
+++ b/src/test/java/org/springframework/cloud/gateway/GatewayApplicationTests.java
@@ -1,16 +1,109 @@
package org.springframework.cloud.gateway;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.client.reactive.ClientResponse;
+import org.springframework.web.client.reactive.WebClient;
+import org.springframework.web.server.ServerWebExchange;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
+import static org.springframework.web.client.reactive.ClientRequest.GET;
+
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
@RunWith(SpringRunner.class)
-@SpringBootTest
+@SpringBootTest(webEnvironment = RANDOM_PORT)
public class GatewayApplicationTests {
+ public static final String HANDLER_MAPPER_HEADER = "X-Gateway-Handler-Mapper-Class";
+ @LocalServerPort
+ private int port;
+
+ private WebClient webClient = WebClient.builder(new ReactorClientHttpConnector()).build();
+
@Test
- public void contextLoads() {
+ public void urlRouteWorks() {
+ Mono result = webClient.exchange(
+ GET("http://localhost:" + port + "/get").build()
+ );
+
+ StepVerifier
+ .create(result.map(response -> response.headers().asHttpHeaders()))
+ .consumeNextWith(
+ httpHeaders -> {
+ assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER))
+ .isEqualTo(GatewayUrlHandlerMapping.class.getSimpleName());
+ })
+ .expectComplete()
+ .verify();
+ }
+
+ @Test
+ public void hostRouteWorks() {
+ Mono result = webClient.exchange(
+ GET("http://localhost:" + port + "/get")
+ .header("Host", "www.example.org")
+ .build()
+ );
+
+ StepVerifier
+ .create(result)
+ .consumeNextWith(
+ response -> {
+ HttpHeaders httpHeaders = response.headers().asHttpHeaders();
+ HttpStatus statusCode = response.statusCode();
+ assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER))
+ .isEqualTo(GatewayHostHandlerMapping.class.getSimpleName());
+ assertThat(statusCode).isEqualTo(HttpStatus.OK);
+ })
+ .expectComplete()
+ .verify();
+ }
+
+ @SpringBootApplication
+ public static class TestConfig {
+
+ private static final Log log = LogFactory.getLog(TestConfig.class);
+
+ @Bean
+ @Order(501)
+ public GatewayFilter modifyResponseFilter() {
+ return (exchange, chain) -> {
+ log.info("modifyResponseFilter start");
+ String value = (String) exchange.getAttribute(GatewayFilter.GATEWAY_HANDLER_MAPPER_ATTR).orElse("N/A");
+ exchange.getResponse().getHeaders().add(HANDLER_MAPPER_HEADER, value);
+ return chain.filter(exchange);
+ };
+ }
+
+ @Bean
+ @Order(502)
+ public GatewayFilter postFilter() {
+ return (exchange, chain) -> {
+ log.info("postFilter start");
+ return chain.filter(exchange).then(postFilterWork(exchange));
+ };
+ }
+
+ private static Mono postFilterWork(ServerWebExchange exchange) {
+ log.info("postFilterWork");
+ exchange.getResponse().getHeaders().add("X-Post-Header", "AddedAfterRoute");
+ return Mono.empty();
+ }
+
}
}