Merge branch '2.1.x'
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user