Browse Source

Parse predicate if needed. Allow extra args in predicate. Create Header Predicate

pull/41/head
Spencer Gibb 8 years ago
parent
commit
7b9d06df44
No known key found for this signature in database
GPG Key ID: 7788A47380690861
  1. 6
      src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java
  2. 107
      src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java
  3. 90
      src/main/java/org/springframework/cloud/gateway/config/PredicateDefinition.java
  4. 73
      src/main/java/org/springframework/cloud/gateway/config/Route.java
  5. 2
      src/main/java/org/springframework/cloud/gateway/filter/RouteToRequestUrlFilter.java
  6. 11
      src/main/java/org/springframework/cloud/gateway/handler/ServerWebExchangePredicateHandlerMapping.java
  7. 6
      src/main/java/org/springframework/cloud/gateway/handler/predicate/GatewayPredicateFactory.java
  8. 36
      src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderPredicateFactory.java
  9. 2
      src/main/java/org/springframework/cloud/gateway/handler/predicate/HostPredicateFactory.java
  10. 2
      src/main/java/org/springframework/cloud/gateway/handler/predicate/MethodPredicateFactory.java
  11. 2
      src/main/java/org/springframework/cloud/gateway/handler/predicate/UrlPredicateFactory.java
  12. 3
      src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java
  13. 13
      src/test/resources/application.yml

6
src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java

@ -8,6 +8,7 @@ import org.springframework.cloud.gateway.actuate.GatewayEndpoint; @@ -8,6 +8,7 @@ import org.springframework.cloud.gateway.actuate.GatewayEndpoint;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter;
import org.springframework.cloud.gateway.handler.GatewayFilteringWebHandler;
import org.springframework.cloud.gateway.handler.predicate.HeaderPredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.HostPredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicateFactory;
import org.springframework.cloud.gateway.handler.GatewayWebHandler;
@ -76,6 +77,11 @@ public class GatewayAutoConfiguration { @@ -76,6 +77,11 @@ public class GatewayAutoConfiguration {
return new MethodPredicateFactory();
}
@Bean
public HeaderPredicateFactory headerPredicateFactory() {
return new HeaderPredicateFactory();
}
@Configuration
@ConditionalOnClass(Endpoint.class)
protected static class GatewayActuatorConfiguration {

107
src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java

@ -1,11 +1,8 @@ @@ -1,11 +1,8 @@
package org.springframework.cloud.gateway.config;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import javax.validation.Valid;
@ -32,108 +29,4 @@ public class GatewayProperties { @@ -32,108 +29,4 @@ public class GatewayProperties {
this.routes = routes;
}
public static class Route {
@NotEmpty
private String id;
@NotEmpty
@Valid
private List<Predicate> predicates = new ArrayList<>();
@NotNull
private URI downstreamUrl;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Predicate> getPredicates() {
return predicates;
}
public void setPredicates(List<Predicate> predicates) {
this.predicates = predicates;
}
public URI getDownstreamUrl() {
return downstreamUrl;
}
public void setDownstreamUrl(URI downstreamUrl) {
this.downstreamUrl = downstreamUrl;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Route route = (Route) o;
return Objects.equals(id, route.id) &&
Objects.equals(predicates, route.predicates) &&
Objects.equals(downstreamUrl, route.downstreamUrl);
}
@Override
public int hashCode() {
return Objects.hash(id, predicates, downstreamUrl);
}
@Override
public String toString() {
return "Route{" +
"id='" + id + '\'' +
", predicates=" + predicates +
", downstreamUrl=" + downstreamUrl +
'}';
}
}
public static class Predicate {
@NotNull
private String name;
@NotNull
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Predicate predicate = (Predicate) o;
return Objects.equals(name, predicate.name) &&
Objects.equals(value, predicate.value);
}
@Override
public int hashCode() {
return Objects.hash(name, value);
}
@Override
public String toString() {
return "Predicate{" +
"name='" + name + '\'' +
", value='" + value + '\'' +
'}';
}
}
}

90
src/main/java/org/springframework/cloud/gateway/config/PredicateDefinition.java

@ -0,0 +1,90 @@ @@ -0,0 +1,90 @@
package org.springframework.cloud.gateway.config;
import java.util.Arrays;
import java.util.Objects;
import javax.validation.ValidationException;
import javax.validation.constraints.NotNull;
import static org.springframework.util.StringUtils.tokenizeToStringArray;
/**
* @author Spencer Gibb
*/
public class PredicateDefinition {
@NotNull
private String name;
@NotNull
private String value;
private String[] args;
public PredicateDefinition() {
}
public PredicateDefinition(String text) {
String[] parts = text.split("=");
if (parts.length != 2) {
throw new ValidationException("Unable to parse Predicate text '" + text + "'" +
", must be of the form name=value");
}
setName(parts[0]);
String[] args = tokenizeToStringArray(parts[1], ",");
setValue(args[0]);
if (args.length > 1) {
setArgs(Arrays.copyOfRange(args, 1, args.length));
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String[] getArgs() {
return args;
}
public void setArgs(String[] args) {
this.args = args;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PredicateDefinition that = (PredicateDefinition) o;
return Objects.equals(name, that.name) &&
Objects.equals(value, that.value) &&
Arrays.equals(args, that.args);
}
@Override
public int hashCode() {
return Objects.hash(name, value, args);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("PredicateDefinition{");
sb.append("name='").append(name).append('\'');
sb.append(", value='").append(value).append('\'');
sb.append(", args=").append(Arrays.toString(args));
sb.append('}');
return sb.toString();
}
}

73
src/main/java/org/springframework/cloud/gateway/config/Route.java

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
package org.springframework.cloud.gateway.config;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author Spencer Gibb
*/
public class Route {
@NotEmpty
private String id;
@NotEmpty
@Valid
private List<PredicateDefinition> predicates = new ArrayList<>();
@NotNull
private URI downstreamUrl;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<PredicateDefinition> getPredicates() {
return predicates;
}
public void setPredicates(List<PredicateDefinition> predicates) {
this.predicates = predicates;
}
public URI getDownstreamUrl() {
return downstreamUrl;
}
public void setDownstreamUrl(URI downstreamUrl) {
this.downstreamUrl = downstreamUrl;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Route route = (Route) o;
return Objects.equals(id, route.id) &&
Objects.equals(predicates, route.predicates) &&
Objects.equals(downstreamUrl, route.downstreamUrl);
}
@Override
public int hashCode() {
return Objects.hash(id, predicates, downstreamUrl);
}
@Override
public String toString() {
return "Route{" +
"id='" + id + '\'' +
", predicates=" + predicates +
", downstreamUrl=" + downstreamUrl +
'}';
}
}

2
src/main/java/org/springframework/cloud/gateway/filter/RouteToRequestUrlFilter.java

@ -5,7 +5,7 @@ import java.net.URI; @@ -5,7 +5,7 @@ import java.net.URI;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.config.GatewayProperties.Route;
import org.springframework.cloud.gateway.config.Route;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilterChain;

11
src/main/java/org/springframework/cloud/gateway/handler/ServerWebExchangePredicateHandlerMapping.java

@ -7,7 +7,8 @@ import java.util.function.Predicate; @@ -7,7 +7,8 @@ import java.util.function.Predicate;
import org.springframework.beans.BeansException;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.config.GatewayProperties.Route;
import org.springframework.cloud.gateway.config.Route;
import org.springframework.cloud.gateway.config.PredicateDefinition;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicateFactory;
import org.springframework.web.reactive.handler.AbstractHandlerMapping;
import org.springframework.web.server.ServerWebExchange;
@ -113,10 +114,10 @@ public class ServerWebExchangePredicateHandlerMapping extends AbstractHandlerMap @@ -113,10 +114,10 @@ public class ServerWebExchangePredicateHandlerMapping extends AbstractHandlerMap
private Predicate<ServerWebExchange> combinePredicates(Route route) {
List<GatewayProperties.Predicate> predicates = route.getPredicates();
List<PredicateDefinition> predicates = route.getPredicates();
Predicate<ServerWebExchange> predicate = lookup(predicates.get(0));
for (GatewayProperties.Predicate andPredicate : predicates.subList(1, predicates.size())) {
for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) {
Predicate<ServerWebExchange> found = lookup(andPredicate);
predicate = predicate.and(found);
}
@ -124,12 +125,12 @@ public class ServerWebExchangePredicateHandlerMapping extends AbstractHandlerMap @@ -124,12 +125,12 @@ public class ServerWebExchangePredicateHandlerMapping extends AbstractHandlerMap
return predicate;
}
private Predicate<ServerWebExchange> lookup(GatewayProperties.Predicate predicate) {
private Predicate<ServerWebExchange> lookup(PredicateDefinition predicate) {
GatewayPredicateFactory found = this.predicateFactories.get(predicate.getName());
if (found == null) {
throw new IllegalArgumentException("Unable to find GatewayPredicateFactory with name " + predicate.getName());
}
return found.create(predicate.getValue());
return found.create(predicate.getValue(), predicate.getArgs());
}
/**

6
src/main/java/org/springframework/cloud/gateway/handler/predicate/GatewayPredicateFactory.java

@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
package org.springframework.cloud.gateway.handler.predicate;
import org.springframework.web.server.ServerWebExchange;
import java.util.function.Predicate;
import org.springframework.web.server.ServerWebExchange;
/**
* @author Spencer Gibb
*/
@ -11,5 +11,5 @@ public interface GatewayPredicateFactory { @@ -11,5 +11,5 @@ public interface GatewayPredicateFactory {
String getName();
Predicate<ServerWebExchange> create(String value);
Predicate<ServerWebExchange> create(String value, String[] args);
}

36
src/main/java/org/springframework/cloud/gateway/handler/predicate/HeaderPredicateFactory.java

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
package org.springframework.cloud.gateway.handler.predicate;
import java.util.List;
import java.util.function.Predicate;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
/**
* @author Spencer Gibb
*/
public class HeaderPredicateFactory implements GatewayPredicateFactory {
@Override
public String getName() {
return "Header";
}
@Override
public Predicate<ServerWebExchange> create(String header, String[] args) {
//TODO: caching can happen here
return exchange -> {
Assert.isTrue(args != null && args.length == 1,
"args must have one entry");
String regexp = args[0];
List<String> values = exchange.getRequest().getHeaders().get(header);
for (String value : values) {
if (value.matches(regexp)) {
return true;
}
}
return false;
};
}
}

2
src/main/java/org/springframework/cloud/gateway/handler/predicate/HostPredicateFactory.java

@ -23,7 +23,7 @@ public class HostPredicateFactory implements GatewayPredicateFactory { @@ -23,7 +23,7 @@ public class HostPredicateFactory implements GatewayPredicateFactory {
}
@Override
public Predicate<ServerWebExchange> create(String pattern) {
public Predicate<ServerWebExchange> create(String pattern, String[] args) {
//TODO: caching can happen here
return exchange -> {
String host = exchange.getRequest().getHeaders().getFirst("Host");

2
src/main/java/org/springframework/cloud/gateway/handler/predicate/MethodPredicateFactory.java

@ -16,7 +16,7 @@ public class MethodPredicateFactory implements GatewayPredicateFactory { @@ -16,7 +16,7 @@ public class MethodPredicateFactory implements GatewayPredicateFactory {
}
@Override
public Predicate<ServerWebExchange> create(String method) {
public Predicate<ServerWebExchange> create(String method, String[] args) {
//TODO: caching can happen here
return exchange -> {
HttpMethod requestMethod = exchange.getRequest().getMethod();

2
src/main/java/org/springframework/cloud/gateway/handler/predicate/UrlPredicateFactory.java

@ -37,7 +37,7 @@ public class UrlPredicateFactory implements GatewayPredicateFactory { @@ -37,7 +37,7 @@ public class UrlPredicateFactory implements GatewayPredicateFactory {
}
@Override
public Predicate<ServerWebExchange> create(String pattern) {
public Predicate<ServerWebExchange> create(String pattern, String[] args) {
return exchange -> {
String lookupPath = getPathHelper().getLookupPathForRequest(exchange);
return getPathMatcher().match(pattern, lookupPath);

3
src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java

@ -8,7 +8,7 @@ import org.springframework.boot.SpringBootConfiguration; @@ -8,7 +8,7 @@ import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.gateway.config.GatewayProperties.Route;
import org.springframework.cloud.gateway.config.Route;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.handler.ServerWebExchangePredicateHandlerMapping;
import org.springframework.context.annotation.Bean;
@ -88,6 +88,7 @@ public class GatewayIntegrationTests { @@ -88,6 +88,7 @@ public class GatewayIntegrationTests {
Mono<ClientResponse> result = webClient.exchange(
GET("http://localhost:" + port + "/headers")
.header("Host", "www.foo.org")
.header("X-Request-Id", "123")
.build()
);

13
src/test/resources/application.yml

@ -7,19 +7,16 @@ spring: @@ -7,19 +7,16 @@ spring:
- id: host_example_to_httpbin
downstreamUrl: http://httpbin.org:80
predicates:
- name: Host
value: '**.example.org'
- Host=**.example.org
# =====================================
- id: host_foo_path_headers_to_httpbin
downstreamUrl: http://httpbin.org:80
predicates:
- name: Host
value: '**.foo.org'
- name: Url
value: /headers
- name: Method
value: GET
- Host=**.foo.org
- Url=/headers
- Method=GET
- Header=X-Request-Id, \d+
# =====================================
- id: default_path_to_httpbin

Loading…
Cancel
Save