Rewrite response header filter factory.
This commit is contained in:
@@ -620,6 +620,24 @@ spring:
|
||||
|
||||
For a request path of `/foo/bar`, this will set the path to `/bar` before making the downstream request. Notice the `$\` which is replaced with `$` because of the YAML spec.
|
||||
|
||||
=== RewriteResponseHeader GatewayFilter Factory
|
||||
The RewriteResponseHeader GatewayFilter Factory takes `name`, `regexp`, and `replacement` parameters. It uses Java regular expressions for a flexible way to rewrite the response header value.
|
||||
|
||||
.application.yml
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
cloud:
|
||||
gateway:
|
||||
routes:
|
||||
- id: rewriteresponseheader_route
|
||||
uri: http://example.org
|
||||
filters:
|
||||
- RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***
|
||||
----
|
||||
|
||||
For a header value of `/42?user=ford&password=omg!what&flag=true`, it will be set to `/42?user=ford&password=\***&flag=true` before making the downstream request. Please use `$\` to mean `$` because of the YAML spec.
|
||||
|
||||
=== SaveSession GatewayFilter Factory
|
||||
The SaveSession GatewayFilter Factory forces a `WebSession::save` operation _before_ forwarding the call downstream. This is of particular use when
|
||||
using something like http://projects.spring.io/spring-session/[Spring Session] with a lazy data store and need to ensure the session state has been saved before making the forwarded call.
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.function.Consumer;
|
||||
import com.netflix.hystrix.HystrixObservableCommand;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.ipc.netty.http.client.HttpClient;
|
||||
@@ -55,28 +56,6 @@ import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
|
||||
import org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter;
|
||||
import org.springframework.cloud.gateway.filter.WebsocketRoutingFilter;
|
||||
import org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter;
|
||||
import org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.AddRequestParameterGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.HystrixGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUriGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SecureHeadersProperties;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetRequestHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.headers.ForwardedHeadersFilter;
|
||||
@@ -575,6 +554,11 @@ public class GatewayAutoConfiguration {
|
||||
return new SetResponseHeaderGatewayFilterFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RewriteResponseHeaderGatewayFilterFactory rewriteResponseHeaderGatewayFilterFactory() {
|
||||
return new RewriteResponseHeaderGatewayFilterFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SetStatusGatewayFilterFactory setStatusGatewayFilterFactory() {
|
||||
return new SetStatusGatewayFilterFactory();
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.gateway.filter.factory;
|
||||
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Vitaliy Pavlyuk
|
||||
*/
|
||||
public class RewriteResponseHeaderGatewayFilterFactory extends AbstractGatewayFilterFactory<RewriteResponseHeaderGatewayFilterFactory.Config> {
|
||||
|
||||
public static final String REGEXP_KEY = "regexp";
|
||||
public static final String REPLACEMENT_KEY = "replacement";
|
||||
|
||||
public RewriteResponseHeaderGatewayFilterFactory() {
|
||||
super(Config.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> shortcutFieldOrder() {
|
||||
return Arrays.asList(NAME_KEY, REGEXP_KEY, REPLACEMENT_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GatewayFilter apply(Config config) {
|
||||
return (exchange, chain) -> chain.filter(exchange).then(Mono.fromRunnable(() -> {
|
||||
rewriteHeader(exchange, config);
|
||||
}));
|
||||
}
|
||||
|
||||
protected void rewriteHeader(ServerWebExchange exchange, Config config) {
|
||||
final String name = config.getName();
|
||||
final String value = exchange.getResponse().getHeaders().getFirst(name);
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
final String newValue = rewrite(value, config.getRegexp(), config.getReplacement());
|
||||
exchange.getResponse().getHeaders().set(name, newValue);
|
||||
}
|
||||
|
||||
String rewrite(String value, String regexp, String replacement) {
|
||||
return value.replaceAll(regexp, replacement.replace("$\\", "$"));
|
||||
}
|
||||
|
||||
public static class Config extends AbstractGatewayFilterFactory.NameConfig {
|
||||
private String regexp;
|
||||
private String replacement;
|
||||
|
||||
public String getRegexp() {
|
||||
return regexp;
|
||||
}
|
||||
|
||||
public Config setRegexp(String regexp) {
|
||||
this.regexp = regexp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getReplacement() {
|
||||
return replacement;
|
||||
}
|
||||
|
||||
public Config setReplacement(String replacement) {
|
||||
this.replacement = replacement;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,33 +29,13 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.*;
|
||||
import reactor.retry.Repeat;
|
||||
import reactor.retry.Retry;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.factory.AbstractChangeRequestUriGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.AddRequestParameterGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.HystrixGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUriGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetRequestHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
|
||||
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
|
||||
@@ -475,6 +455,18 @@ public class GatewayFilterSpec extends UriSpec {
|
||||
.apply(c -> c.setName(headerName).setValue(headerValue)));
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter that rewrites a header value on the response before it is returned to the client by the Gateway.
|
||||
* @param headerName the header name
|
||||
* @param regex a Java regular expression to match the path against
|
||||
* @param replacement the replacement for the path
|
||||
* @return a {@link GatewayFilterSpec} that can be used to apply additional filters
|
||||
*/
|
||||
public GatewayFilterSpec rewriteResponseHeader(String headerName, String regex, String replacement) {
|
||||
return filter(getBean(RewriteResponseHeaderGatewayFilterFactory.class)
|
||||
.apply(c -> c.setReplacement(replacement).setRegexp(regex).setName(headerName)));
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter that sets the status on the response before it is returned to the client by the Gateway.
|
||||
* @param status the status to set on the response
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.gateway.filter.factory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.gateway.test.BaseWebClientTests;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT)
|
||||
@DirtiesContext
|
||||
public class RewriteResponseHeaderGatewayFilterFactoryTests extends BaseWebClientTests {
|
||||
|
||||
@Test
|
||||
public void rewriteResponseHeaderFilterWorks() {
|
||||
testClient.get()
|
||||
.uri("/headers")
|
||||
.header("Host", "www.rewriteresponseheader.org")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().valueEquals("X-Request-Foo", "/42?user=ford&password=***&flag=true");
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@SpringBootConfiguration
|
||||
@Import(DefaultTestConfig.class)
|
||||
public static class TestConfig { }
|
||||
|
||||
}
|
||||
@@ -25,21 +25,7 @@ import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
import org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.AddRequestParameterGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.HystrixGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactoryIntegrationTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactoryIntegrationTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactoryTests;
|
||||
import org.springframework.cloud.gateway.filter.factory.*;
|
||||
import org.springframework.cloud.gateway.filter.headers.ForwardedHeadersFilterTests;
|
||||
import org.springframework.cloud.gateway.filter.headers.RemoveHopByHopHeadersFilterTests;
|
||||
import org.springframework.cloud.gateway.filter.headers.XForwardedHeadersFilterTests;
|
||||
@@ -89,6 +75,7 @@ import static org.junit.Assume.assumeThat;
|
||||
SetPathGatewayFilterFactoryIntegrationTests.class,
|
||||
AddRequestParameterGatewayFilterFactoryTests.class,
|
||||
SetResponseHeaderGatewayFilterFactoryTests.class,
|
||||
RewriteResponseHeaderGatewayFilterFactoryTests.class,
|
||||
PrincipalNameKeyResolverIntegrationTests.class,
|
||||
RedisRateLimiterTests.class,
|
||||
RouteDefinitionRouteLocatorTests.class,
|
||||
|
||||
@@ -65,6 +65,16 @@ spring:
|
||||
filters:
|
||||
- AddResponseHeader=X-Request-Foo, Bar
|
||||
|
||||
# =====================================
|
||||
- id: rewrite_response_header_test
|
||||
uri: ${test.uri}
|
||||
predicates:
|
||||
- Host=**.rewriteresponseheader.org
|
||||
- Path=/headers
|
||||
filters:
|
||||
- AddResponseHeader=X-Request-Foo, /42?user=ford&password=omg!what&flag=true
|
||||
- RewriteResponseHeader=X-Request-Foo, password=[^&]+, password=***
|
||||
|
||||
# =====================================
|
||||
- id: forward_test
|
||||
uri: forward:/localcontroller
|
||||
|
||||
Reference in New Issue
Block a user