Browse Source

Moves to named Tuple args

Moves WebFilterFactory used to named Tuple arguments rather than a String array.
pull/41/head
Spencer Gibb 8 years ago
parent
commit
c8a27f5547
No known key found for this signature in database
GPG Key ID: 7788A47380690861
  1. 8
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteLocator.java
  2. 16
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderWebFilterFactory.java
  3. 15
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterWebFilterFactory.java
  4. 16
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderWebFilterFactory.java
  5. 14
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixWebFilterFactory.java
  6. 16
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PrefixPathWebFilterFactory.java
  7. 23
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RedirectToWebFilterFactory.java
  8. 3
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveNonProxyHeadersWebFilterFactory.java
  9. 14
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderWebFilterFactory.java
  10. 14
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderWebFilterFactory.java
  11. 19
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactory.java
  12. 3
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersWebFilterFactory.java
  13. 16
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetPathWebFilterFactory.java
  14. 16
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderWebFilterFactory.java
  15. 17
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetStatusWebFilterFactory.java
  16. 30
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/WebFilterFactory.java
  17. 51
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java
  18. 19
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/RequestPredicateHandlerMapping.java
  19. 2
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/QueryRequestPredicateFactory.java
  20. 4
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RequestPredicateFactory.java
  21. 23
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/model/FilterDefinition.java
  22. 4
      spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/model/PredicateDefinition.java
  23. 10
      spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactoryTests.java
  24. 4
      spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetPathWebFilterFactoryTests.java
  25. 3
      spring-cloud-gateway-core/src/test/resources/application.yml

8
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/discovery/DiscoveryClientRouteLocator.java

@ -18,7 +18,6 @@ @@ -18,7 +18,6 @@
package org.springframework.cloud.gateway.discovery;
import java.net.URI;
import java.util.Collections;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.api.RouteLocator;
@ -28,6 +27,8 @@ import org.springframework.cloud.gateway.model.FilterDefinition; @@ -28,6 +27,8 @@ import org.springframework.cloud.gateway.model.FilterDefinition;
import org.springframework.cloud.gateway.model.PredicateDefinition;
import org.springframework.cloud.gateway.model.Route;
import static org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactory.REGEXP_KEY;
import static org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactory.REPLACEMENT_KEY;
import static org.springframework.cloud.gateway.handler.predicate.PathRequestPredicateFactory.PATTERN_KEY;
import static org.springframework.cloud.gateway.support.NameUtils.normalizeFilterName;
import static org.springframework.cloud.gateway.support.NameUtils.normalizePredicateName;
@ -59,7 +60,7 @@ public class DiscoveryClientRouteLocator implements RouteLocator { @@ -59,7 +60,7 @@ public class DiscoveryClientRouteLocator implements RouteLocator {
// add a predicate that matches the url at /serviceId/**
PredicateDefinition predicate = new PredicateDefinition();
predicate.setName(normalizePredicateName(PathRequestPredicateFactory.class));
predicate.setArgs(Collections.singletonMap(PATTERN_KEY, "/" + serviceId + "/**"));
predicate.addArg(PATTERN_KEY, "/" + serviceId + "/**");
route.getPredicates().add(predicate);
//TODO: support for other default predicates
@ -69,7 +70,8 @@ public class DiscoveryClientRouteLocator implements RouteLocator { @@ -69,7 +70,8 @@ public class DiscoveryClientRouteLocator implements RouteLocator {
filter.setName(normalizeFilterName(RewritePathWebFilterFactory.class));
String regex = "/" + serviceId + "/(?<remaining>.*)";
String replacement = "/${remaining}";
filter.setArgs(regex, replacement);
filter.addArg(REGEXP_KEY, regex);
filter.addArg(REPLACEMENT_KEY, replacement);
route.getFilters().add(filter);
//TODO: support for default filters

16
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestHeaderWebFilterFactory.java

@ -17,21 +17,31 @@ @@ -17,21 +17,31 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import java.util.Arrays;
import java.util.List;
/**
* @author Spencer Gibb
*/
public class AddRequestHeaderWebFilterFactory implements WebFilterFactory {
@Override
public WebFilter apply(String... args) {
validate(2, args);
public List<String> argNames() {
return Arrays.asList(NAME_KEY, VALUE_KEY);
}
@Override
public WebFilter apply(Tuple args) {
String name = args.getString(NAME_KEY);
String value = args.getString(VALUE_KEY);
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest().mutate()
.header(args[0], args[1])
.header(name, value)
.build();
return chain.filter(exchange.mutate().request(request).build());

15
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddRequestParameterWebFilterFactory.java

@ -19,11 +19,14 @@ package org.springframework.cloud.gateway.filter.factory; @@ -19,11 +19,14 @@ package org.springframework.cloud.gateway.filter.factory;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.tuple.Tuple;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.server.WebFilter;
@ -34,10 +37,14 @@ import org.springframework.web.server.WebFilter; @@ -34,10 +37,14 @@ import org.springframework.web.server.WebFilter;
public class AddRequestParameterWebFilterFactory implements WebFilterFactory {
@Override
public WebFilter apply(String... args) {
validate(2, args);
String parameter = args[0];
String value = args[1];
public List<String> argNames() {
return Arrays.asList(NAME_KEY, VALUE_KEY);
}
@Override
public WebFilter apply(Tuple args) {
String parameter = args.getString(NAME_KEY);
String value = args.getString(VALUE_KEY);
return (exchange, chain) -> {

16
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AddResponseHeaderWebFilterFactory.java

@ -17,18 +17,26 @@ @@ -17,18 +17,26 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import java.util.Arrays;
import java.util.List;
/**
* @author Spencer Gibb
*/
public class AddResponseHeaderWebFilterFactory implements WebFilterFactory {
@Override
public WebFilter apply(String... args) {
validate(2, args);
final String header = args[0];
final String value = args[1];
public List<String> argNames() {
return Arrays.asList(NAME_KEY, VALUE_KEY);
}
@Override
public WebFilter apply(Tuple args) {
final String header = args.getString(NAME_KEY);
final String value = args.getString(VALUE_KEY);
return (exchange, chain) -> {
exchange.getResponse().getHeaders().add(header, value);

14
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixWebFilterFactory.java

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
@ -30,15 +31,22 @@ import rx.Observable; @@ -30,15 +31,22 @@ import rx.Observable;
import rx.RxReactiveStreams;
import rx.Subscription;
import java.util.Arrays;
import java.util.List;
/**
* @author Spencer Gibb
*/
public class HystrixWebFilterFactory implements WebFilterFactory {
@Override
public WebFilter apply(String... args) {
validate(1, args);
final String commandName = args[0];
public List<String> argNames() {
return Arrays.asList(NAME_KEY);
}
@Override
public WebFilter apply(Tuple args) {
final String commandName = args.getString(NAME_KEY);
final HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey(getClass().getSimpleName());
final HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey(commandName);

16
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/PrefixPathWebFilterFactory.java

@ -18,18 +18,28 @@ @@ -18,18 +18,28 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import java.util.Arrays;
import java.util.List;
/**
* @author Spencer Gibb
*/
public class PrefixPathWebFilterFactory implements WebFilterFactory {
public static final String PREFIX_KEY = "prefix";
@Override
public List<String> argNames() {
return Arrays.asList(PREFIX_KEY);
}
@Override
@SuppressWarnings("unchecked")
public WebFilter apply(String... args) {
validate(1, args);
final String prefix = args[0];
public WebFilter apply(Tuple args) {
final String prefix = args.getString(PREFIX_KEY);
return (exchange, chain) -> {
ServerHttpRequest req = exchange.getRequest();

23
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RedirectToWebFilterFactory.java

@ -20,10 +20,13 @@ package org.springframework.cloud.gateway.filter.factory; @@ -20,10 +20,13 @@ package org.springframework.cloud.gateway.filter.factory;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.parse;
@ -35,18 +38,26 @@ import reactor.core.publisher.Mono; @@ -35,18 +38,26 @@ import reactor.core.publisher.Mono;
* @author Spencer Gibb
*/
public class RedirectToWebFilterFactory implements WebFilterFactory {
public static final String STATUS_KEY = "status";
public static final String URL_KEY = "url";
@Override
public List<String> argNames() {
return Arrays.asList(STATUS_KEY, URL_KEY);
}
@Override
public WebFilter apply(String... args) {
validate(2, args);
final String statusString = args[0];
final String uri = args[1];
public WebFilter apply(Tuple args) {
String statusString = args.getRawString(STATUS_KEY);
String urlString = args.getString(URL_KEY);
final HttpStatus httpStatus = parse(statusString);
final URL url;
try {
url = URI.create(uri).toURL();
url = URI.create(urlString).toURL();
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Invalid url " + uri, e);
throw new IllegalArgumentException("Invalid url " + urlString, e);
}
return (exchange, chain) ->

3
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveNonProxyHeadersWebFilterFactory.java

@ -19,6 +19,7 @@ package org.springframework.cloud.gateway.filter.factory; @@ -19,6 +19,7 @@ package org.springframework.cloud.gateway.filter.factory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import java.util.Arrays;
@ -61,7 +62,7 @@ public class RemoveNonProxyHeadersWebFilterFactory implements WebFilterFactory { @@ -61,7 +62,7 @@ public class RemoveNonProxyHeadersWebFilterFactory implements WebFilterFactory {
}
@Override
public WebFilter apply(String... args) {
public WebFilter apply(Tuple args) {
//TODO: support filter args
return (exchange, chain) -> {

14
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestHeaderWebFilterFactory.java

@ -17,9 +17,13 @@ @@ -17,9 +17,13 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import java.util.Arrays;
import java.util.List;
/**
* @author Spencer Gibb
*/
@ -28,9 +32,13 @@ public class RemoveRequestHeaderWebFilterFactory implements WebFilterFactory { @@ -28,9 +32,13 @@ public class RemoveRequestHeaderWebFilterFactory implements WebFilterFactory {
private static final String FAKE_HEADER = "_______force_______";
@Override
public WebFilter apply(String... args) {
validate(1, args);
final String header = args[0];
public List<String> argNames() {
return Arrays.asList(NAME_KEY);
}
@Override
public WebFilter apply(Tuple args) {
final String header = args.getString(NAME_KEY);
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest().mutate()

14
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveResponseHeaderWebFilterFactory.java

@ -17,17 +17,25 @@ @@ -17,17 +17,25 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import java.util.Arrays;
import java.util.List;
/**
* @author Spencer Gibb
*/
public class RemoveResponseHeaderWebFilterFactory implements WebFilterFactory {
@Override
public WebFilter apply(String... args) {
validate(1, args);
final String header = args[0];
public List<String> argNames() {
return Arrays.asList(NAME_KEY);
}
@Override
public WebFilter apply(Tuple args) {
final String header = args.getString(NAME_KEY);
return (exchange, chain) -> {
exchange.getResponse().getHeaders().remove(header);

19
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactory.java

@ -17,19 +17,30 @@ @@ -17,19 +17,30 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import java.util.Arrays;
import java.util.List;
/**
* @author Spencer Gibb
*/
public class RewritePathWebFilterFactory implements WebFilterFactory {
public static final String REGEXP_KEY = "regexp";
public static final String REPLACEMENT_KEY = "replacement";
@Override
public List<String> argNames() {
return Arrays.asList(REGEXP_KEY, REPLACEMENT_KEY);
}
@Override
public WebFilter apply(String... args) {
validate(2, args);
final String regex = args[0];
String replacement = args[1].replace("$\\", "$");
public WebFilter apply(Tuple args) {
final String regex = args.getString(REGEXP_KEY);
String replacement = args.getString(REPLACEMENT_KEY).replace("$\\", "$");
return (exchange, chain) -> {
ServerHttpRequest req = exchange.getRequest();

3
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersWebFilterFactory.java

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.http.HttpHeaders;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
/**
@ -42,7 +43,7 @@ public class SecureHeadersWebFilterFactory implements WebFilterFactory { @@ -42,7 +43,7 @@ public class SecureHeadersWebFilterFactory implements WebFilterFactory {
}
@Override
public WebFilter apply(String... args) {
public WebFilter apply(Tuple args) {
//TODO: allow args to override properties
return (exchange, chain) -> {

16
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetPathWebFilterFactory.java

@ -18,9 +18,12 @@ @@ -18,9 +18,12 @@
package org.springframework.cloud.gateway.filter.factory;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import org.springframework.web.util.UriTemplate;
@ -32,11 +35,18 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.U @@ -32,11 +35,18 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.U
*/
public class SetPathWebFilterFactory implements WebFilterFactory {
public static final String TEMPLATE_KEY = "template";
@Override
public List<String> argNames() {
return Arrays.asList(TEMPLATE_KEY);
}
@Override
@SuppressWarnings("unchecked")
public WebFilter apply(String... args) {
validate(1, args);
UriTemplate uriTemplate = new UriTemplate(args[0]);
public WebFilter apply(Tuple args) {
String template = args.getString(TEMPLATE_KEY);
UriTemplate uriTemplate = new UriTemplate(template);
return (exchange, chain) -> {
Map<String, String> variables = getAttribute(exchange, URI_TEMPLATE_VARIABLES_ATTRIBUTE, Map.class);

16
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetResponseHeaderWebFilterFactory.java

@ -17,18 +17,26 @@ @@ -17,18 +17,26 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import java.util.Arrays;
import java.util.List;
/**
* @author Spencer Gibb
*/
public class SetResponseHeaderWebFilterFactory implements WebFilterFactory {
@Override
public WebFilter apply(String... args) {
validate(2, args);
final String header = args[0];
final String value = args[1];
public List<String> argNames() {
return Arrays.asList(NAME_KEY, VALUE_KEY);
}
@Override
public WebFilter apply(Tuple args) {
final String header = args.getString(NAME_KEY);
final String value = args.getString(VALUE_KEY);
return (exchange, chain) -> {
exchange.getResponse().getHeaders().set(header, value);

17
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/SetStatusWebFilterFactory.java

@ -19,21 +19,32 @@ package org.springframework.cloud.gateway.filter.factory; @@ -19,21 +19,32 @@ package org.springframework.cloud.gateway.filter.factory;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.HttpStatus;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.setResponseStatus;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
/**
* @author Spencer Gibb
*/
public class SetStatusWebFilterFactory implements WebFilterFactory {
public static final String STATUS_KEY = "status";
@Override
public List<String> argNames() {
return Arrays.asList(STATUS_KEY);
}
@Override
public WebFilter apply(String... args) {
validate(1, args);
final HttpStatus httpStatus = ServerWebExchangeUtils.parse(args[0]);
public WebFilter apply(Tuple args) {
String status = args.getRawString(STATUS_KEY);
final HttpStatus httpStatus = ServerWebExchangeUtils.parse(status);
return (exchange, chain) -> {

30
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/WebFilterFactory.java

@ -18,24 +18,48 @@ @@ -18,24 +18,48 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.tuple.Tuple;
import org.springframework.util.Assert;
import org.springframework.web.server.WebFilter;
import java.util.Collections;
import java.util.List;
/**
* @author Spencer Gibb
*/
@FunctionalInterface
public interface WebFilterFactory {
String NAME_KEY = "name";
String VALUE_KEY = "value";
//TODO: move from String... to Tuple
WebFilter apply(String... args);
WebFilter apply(Tuple args);
default String name() {
return NameUtils.normalizeFilterName(getClass());
}
default void validate(int requiredSize, String... args) {
Assert.isTrue(args != null && args.length == requiredSize,
/**
* Returns hints about the number of args and the order for shortcut parsing.
* @return
*/
default List<String> argNames() {
return Collections.emptyList();
}
/**
* Validate supplied argument size against {@see #argNames} size.
* Useful for variable arg predicates.
* @return
*/
default boolean validateArgs() {
return true;
}
default void validate(int requiredSize, Tuple args) {
Assert.isTrue(args != null && args.size() == requiredSize,
"args must have "+ requiredSize +" entry(s)");
}
}

51
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/FilteringWebHandler.java

@ -18,7 +18,6 @@ @@ -18,7 +18,6 @@
package org.springframework.cloud.gateway.handler;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -36,10 +35,13 @@ import org.springframework.cloud.gateway.model.FilterDefinition; @@ -36,10 +35,13 @@ import org.springframework.cloud.gateway.model.FilterDefinition;
import org.springframework.cloud.gateway.model.Route;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.cloud.gateway.support.RefreshRoutesEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.tuple.Tuple;
import org.springframework.tuple.TupleBuilder;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
@ -153,16 +155,49 @@ public class FilteringWebHandler extends WebHandlerDecorator { @@ -153,16 +155,49 @@ public class FilteringWebHandler extends WebHandlerDecorator {
if (filter == null) {
throw new IllegalArgumentException("Unable to find WebFilterFactory with name " + definition.getName());
}
Map<String, String> args = definition.getArgs();
if (logger.isDebugEnabled()) {
List<String> args;
if (definition.getArgs() != null) {
args = Arrays.asList(definition.getArgs());
} else {
args = Collections.emptyList();
}
logger.debug("Route " + id + " applying filter " + args + " to " + definition.getName());
}
return filter.apply(definition.getArgs());
//TODO: move Tuple building to common class, see RequestPredicateFactory.lookup
TupleBuilder builder = TupleBuilder.tuple();
List<String> argNames = filter.argNames();
if (!argNames.isEmpty()) {
// ensure size is the same for key replacement later
if (filter.validateArgs() && args.size() != argNames.size()) {
throw new IllegalArgumentException("Wrong number of arguments. Expected " + argNames
+ " " + argNames + ". Found " + args.size() + " " + args + "'");
}
}
int entryIdx = 0;
for (Map.Entry<String, String> entry : args.entrySet()) {
String key = entry.getKey();
// RequestPredicateFactory has name hints and this has a fake key name
// replace with the matching key hint
if (key.startsWith(NameUtils.GENERATED_NAME_PREFIX) && !argNames.isEmpty()
&& entryIdx < args.size()) {
key = argNames.get(entryIdx);
}
builder.put(key, entry.getValue());
entryIdx++;
}
Tuple tuple = builder.build();
if (filter.validateArgs()) {
for (String name : argNames) {
if (!tuple.hasFieldName(name)) {
throw new IllegalArgumentException("Missing argument '" + name + "'. Given " + tuple);
}
}
}
return filter.apply(tuple);
})
.collect(Collectors.toList());

19
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/RequestPredicateHandlerMapping.java

@ -170,10 +170,12 @@ public class RequestPredicateHandlerMapping extends AbstractHandlerMapping { @@ -170,10 +170,12 @@ public class RequestPredicateHandlerMapping extends AbstractHandlerMapping {
List<String> argNames = found.argNames();
if (!argNames.isEmpty()) {
// ensure size is the same for key replacement later
if (found.validateArgSize() && args.size() != argNames.size()) {
throw new IllegalArgumentException("Wrong number of arguments. Expected " + argNames
+ " " + argNames + ". Found "+ args.size() +" " + args +"'");
if (!argNames.isEmpty()) {
// ensure size is the same for key replacement later
if (found.validateArgs() && args.size() != argNames.size()) {
throw new IllegalArgumentException("Wrong number of arguments. Expected " + argNames
+ " " + argNames + ". Found " + args.size() + " " + args + "'");
}
}
}
@ -193,6 +195,15 @@ public class RequestPredicateHandlerMapping extends AbstractHandlerMapping { @@ -193,6 +195,15 @@ public class RequestPredicateHandlerMapping extends AbstractHandlerMapping {
}
Tuple tuple = builder.build();
if (found.validateArgs()) {
for (String name : argNames) {
if (!tuple.hasFieldName(name)) {
throw new IllegalArgumentException("Missing argument '" + name + "'. Given " + tuple);
}
}
}
return found.apply(tuple);
}

2
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/QueryRequestPredicateFactory.java

@ -39,7 +39,7 @@ public class QueryRequestPredicateFactory implements RequestPredicateFactory { @@ -39,7 +39,7 @@ public class QueryRequestPredicateFactory implements RequestPredicateFactory {
}
@Override
public boolean validateArgSize() {
public boolean validateArgs() {
return false;
}

4
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/handler/predicate/RequestPredicateFactory.java

@ -46,11 +46,11 @@ public interface RequestPredicateFactory { @@ -46,11 +46,11 @@ public interface RequestPredicateFactory {
}
/**
* Validate supplied argument size against {@see #argNames} size.
* Auto validate supplied argument size against {@see #argNames} size and that an arg for each key exists.
* Useful for variable arg predicates.
* @return
*/
default boolean validateArgSize() {
default boolean validateArgs() {
return true;
}

23
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/model/FilterDefinition.java

@ -17,11 +17,14 @@ @@ -17,11 +17,14 @@
package org.springframework.cloud.gateway.model;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import javax.validation.constraints.NotNull;
import org.springframework.cloud.gateway.support.NameUtils;
import static org.springframework.util.StringUtils.tokenizeToStringArray;
/**
@ -30,7 +33,7 @@ import static org.springframework.util.StringUtils.tokenizeToStringArray; @@ -30,7 +33,7 @@ import static org.springframework.util.StringUtils.tokenizeToStringArray;
public class FilterDefinition {
@NotNull
private String name;
private String[] args;
private Map<String, String> args = new LinkedHashMap<>();
public FilterDefinition() {
}
@ -45,7 +48,9 @@ public class FilterDefinition { @@ -45,7 +48,9 @@ public class FilterDefinition {
String[] args = tokenizeToStringArray(text.substring(eqIdx+1), ",");
setArgs(args);
for (int i=0; i < args.length; i++) {
this.args.put(NameUtils.generateName(i), args[i]);
}
}
public String getName() {
@ -56,21 +61,25 @@ public class FilterDefinition { @@ -56,21 +61,25 @@ public class FilterDefinition {
this.name = name;
}
public String[] getArgs() {
public Map<String, String> getArgs() {
return args;
}
public void setArgs(String... args) {
public void setArgs(Map<String, String> args) {
this.args = args;
}
public void addArg(String key, String value) {
this.args.put(key, value);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FilterDefinition that = (FilterDefinition) o;
return Objects.equals(name, that.name) &&
Arrays.equals(args, that.args);
Objects.equals(args, that.args);
}
@Override
@ -82,7 +91,7 @@ public class FilterDefinition { @@ -82,7 +91,7 @@ public class FilterDefinition {
public String toString() {
final StringBuilder sb = new StringBuilder("FilterDefinition{");
sb.append("name='").append(name).append('\'');
sb.append(", args=").append(Arrays.toString(args));
sb.append(", args=").append(args);
sb.append('}');
return sb.toString();
}

4
spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/model/PredicateDefinition.java

@ -70,6 +70,10 @@ public class PredicateDefinition { @@ -70,6 +70,10 @@ public class PredicateDefinition {
this.args = args;
}
public void addArg(String key, String value) {
this.args.put(key, value);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

10
spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RewritePathWebFilterFactoryTests.java

@ -20,16 +20,20 @@ package org.springframework.cloud.gateway.filter.factory; @@ -20,16 +20,20 @@ package org.springframework.cloud.gateway.filter.factory;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.web.server.WebFilter;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.MockServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import reactor.core.publisher.Mono;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactory.REGEXP_KEY;
import static org.springframework.cloud.gateway.filter.factory.RewritePathWebFilterFactory.REPLACEMENT_KEY;
import static org.springframework.tuple.TupleBuilder.tuple;
import reactor.core.publisher.Mono;
/**
* @author Spencer Gibb
@ -47,7 +51,7 @@ public class RewritePathWebFilterFactoryTests { @@ -47,7 +51,7 @@ public class RewritePathWebFilterFactoryTests {
}
private void testRewriteFilter(String regex, String replacement, String actualPath, String expectedPath) {
WebFilter filter = new RewritePathWebFilterFactory().apply(regex, replacement);
WebFilter filter = new RewritePathWebFilterFactory().apply(tuple().of(REGEXP_KEY, regex, REPLACEMENT_KEY, replacement));
MockServerHttpRequest request = MockServerHttpRequest
.get("http://localhost"+ actualPath)

4
spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/SetPathWebFilterFactoryTests.java

@ -32,6 +32,8 @@ import org.springframework.web.server.adapter.DefaultServerWebExchange; @@ -32,6 +32,8 @@ import org.springframework.web.server.adapter.DefaultServerWebExchange;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.springframework.cloud.gateway.filter.factory.SetPathWebFilterFactory.TEMPLATE_KEY;
import static org.springframework.tuple.TupleBuilder.tuple;
import reactor.core.publisher.Mono;
@ -54,7 +56,7 @@ public class SetPathWebFilterFactoryTests { @@ -54,7 +56,7 @@ public class SetPathWebFilterFactoryTests {
}
private void testRewriteFilter(String template, String actualPath, String expectedPath, HashMap<String, String> variables) {
WebFilter filter = new SetPathWebFilterFactory().apply(new String[]{template});
WebFilter filter = new SetPathWebFilterFactory().apply(tuple().of(TEMPLATE_KEY, template));
MockServerHttpRequest request = MockServerHttpRequest
.get("http://localhost"+ actualPath)

3
spring-cloud-gateway-core/src/test/resources/application.yml

@ -151,7 +151,8 @@ spring: @@ -151,7 +151,8 @@ spring:
- Path=/headers
filters:
- name: SetStatus
args: 401
args:
status: 401
# =====================================
- id: set_status_string_test

Loading…
Cancel
Save