diff --git a/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java index 360b3255..5eaa5433 100644 --- a/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java +++ b/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java @@ -13,6 +13,7 @@ import org.springframework.cloud.gateway.filter.factory.AddRequestHeaderFilterFa import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderFilterFactory; import org.springframework.cloud.gateway.filter.factory.FilterFactory; import org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter; +import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderFilterFactory; import org.springframework.cloud.gateway.filter.factory.RewritePathFilterFactory; import org.springframework.cloud.gateway.handler.GatewayFilteringWebHandler; import org.springframework.cloud.gateway.handler.GatewayPredicateHandlerMapping; @@ -121,6 +122,11 @@ public class GatewayAutoConfiguration { return new AddResponseHeaderFilterFactory(); } + @Bean + public RemoveRequestHeaderFilterFactory removeRequestHeaderFilterFactory() { + return new RemoveRequestHeaderFilterFactory(); + } + @Bean public RewritePathFilterFactory rewritePathFilterFactory() { return new RewritePathFilterFactory(); diff --git a/src/main/java/org/springframework/cloud/gateway/filter/OrderedGatewayFilter.java b/src/main/java/org/springframework/cloud/gateway/filter/OrderedGatewayFilter.java index abeafe6d..865ab78d 100644 --- a/src/main/java/org/springframework/cloud/gateway/filter/OrderedGatewayFilter.java +++ b/src/main/java/org/springframework/cloud/gateway/filter/OrderedGatewayFilter.java @@ -27,4 +27,13 @@ public class OrderedGatewayFilter implements GatewayFilter, Ordered { public int getOrder() { return this.order; } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("OrderedGatewayFilter{"); + sb.append("delegate=").append(delegate); + sb.append(", order=").append(order); + sb.append('}'); + return sb.toString(); + } } diff --git a/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderFilterFactory.java b/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderFilterFactory.java new file mode 100644 index 00000000..3e0e4556 --- /dev/null +++ b/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderFilterFactory.java @@ -0,0 +1,28 @@ +package org.springframework.cloud.gateway.filter.factory; + +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.http.server.reactive.ServerHttpRequest; + +/** + * @author Spencer Gibb + */ +public class RemoveRequestHeaderFilterFactory implements FilterFactory { + + public static final String FAKE_HEADER = "_______force_______"; + + @Override + public GatewayFilter apply(String header, String[] args) { + + //TODO: caching can happen here + return (exchange, chain) -> { + ServerHttpRequest request = exchange.getRequest().mutate() + .header(FAKE_HEADER, "mutable") //TODO: is there a better way? + .build(); + + request.getHeaders().remove(FAKE_HEADER); + request.getHeaders().remove(header); + + return chain.filter(exchange.mutate().request(request).build()); + }; + } +} diff --git a/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java b/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java index 8a02b9fb..e4305928 100644 --- a/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java +++ b/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java @@ -149,10 +149,11 @@ public class GatewayIntegrationTests { } @Test + @SuppressWarnings("unchecked") public void addRequestHeaderFilterWorks() { Mono result = webClient.exchange( GET("http://localhost:" + port + "/headers") - .header("Host", "www.bar.org") + .header("Host", "www.addrequestheader.org") .build() ).then(response -> response.body(toMono(Map.class))); @@ -169,6 +170,29 @@ public class GatewayIntegrationTests { ); } + @Test + @SuppressWarnings("unchecked") + public void removeRequestHeaderFilterWorks() { + Mono result = webClient.exchange( + GET("http://localhost:" + port + "/headers") + .header("Host", "www.removerequestheader.org") + .header("X-Request-Foo", "Bar") + .build() + ).then(response -> response.body(toMono(Map.class))); + + verify( () -> + StepVerifier.create(result) + .consumeNextWith( + response -> { + assertThat(response).containsKey("headers").isInstanceOf(Map.class); + Map headers = (Map) response.get("headers"); + assertThat(headers).doesNotContainKey("X-Request-Foo"); + }) + .expectComplete() + .verify(Duration.ofSeconds(3)) + ); + } + @Test public void postWorks() { ClientRequest> request = POST("http://localhost:" + port + "/post") @@ -222,7 +246,7 @@ public class GatewayIntegrationTests { private static final Log log = LogFactory.getLog(TestConfig.class); @Bean - @Order(501) + @Order(500) public GatewayFilter modifyResponseFilter() { return (exchange, chain) -> { log.info("modifyResponseFilter start"); @@ -237,7 +261,7 @@ public class GatewayIntegrationTests { } @Bean - @Order(502) + @Order(-1) public GatewayFilter postFilter() { return (exchange, chain) -> { log.info("postFilter start"); diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 997af119..0656bc4d 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -24,11 +24,20 @@ spring: - id: add_request_header_test uri: http://httpbin.org:80 predicates: - - Host=**.bar.org + - Host=**.addrequestheader.org - Url=/headers filters: - AddRequestHeader=X-Request-Foo, Bar + # ===================================== + - id: remove_request_header_test + uri: http://httpbin.org:80 + predicates: + - Host=**.removerequestheader.org + - Url=/headers + filters: + - RemoveRequestHeader=X-Request-Foo + # ===================================== - id: rewrite_path_test uri: http://httpbin.org:80