Merge branch '2.1.x'

This commit is contained in:
Spencer Gibb
2019-07-24 14:30:41 -04:00
8 changed files with 615 additions and 0 deletions

View File

@@ -841,6 +841,34 @@ 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.
=== RewriteLocationResponseHeader GatewayFilter Factory
The RewriteLocationResponseHeader GatewayFilter Factory modifies the value of `Location` response header, usually to get rid of backend specific details. It takes `stripVersionMode`, `locationHeaderName`, `hostValue`, and `protocolsRegex` parameters.
.application.yml
[source,yaml]
----
spring:
cloud:
gateway:
routes:
- id: rewritelocationresponseheader_route
uri: http://example.org
filters:
- RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,
----
For example, for a request `POST https://api.example.com/some/object/name`, `Location` response header value `https://object-service.prod.example.net/v2/some/object/id` will be rewritten as `https://api.example.com/some/object/id`.
Parameter `stripVersionMode` has the following possible values: `NEVER_STRIP`, `AS_IN_REQUEST` (default), `ALWAYS_STRIP`.
* `NEVER_STRIP` - Version will not be stripped, even if the original request path contains no version
* `AS_IN_REQUEST` - Version will be stripped only if the original request path contains no version
* `ALWAYS_STRIP` - Version will be stripped, even if the original request path contains version
Parameter `hostValue`, if provided, will be used to replace the `host:port` portion of the response `Location` header. If not provided, the value of the `Host` request header will be used.
Parameter `protocolsRegex` must be a valid regex `String`, against which the protocol name will be matched. If not matched, the filter will do nothing. Default is `http|https|ftp|ftps`.
=== 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.

View File

@@ -79,6 +79,7 @@ import org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUr
import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewriteResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactory;
@@ -502,6 +503,11 @@ public class GatewayAutoConfiguration {
return new RewriteResponseHeaderGatewayFilterFactory();
}
@Bean
public RewriteLocationResponseHeaderGatewayFilterFactory rewriteLocationResponseHeaderGatewayFilterFactory() {
return new RewriteLocationResponseHeaderGatewayFilterFactory();
}
@Bean
public SetStatusGatewayFilterFactory setStatusGatewayFilterFactory() {
return new SetStatusGatewayFilterFactory();

View File

@@ -0,0 +1,269 @@
/*
* 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
*
* https://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 java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import reactor.core.publisher.Mono;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.http.HttpHeaders;
import org.springframework.web.server.ServerWebExchange;
import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator;
/*
This filter intent is to modify the value of Location response header, ridding it of backend specific details.
Typical scenario: POST response from a legacy backend contains a Location header with backend's hostname.
You want to replace the backend's hostname:port with your documented gateway's hostname:port.
Additionally, sometimes backend returns a 'versioned' Location, and you may want to strip the version portion.
Note that the protocol portion of the URL will not be replaced by this filter. If you need that too,
either follow this filter with a generic rewrite response header filter, or subclass this filter.
Configuration parameters:
- stripVersion
NEVER_STRIP - Version will not be stripped, even if the original request path contains no version
AS_IN_REQUEST - Default. Version will be stripped only if the original request path contains no version
ALWAYS_STRIP - Version will be stripped, even if the original request path contains version
- locationHeaderName
String representing a custom location header name. Default - Location
- hostValue
A String. If provided, will be used to replace the host:port portion of the response Location header.
Default - The value of request Host header is used to replace.
- protocols
A valid regex String, against which the protocol name will be matched. If not matched, the filter will do nothing.
Default - https?|ftps? (which is the same as http|https|ftp|ftps)
Example 1
default-filters:
- RewriteLocationResponseHeader
Host request header: api.example.com:443
POST request path: /some/object/name
Location response header: https://object-service.prod.example.net/v2/some/object/id
Modified Location response header: https://api.example.com:443/some/object/id
Example 2
default-filters:
- name: RewriteLocationResponseHeader
args:
stripVersion: ALWAYS_STRIP
locationHeaderName: Link
hostValue: example-api.com
Host request header (irrelevant): api.example.com:443
POST request path: /v1/some/object/name
Link response header: https://object-service.prod.example.net/v1/some/object/id
Modified Link response header: https://example-api.com/some/object/id
Example 3
default-filters:
- name: RewriteLocationResponseHeader
args:
stripVersion: NEVER_STRIP
protocols: https|ftps # only replace host:port for https or ftps, but not http or ftp
Host request header: api.example.com:443
1. POST request path: /some/object/name
Location response header: https://object-service.prod.example.net/v1/some/object/id
Modified Location response header: https://api.example.com/v1/some/object/id
2. POST request path: /some/other/object/name
Location response header: http://object-service.prod.example.net/v1/some/object/id
Modified (not) Location response header: http://object-service.prod.example.net/v1/some/object/id
*/
/**
* @author Vitaliy Pavlyuk
*/
public class RewriteLocationResponseHeaderGatewayFilterFactory extends
AbstractGatewayFilterFactory<RewriteLocationResponseHeaderGatewayFilterFactory.Config> {
private static final String STRIP_VERSION_KEY = "stripVersion";
private static final String LOCATION_HEADER_NAME_KEY = "locationHeaderName";
private static final String HOST_VALUE_KEY = "hostValue";
private static final String PROTOCOLS_KEY = "protocols";
private static final Pattern VERSIONED_PATH = Pattern.compile("^/v\\d+/.*");
private static final String DEFAULT_PROTOCOLS = "https?|ftps?";
private static final Pattern DEFAULT_HOST_PORT = compileHostPortPattern(
DEFAULT_PROTOCOLS);
private static final Pattern DEFAULT_HOST_PORT_VERSION = compileHostPortVersionPattern(
DEFAULT_PROTOCOLS);
public RewriteLocationResponseHeaderGatewayFilterFactory() {
super(Config.class);
}
private static Pattern compileHostPortPattern(String protocols) {
return Pattern.compile("(?<=^(?:" + protocols + ")://)[^:/]+(?::\\d+)?(?=/)");
}
private static Pattern compileHostPortVersionPattern(String protocols) {
return Pattern.compile(
"(?<=^(?:" + protocols + ")://)[^:/]+(?::\\d+)?(?:/v\\d+)?(?=/)");
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(STRIP_VERSION_KEY, LOCATION_HEADER_NAME_KEY, HOST_VALUE_KEY,
PROTOCOLS_KEY);
}
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange,
GatewayFilterChain chain) {
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> rewriteLocation(exchange, config)));
}
@Override
public String toString() {
// @formatter:off
return filterToStringCreator(
RewriteLocationResponseHeaderGatewayFilterFactory.this)
.append("stripVersion", config.stripVersion)
.append("locationHeaderName", config.locationHeaderName)
.append("hostValue", config.hostValue)
.append("protocols", config.protocols)
.toString();
// @formatter:on
}
};
}
void rewriteLocation(ServerWebExchange exchange, Config config) {
final String location = exchange.getResponse().getHeaders()
.getFirst(config.getLocationHeaderName());
final String host = config.getHostValue() != null ? config.getHostValue()
: exchange.getRequest().getHeaders().getFirst(HttpHeaders.HOST);
final String path = exchange.getRequest().getURI().getPath();
if (location != null && host != null) {
final String fixedLocation = fixedLocation(location, host, path,
config.getStripVersion(), config.getHostPortPattern(),
config.getHostPortVersionPattern());
exchange.getResponse().getHeaders().set(config.getLocationHeaderName(),
fixedLocation);
}
}
String fixedLocation(String location, String host, String path,
StripVersion stripVersion, Pattern hostPortPattern,
Pattern hostPortVersionPattern) {
final boolean doStrip = StripVersion.ALWAYS_STRIP.equals(stripVersion)
|| (StripVersion.AS_IN_REQUEST.equals(stripVersion)
&& !VERSIONED_PATH.matcher(path).matches());
final Pattern pattern = doStrip ? hostPortVersionPattern : hostPortPattern;
return pattern.matcher(location).replaceFirst(host);
}
public enum StripVersion {
/**
* Version will not be stripped, even if the original request path contains no
* version.
*/
NEVER_STRIP,
/**
* Version will be stripped only if the original request path contains no version.
* This is the Default.
*/
AS_IN_REQUEST,
/**
* Version will be stripped, even if the original request path contains version.
*/
ALWAYS_STRIP
}
public static class Config {
private StripVersion stripVersion = StripVersion.AS_IN_REQUEST;
private String locationHeaderName = HttpHeaders.LOCATION;
private String hostValue;
private String protocols = DEFAULT_PROTOCOLS;
private Pattern hostPortPattern = DEFAULT_HOST_PORT;
private Pattern hostPortVersionPattern = DEFAULT_HOST_PORT_VERSION;
public StripVersion getStripVersion() {
return stripVersion;
}
public Config setStripVersion(StripVersion stripVersion) {
this.stripVersion = stripVersion;
return this;
}
public String getLocationHeaderName() {
return locationHeaderName;
}
public Config setLocationHeaderName(String locationHeaderName) {
this.locationHeaderName = locationHeaderName;
return this;
}
public String getHostValue() {
return hostValue;
}
public Config setHostValue(String hostValue) {
this.hostValue = hostValue;
return this;
}
public String getProtocols() {
return protocols;
}
public Config setProtocols(String protocols) {
this.protocols = protocols;
this.hostPortPattern = compileHostPortPattern(protocols);
this.hostPortVersionPattern = compileHostPortVersionPattern(protocols);
return this;
}
public Pattern getHostPortPattern() {
return hostPortPattern;
}
public Pattern getHostPortVersionPattern() {
return hostPortVersionPattern;
}
}
}

View File

@@ -55,6 +55,8 @@ import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewa
import org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactory.StripVersion;
import org.springframework.cloud.gateway.filter.factory.RewriteResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory;
@@ -579,6 +581,24 @@ public class GatewayFilterSpec extends UriSpec {
c -> c.setReplacement(replacement).setRegexp(regex).setName(headerName)));
}
/**
* A filter that rewrites the value of Location response header, ridding it of backend
* specific details.
* @param stripVersionMode NEVER_STRIP, AS_IN_REQUEST, or ALWAYS_STRIP
* @param locationHeaderName a location header name
* @param hostValue host value
* @param protocolsRegex a valid regex String, against which the protocol name will be
* matched
* @return a {@link GatewayFilterSpec} that can be used to apply additional filters
*/
public GatewayFilterSpec rewriteLocationResponseHeader(String stripVersionMode,
String locationHeaderName, String hostValue, String protocolsRegex) {
return filter(getBean(RewriteLocationResponseHeaderGatewayFilterFactory.class)
.apply(c -> c.setStripVersion(StripVersion.valueOf(stripVersionMode))
.setLocationHeaderName(locationHeaderName).setHostValue(hostValue)
.setProtocols(protocolsRegex)));
}
/**
* A filter that sets the status on the response before it is returned to the client
* by the Gateway.

View File

@@ -0,0 +1,53 @@
/*
* 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
*
* https://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 RewriteLocationResponseHeaderGatewayFilterFactoryTests
extends BaseWebClientTests {
@Test
public void rewriteLocationResponseHeaderFilterWorks() {
testClient.post().uri("/headers")
.header("Host", "test1.rewritelocationresponseheader.org").exchange()
.expectStatus().isOk().expectHeader().valueEquals("Location",
"https://test1.rewritelocationresponseheader.org/some/object/id");
}
@EnableAutoConfiguration
@SpringBootConfiguration
@Import(DefaultTestConfig.class)
public static class TestConfig {
}
}

View File

@@ -0,0 +1,227 @@
/*
* 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
*
* https://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 java.net.URI;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactory.Config;
import org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactory.StripVersion;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(MockitoJUnitRunner.class)
public class RewriteLocationResponseHeaderGatewayFilterFactoryUnitTests {
@InjectMocks
private RewriteLocationResponseHeaderGatewayFilterFactory filter;
@Mock
private ServerWebExchange exchange;
@Mock
private ServerHttpRequest request;
@Mock
private ServerHttpResponse response;
@Mock
private HttpHeaders requestHeaders;
@Mock
private HttpHeaders responseHeaders;
private URI uri;
private Config config;
@Before
public void setUp() {
filter = new RewriteLocationResponseHeaderGatewayFilterFactory();
Mockito.when(exchange.getRequest()).thenReturn(request);
Mockito.when(exchange.getResponse()).thenReturn(response);
Mockito.when(request.getHeaders()).thenReturn(requestHeaders);
Mockito.when(response.getHeaders()).thenReturn(responseHeaders);
config = new Config();
}
private void setupTest(String location, String host, String path) {
Mockito.when(responseHeaders.getFirst(HttpHeaders.LOCATION)).thenReturn(location);
Mockito.when(requestHeaders.getFirst(HttpHeaders.HOST)).thenReturn(host);
uri = URI.create("http://" + host + path);
Mockito.when(request.getURI()).thenReturn(uri);
}
@Test
public void rewriteLocationNullLocation() {
setupTest(null, "host", "/path");
filter.rewriteLocation(exchange, config);
Mockito.verify(responseHeaders, Mockito.never()).set(Mockito.anyString(),
Mockito.anyString());
}
@Test
public void rewriteLocationNullHost() {
setupTest("location", null, "/path");
filter.rewriteLocation(exchange, config);
Mockito.verify(responseHeaders, Mockito.never()).set(Mockito.anyString(),
Mockito.anyString());
}
@Test
public void rewriteLocation() {
setupTest("location", "host", "/path");
filter.rewriteLocation(exchange, config);
Mockito.verify(responseHeaders).set(Mockito.eq("Location"),
Mockito.eq("location"));
}
@Test
public void rewriteLocationCustomHeaderName() {
setupTest("location", "host", "/path");
Mockito.when(responseHeaders.getFirst("Link")).thenReturn("link");
config.setLocationHeaderName("Link");
filter.rewriteLocation(exchange, config);
Mockito.verify(responseHeaders).set(Mockito.eq("Link"), Mockito.eq("link"));
}
@Test
public void rewriteLocationCustomHostValue() {
setupTest("https://replaceme/some/path", "host", "/some/path");
config.setHostValue("different.host");
filter.rewriteLocation(exchange, config);
Mockito.verify(responseHeaders).set(Mockito.eq("Location"),
Mockito.eq("https://different.host/some/path"));
}
@Test
public void rewriteLocationCustomProtocols() {
setupTest("https://replaceme/some/path", "host", "/some/path");
config.setProtocols("gopher|whatever");
filter.rewriteLocation(exchange, config);
Mockito.verify(responseHeaders).set(Mockito.eq("Location"),
Mockito.eq("https://replaceme/some/path"));
}
@Test
public void fixedLocationVersionedAlwaysStrip() {
String location = "https://backend-url.example.com:443/v1/path/to/riches";
String host = "example.com:443";
String path = "/v1/path/to/riches";
setupTest(location, host, path);
assertThat(filter.fixedLocation(location, host, path, StripVersion.ALWAYS_STRIP,
config.getHostPortPattern(), config.getHostPortVersionPattern()))
.isEqualTo("https://example.com:443/path/to/riches");
}
@Test
public void fixedLocationVersionedStripAsInRequest() {
String location = "https://backend-url.example.com:443/v1/path/to/riches";
String host = "example.com:443";
String path = "/v1/path/to/riches";
setupTest(location, host, path);
assertThat(filter.fixedLocation(location, host, path, StripVersion.AS_IN_REQUEST,
config.getHostPortPattern(), config.getHostPortVersionPattern()))
.isEqualTo("https://example.com:443/v1/path/to/riches");
}
@Test
public void fixedLocationVersionedDontStrip() {
String location = "https://backend-url.example.com:443/v1/path/to/riches";
String host = "example.com:443";
String path = "/v1/path/to/riches";
setupTest(location, host, path);
assertThat(filter.fixedLocation(location, host, path, StripVersion.NEVER_STRIP,
config.getHostPortPattern(), config.getHostPortVersionPattern()))
.isEqualTo("https://example.com:443/v1/path/to/riches");
}
@Test
public void fixedLocationUnversionedAlwaysStrip() {
String location = "https://backend-url.example.com:443/v2/path/to/riches";
String host = "api.example.com:443";
String path = "/path/to/riches";
setupTest(location, host, path);
assertThat(filter.fixedLocation(location, host, path, StripVersion.ALWAYS_STRIP,
config.getHostPortPattern(), config.getHostPortVersionPattern()))
.isEqualTo("https://api.example.com:443/path/to/riches");
}
@Test
public void fixedLocationUnversionedStripAsInRequest() {
String location = "https://backend-url.example.com:443/v2/path/to/riches";
String host = "api.example.com:443";
String path = "/path/to/riches";
setupTest(location, host, path);
assertThat(filter.fixedLocation(location, host, path, StripVersion.AS_IN_REQUEST,
config.getHostPortPattern(), config.getHostPortVersionPattern()))
.isEqualTo("https://api.example.com:443/path/to/riches");
}
@Test
public void fixedLocationUnversionedDontStrip() {
String location = "https://backend-url.example.com:443/v2/path/to/riches";
String host = "api.example.com:443";
String path = "/path/to/riches";
setupTest(location, host, path);
assertThat(filter.fixedLocation(location, host, path, StripVersion.NEVER_STRIP,
config.getHostPortPattern(), config.getHostPortVersionPattern()))
.isEqualTo("https://api.example.com:443/v2/path/to/riches");
}
@Test
public void fixedLocationNoPort() {
String location = "https://backend-url.example.com/v2/path/to/riches";
String host = "api.example.com:443";
String path = "/path/to/riches";
setupTest(location, host, path);
assertThat(filter.fixedLocation(location, host, path, StripVersion.AS_IN_REQUEST,
config.getHostPortPattern(), config.getHostPortVersionPattern()))
.isEqualTo("https://api.example.com:443/path/to/riches");
}
@Test
public void toStringFormat() {
// @formatter:off
Config config = new Config().setStripVersion(StripVersion.ALWAYS_STRIP)
.setLocationHeaderName("mylocation")
.setHostValue("myhost")
.setProtocols("myproto");
GatewayFilter filter = new RewriteLocationResponseHeaderGatewayFilterFactory()
.apply(config);
assertThat(filter.toString())
.contains("ALWAYS_STRIP")
.contains("mylocation")
.contains("myhost")
.contains("myproto");
// @formatter:on
}
}

View File

@@ -25,6 +25,7 @@ import org.junit.runners.Suite.SuiteClasses;
import org.junit.runners.model.Statement;
import org.springframework.cloud.gateway.filter.GatewayMetricsFilterTests;
import org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactoryTests;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
@@ -63,6 +64,7 @@ import static org.junit.Assume.assumeThat;
org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactoryTests.class,
org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactoryTest.class,
org.springframework.cloud.gateway.filter.factory.RewriteResponseHeaderGatewayFilterFactoryUnitTests.class,
RewriteLocationResponseHeaderGatewayFilterFactoryTests.class,
org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactoryTests.class,
org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUriGatewayFilterFactoryIntegrationTests.class,
org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactoryTests.class,

View File

@@ -99,6 +99,16 @@ spring:
- AddResponseHeader=X-Request-Foo, /42?user=ford&password=omg!what&flag=true
- RewriteResponseHeader=X-Request-Foo, password=[^&]+, password=***
# =====================================
- id: rewrite_location_response_header_test
uri: ${test.uri}
predicates:
- Host=**.rewritelocationresponseheader.org
- Path=/headers
filters:
- AddResponseHeader=Location, https://backend.org:443/v1/some/object/id
- RewriteLocationResponseHeader
# =====================================
- id: forward_test
uri: forward:/localcontroller