Adds option to lower case routes to services.
fixes gh-302
This commit is contained in:
@@ -28,6 +28,7 @@ import org.springframework.cloud.gateway.filter.FilterDefinition;
|
|||||||
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
|
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
|
||||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||||
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
|
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
|
||||||
|
import org.springframework.core.style.ToStringCreator;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
||||||
@@ -84,11 +85,13 @@ public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLoc
|
|||||||
String uri = urlExpr.getValue(evalCtxt, instance, String.class);
|
String uri = urlExpr.getValue(evalCtxt, instance, String.class);
|
||||||
routeDefinition.setUri(URI.create(uri));
|
routeDefinition.setUri(URI.create(uri));
|
||||||
|
|
||||||
|
final ServiceInstance instanceForEval = new DelegatingServiceInstance(instance, properties);
|
||||||
|
|
||||||
for (PredicateDefinition original : this.properties.getPredicates()) {
|
for (PredicateDefinition original : this.properties.getPredicates()) {
|
||||||
PredicateDefinition predicate = new PredicateDefinition();
|
PredicateDefinition predicate = new PredicateDefinition();
|
||||||
predicate.setName(original.getName());
|
predicate.setName(original.getName());
|
||||||
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
|
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
|
||||||
String value = getValueFromExpr(evalCtxt, parser, instance, entry);
|
String value = getValueFromExpr(evalCtxt, parser, instanceForEval, entry);
|
||||||
predicate.addArg(entry.getKey(), value);
|
predicate.addArg(entry.getKey(), value);
|
||||||
}
|
}
|
||||||
routeDefinition.getPredicates().add(predicate);
|
routeDefinition.getPredicates().add(predicate);
|
||||||
@@ -98,7 +101,7 @@ public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLoc
|
|||||||
FilterDefinition filter = new FilterDefinition();
|
FilterDefinition filter = new FilterDefinition();
|
||||||
filter.setName(original.getName());
|
filter.setName(original.getName());
|
||||||
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
|
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
|
||||||
String value = getValueFromExpr(evalCtxt, parser, instance, entry);
|
String value = getValueFromExpr(evalCtxt, parser, instanceForEval, entry);
|
||||||
filter.addArg(entry.getKey(), value);
|
filter.addArg(entry.getKey(), value);
|
||||||
}
|
}
|
||||||
routeDefinition.getFilters().add(filter);
|
routeDefinition.getFilters().add(filter);
|
||||||
@@ -112,4 +115,61 @@ public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLoc
|
|||||||
Expression valueExpr = parser.parseExpression(entry.getValue());
|
Expression valueExpr = parser.parseExpression(entry.getValue());
|
||||||
return valueExpr.getValue(evalCtxt, instance, String.class);
|
return valueExpr.getValue(evalCtxt, instance, String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class DelegatingServiceInstance implements ServiceInstance {
|
||||||
|
|
||||||
|
final ServiceInstance delegate;
|
||||||
|
private final DiscoveryLocatorProperties properties;
|
||||||
|
|
||||||
|
private DelegatingServiceInstance(ServiceInstance delegate, DiscoveryLocatorProperties properties) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServiceId() {
|
||||||
|
if (properties.isLowerCaseServiceId()) {
|
||||||
|
return delegate.getServiceId().toLowerCase();
|
||||||
|
}
|
||||||
|
return delegate.getServiceId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHost() {
|
||||||
|
return delegate.getHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPort() {
|
||||||
|
return delegate.getPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSecure() {
|
||||||
|
return delegate.isSecure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI getUri() {
|
||||||
|
return delegate.getUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getMetadata() {
|
||||||
|
return delegate.getMetadata();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getScheme() {
|
||||||
|
return delegate.getScheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new ToStringCreator(this)
|
||||||
|
.append("delegate", delegate)
|
||||||
|
.append("properties", properties)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,13 @@ public class DiscoveryLocatorProperties {
|
|||||||
/** SpEL expression that create the uri for each route, defaults to: 'lb://'+serviceId */
|
/** SpEL expression that create the uri for each route, defaults to: 'lb://'+serviceId */
|
||||||
private String urlExpression = "'lb://'+serviceId";
|
private String urlExpression = "'lb://'+serviceId";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Option to lower case serviceId in predicates and filters, defaults to false.
|
||||||
|
* Useful with eureka when it automatically uppercases serviceId.
|
||||||
|
* so MYSERIVCE, would match /myservice/**
|
||||||
|
*/
|
||||||
|
private boolean lowerCaseServiceId = false;
|
||||||
|
|
||||||
private List<PredicateDefinition> predicates = new ArrayList<>();
|
private List<PredicateDefinition> predicates = new ArrayList<>();
|
||||||
|
|
||||||
private List<FilterDefinition> filters = new ArrayList<>();
|
private List<FilterDefinition> filters = new ArrayList<>();
|
||||||
@@ -83,6 +90,14 @@ public class DiscoveryLocatorProperties {
|
|||||||
this.urlExpression = urlExpression;
|
this.urlExpression = urlExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLowerCaseServiceId() {
|
||||||
|
return lowerCaseServiceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLowerCaseServiceId(boolean lowerCaseServiceId) {
|
||||||
|
this.lowerCaseServiceId = lowerCaseServiceId;
|
||||||
|
}
|
||||||
|
|
||||||
public List<PredicateDefinition> getPredicates() {
|
public List<PredicateDefinition> getPredicates() {
|
||||||
return predicates;
|
return predicates;
|
||||||
}
|
}
|
||||||
@@ -106,6 +121,7 @@ public class DiscoveryLocatorProperties {
|
|||||||
.append("routeIdPrefix", routeIdPrefix)
|
.append("routeIdPrefix", routeIdPrefix)
|
||||||
.append("includeExpression", includeExpression)
|
.append("includeExpression", includeExpression)
|
||||||
.append("urlExpression", urlExpression)
|
.append("urlExpression", urlExpression)
|
||||||
|
.append("lowerCaseServiceId", lowerCaseServiceId)
|
||||||
.append("predicates", predicates)
|
.append("predicates", predicates)
|
||||||
.append("filters", filters)
|
.append("filters", filters)
|
||||||
.toString();
|
.toString();
|
||||||
|
|||||||
@@ -49,11 +49,12 @@ import static org.springframework.cloud.gateway.handler.predicate.RoutePredicate
|
|||||||
properties = {"spring.cloud.gateway.discovery.locator.enabled=true",
|
properties = {"spring.cloud.gateway.discovery.locator.enabled=true",
|
||||||
"spring.cloud.gateway.discovery.locator.route-id-prefix=testedge_",
|
"spring.cloud.gateway.discovery.locator.route-id-prefix=testedge_",
|
||||||
"spring.cloud.gateway.discovery.locator.include-expression=metadata['edge'] == 'true'",
|
"spring.cloud.gateway.discovery.locator.include-expression=metadata['edge'] == 'true'",
|
||||||
"spring.cloud.gateway.discovery.locator.predicates[0].name=Path",
|
"spring.cloud.gateway.discovery.locator.lower-case-service-id=true",
|
||||||
|
/*"spring.cloud.gateway.discovery.locator.predicates[0].name=Path",
|
||||||
"spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]='/'+serviceId.toLowerCase()+'/**'",
|
"spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]='/'+serviceId.toLowerCase()+'/**'",
|
||||||
"spring.cloud.gateway.discovery.locator.filters[0].name=RewritePath",
|
"spring.cloud.gateway.discovery.locator.filters[0].name=RewritePath",
|
||||||
"spring.cloud.gateway.discovery.locator.filters[0].args[regexp]='/' + serviceId.toLowerCase() + '/(?<remaining>.*)'",
|
"spring.cloud.gateway.discovery.locator.filters[0].args[regexp]='/' + serviceId.toLowerCase() + '/(?<remaining>.*)'",
|
||||||
"spring.cloud.gateway.discovery.locator.filters[0].args[replacement]='/$\\\\{remaining}'",
|
"spring.cloud.gateway.discovery.locator.filters[0].args[replacement]='/$\\\\{remaining}'",*/
|
||||||
})
|
})
|
||||||
public class DiscoveryClientRouteDefinitionLocatorTests {
|
public class DiscoveryClientRouteDefinitionLocatorTests {
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ public class DiscoveryClientRouteDefinitionLocatorTests {
|
|||||||
assertThat(filter.getName()).isEqualTo("RewritePath");
|
assertThat(filter.getName()).isEqualTo("RewritePath");
|
||||||
assertThat(filter.getArgs()).hasSize(2)
|
assertThat(filter.getArgs()).hasSize(2)
|
||||||
.containsEntry(REGEXP_KEY, "/service1/(?<remaining>.*)")
|
.containsEntry(REGEXP_KEY, "/service1/(?<remaining>.*)")
|
||||||
.containsEntry(REPLACEMENT_KEY, "/$\\{remaining}");
|
.containsEntry(REPLACEMENT_KEY, "/${remaining}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@SpringBootConfiguration
|
@SpringBootConfiguration
|
||||||
|
|||||||
Reference in New Issue
Block a user