add new config for AddResponseHeaderGatewayFilterFactory
Signed-off-by: jiangyuan <joe469391363@gmail.com>
This commit is contained in:
@@ -16,12 +16,17 @@
|
||||
|
||||
package org.springframework.cloud.gateway.filter.factory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator;
|
||||
@@ -29,10 +34,22 @@ import static org.springframework.cloud.gateway.support.GatewayToStringStyler.fi
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class AddResponseHeaderGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
|
||||
public class AddResponseHeaderGatewayFilterFactory
|
||||
extends AbstractGatewayFilterFactory<AddResponseHeaderGatewayFilterFactory.Config> {
|
||||
|
||||
private static final String OVERRIDE_KEY = "override";
|
||||
|
||||
public AddResponseHeaderGatewayFilterFactory() {
|
||||
super(Config.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GatewayFilter apply(NameValueConfig config) {
|
||||
public List<String> shortcutFieldOrder() {
|
||||
return Arrays.asList(GatewayFilter.NAME_KEY, GatewayFilter.VALUE_KEY, OVERRIDE_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GatewayFilter apply(Config config) {
|
||||
return new GatewayFilter() {
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
@@ -42,19 +59,76 @@ public class AddResponseHeaderGatewayFilterFactory extends AbstractNameValueGate
|
||||
@Override
|
||||
public String toString() {
|
||||
return filterToStringCreator(AddResponseHeaderGatewayFilterFactory.this)
|
||||
.append(config.getName(), config.getValue())
|
||||
.append(GatewayFilter.NAME_KEY, config.getName())
|
||||
.append(GatewayFilter.VALUE_KEY, config.getValue())
|
||||
.append(OVERRIDE_KEY, config.isOverride())
|
||||
.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void addHeader(ServerWebExchange exchange, NameValueConfig config) {
|
||||
final String value = ServerWebExchangeUtils.expand(exchange, config.getValue());
|
||||
HttpHeaders headers = exchange.getResponse().getHeaders();
|
||||
void addHeader(ServerWebExchange exchange, Config config) {
|
||||
// if response has been commited, no more response headers will bee added.
|
||||
if (!exchange.getResponse().isCommitted()) {
|
||||
headers.add(config.getName(), value);
|
||||
final String value = ServerWebExchangeUtils.expand(exchange, config.getValue());
|
||||
HttpHeaders headers = exchange.getResponse().getHeaders();
|
||||
if (config.override) {
|
||||
headers.add(config.getName(), value);
|
||||
}
|
||||
else {
|
||||
boolean headerIsMissingOrBlank = headers.getOrEmpty(config.getName())
|
||||
.stream()
|
||||
.allMatch(h -> !StringUtils.hasText(h));
|
||||
if (headerIsMissingOrBlank) {
|
||||
headers.add(config.getName(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Config {
|
||||
|
||||
private String name;
|
||||
|
||||
private String value;
|
||||
|
||||
private boolean override = true;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Config setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Config setValue(String value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isOverride() {
|
||||
return override;
|
||||
}
|
||||
|
||||
public Config setOverride(boolean override) {
|
||||
this.override = override;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append(NAME_KEY, name)
|
||||
.append(VALUE_KEY, value)
|
||||
.append(OVERRIDE_KEY, override)
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -225,6 +225,18 @@ public class GatewayFilterSpec extends UriSpec {
|
||||
.apply(c -> c.setName(headerName).setValue(headerValue)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a header to the response returned to the Gateway from the route.
|
||||
* @param headerName the header name
|
||||
* @param headerValue the header value
|
||||
* @param override override or not
|
||||
* @return a {@link GatewayFilterSpec} that can be used to apply additional filters
|
||||
*/
|
||||
public GatewayFilterSpec addResponseHeader(String headerName, String headerValue, boolean override) {
|
||||
return filter(getBean(AddResponseHeaderGatewayFilterFactory.class)
|
||||
.apply(c -> c.setName(headerName).setValue(headerValue).setOverride(override)));
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter that adds a local cache for storing response body for repeated requests.
|
||||
* <p>
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.springframework.cloud.gateway.filter.factory;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -25,7 +27,6 @@ import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory.NameValueConfig;
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
|
||||
import org.springframework.cloud.gateway.test.BaseWebClientTests;
|
||||
@@ -51,20 +52,71 @@ class AddResponseHeaderGatewayFilterFactoryTests extends BaseWebClientTests {
|
||||
.header("Host", host)
|
||||
.exchange()
|
||||
.expectHeader()
|
||||
.valueEquals("X-Request-Foo", expectedValue);
|
||||
.valueEquals("X-Request-Foo", expectedValue)
|
||||
.expectHeader()
|
||||
.valueEquals("X-Request-Example", "ValueA");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testResponseHeaderFilterHeaderPresent() {
|
||||
URI uri = UriComponentsBuilder.fromUriString(this.baseUri + "/headers").build(true).toUri();
|
||||
String host = "www.addresponseheader.org";
|
||||
String expectedValue = "Bar";
|
||||
|
||||
Map<String, String> body = new HashMap<>();
|
||||
body.put("X-Request-Example", "ValueB");
|
||||
|
||||
testClient.patch()
|
||||
.uri(uri)
|
||||
.header("Host", host)
|
||||
.bodyValue(body)
|
||||
.exchange()
|
||||
.expectHeader()
|
||||
.valueEquals("X-Request-Foo", expectedValue)
|
||||
.expectHeader()
|
||||
.valueEquals("X-Request-Example", "ValueB");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testResponseHeaderFilterJavaDsl() {
|
||||
URI uri = UriComponentsBuilder.fromUriString(this.baseUri + "/get").build(true).toUri();
|
||||
URI uri = UriComponentsBuilder.fromUriString(this.baseUri + "/headers").build(true).toUri();
|
||||
String host = "www.addresponseheaderjava.org";
|
||||
String expectedValue = "myresponsevalue-www";
|
||||
testClient.get().uri(uri).header("Host", host).exchange().expectHeader().valueEquals("example", expectedValue);
|
||||
testClient.get()
|
||||
.uri(uri)
|
||||
.header("Host", host)
|
||||
.exchange()
|
||||
.expectHeader()
|
||||
.valueEquals("example", expectedValue)
|
||||
.expectHeader()
|
||||
.valueEquals("example2", "myresponsevalue2-www");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testResponseHeaderFilterHeaderPresentJavaDsl() {
|
||||
URI uri = UriComponentsBuilder.fromUriString(this.baseUri + "/headers").build(true).toUri();
|
||||
String host = "www.addresponseheaderjava.org";
|
||||
String expectedValue = "myresponsevalue-www";
|
||||
|
||||
Map<String, String> body = new HashMap<>();
|
||||
body.put("example2", "myresponsevalue2");
|
||||
|
||||
testClient.patch()
|
||||
.uri(uri)
|
||||
.header("Host", host)
|
||||
.bodyValue(body)
|
||||
.exchange()
|
||||
.expectHeader()
|
||||
.valueEquals("example", expectedValue)
|
||||
.expectHeader()
|
||||
.valueEquals("example2", "myresponsevalue2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void toStringFormat() {
|
||||
NameValueConfig config = new NameValueConfig().setName("myname").setValue("myvalue");
|
||||
AddResponseHeaderGatewayFilterFactory.Config config = new AddResponseHeaderGatewayFilterFactory.Config()
|
||||
.setName("myname")
|
||||
.setValue("myvalue");
|
||||
GatewayFilter filter = new AddResponseHeaderGatewayFilterFactory().apply(config);
|
||||
assertThat(filter.toString()).contains("myname").contains("myvalue");
|
||||
}
|
||||
@@ -81,11 +133,11 @@ class AddResponseHeaderGatewayFilterFactoryTests extends BaseWebClientTests {
|
||||
public RouteLocator testRouteLocator(RouteLocatorBuilder builder) {
|
||||
return builder.routes()
|
||||
.route("add_response_header_java_test",
|
||||
r -> r.path("/get")
|
||||
r -> r.path("/headers")
|
||||
.and()
|
||||
.host("{sub}.addresponseheaderjava.org")
|
||||
.filters(
|
||||
f -> f.prefixPath("/httpbin").addResponseHeader("example", "myresponsevalue-{sub}"))
|
||||
.filters(f -> f.addResponseHeader("example", "myresponsevalue-{sub}")
|
||||
.addResponseHeader("example2", "myresponsevalue2-{sub}", false))
|
||||
.uri(uri))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ spring:
|
||||
- Path=/headers
|
||||
filters:
|
||||
- AddResponseHeader=X-Request-Foo, Bar
|
||||
- AddResponseHeader=X-Request-Example, ValueA, false
|
||||
|
||||
- id: cache_request_body_test
|
||||
uri: ${test.uri}
|
||||
|
||||
Reference in New Issue
Block a user