Bumping versions

This commit is contained in:
buildmaster
2024-07-23 12:11:58 +00:00
parent 4a2c6d836f
commit 656ab5aba4
292 changed files with 5555 additions and 3015 deletions

View File

@@ -120,35 +120,43 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
getAvailableEndpointsForClass(AbstractGatewayControllerEndpoint.class.getName()),
getAvailableEndpointsForClass(GatewayControllerEndpoint.class.getName()));
return Flux.fromIterable(endpoints).map(p -> p)
.flatMap(path -> this.routeLocator.getRoutes().map(r -> generateHref(r, path)).distinct().collectList()
.flatMapMany(Flux::fromIterable))
.distinct() // Ensure overall uniqueness
.collectList();
return Flux.fromIterable(endpoints)
.map(p -> p)
.flatMap(path -> this.routeLocator.getRoutes()
.map(r -> generateHref(r, path))
.distinct()
.collectList()
.flatMapMany(Flux::fromIterable))
.distinct() // Ensure overall uniqueness
.collectList();
}
private List<GatewayEndpointInfo> mergeEndpoints(List<GatewayEndpointInfo> listA, List<GatewayEndpointInfo> listB) {
Map<String, List<String>> mergedMap = new HashMap<>();
Stream.concat(listA.stream(), listB.stream()).forEach(e -> mergedMap
.computeIfAbsent(e.getHref(), k -> new ArrayList<>()).addAll(Arrays.asList(e.getMethods())));
Stream.concat(listA.stream(), listB.stream())
.forEach(e -> mergedMap.computeIfAbsent(e.getHref(), k -> new ArrayList<>())
.addAll(Arrays.asList(e.getMethods())));
return mergedMap.entrySet().stream().map(entry -> new GatewayEndpointInfo(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
return mergedMap.entrySet()
.stream()
.map(entry -> new GatewayEndpointInfo(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
private List<GatewayEndpointInfo> getAvailableEndpointsForClass(String className) {
try {
MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader(className);
Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata()
.getAnnotatedMethods(RequestMapping.class.getName());
.getAnnotatedMethods(RequestMapping.class.getName());
String gatewayActuatorPath = webEndpointProperties.getBasePath() + "/gateway";
return annotatedMethods.stream().map(method -> new GatewayEndpointInfo(gatewayActuatorPath
+ ((String[]) method.getAnnotationAttributes(RequestMapping.class.getName()).get("path"))[0],
((RequestMethod[]) method.getAnnotationAttributes(RequestMapping.class.getName()).get("method"))[0]
.name()))
.collect(Collectors.toList());
return annotatedMethods.stream()
.map(method -> new GatewayEndpointInfo(gatewayActuatorPath
+ ((String[]) method.getAnnotationAttributes(RequestMapping.class.getName()).get("path"))[0],
((RequestMethod[]) method.getAnnotationAttributes(RequestMapping.class.getName())
.get("method"))[0].name()))
.collect(Collectors.toList());
}
catch (IOException exception) {
log.warn(exception.getMessage());
@@ -186,8 +194,9 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
}
private Map<String, Object> convertToMap(List<String> byMetadata) {
return byMetadata.stream().map(keyValueStr -> keyValueStr.split(":"))
.collect(Collectors.toMap(kv -> kv[0], kv -> kv.length > 1 ? kv[1] : null));
return byMetadata.stream()
.map(keyValueStr -> keyValueStr.split(":"))
.collect(Collectors.toMap(kv -> kv[0], kv -> kv.length > 1 ? kv[1] : null));
}
@GetMapping("/globalfilters")
@@ -228,13 +237,14 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
@SuppressWarnings("unchecked")
public Mono<ResponseEntity<Object>> save(@PathVariable String id, @RequestBody RouteDefinition route) {
return Mono.just(route).doOnNext(this::validateRouteDefinition)
.flatMap(routeDefinition -> this.routeDefinitionWriter.save(Mono.just(routeDefinition).map(r -> {
r.setId(id);
log.debug("Saving route: " + route);
return r;
})).then(Mono.defer(() -> Mono.just(ResponseEntity.created(URI.create("/routes/" + id)).build()))))
.switchIfEmpty(Mono.defer(() -> Mono.just(ResponseEntity.badRequest().build())));
return Mono.just(route)
.doOnNext(this::validateRouteDefinition)
.flatMap(routeDefinition -> this.routeDefinitionWriter.save(Mono.just(routeDefinition).map(r -> {
r.setId(id);
log.debug("Saving route: " + route);
return r;
})).then(Mono.defer(() -> Mono.just(ResponseEntity.created(URI.create("/routes/" + id)).build()))))
.switchIfEmpty(Mono.defer(() -> Mono.just(ResponseEntity.badRequest().build())));
}
@PostMapping("/routes")
@@ -246,11 +256,12 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
});
return Flux.fromIterable(routes)
.flatMap(routeDefinition -> this.routeDefinitionWriter.save(Mono.just(routeDefinition).map(r -> {
log.debug("Saving route: " + routeDefinition);
return r;
}))).then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build())))
.switchIfEmpty(Mono.defer(() -> Mono.just(ResponseEntity.badRequest().build())));
.flatMap(routeDefinition -> this.routeDefinitionWriter.save(Mono.just(routeDefinition).map(r -> {
log.debug("Saving route: " + routeDefinition);
return r;
})))
.then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build())))
.switchIfEmpty(Mono.defer(() -> Mono.just(ResponseEntity.badRequest().build())));
}
private void validateRouteId(RouteDefinition routeDefinition) {
@@ -260,11 +271,17 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
}
private void validateRouteDefinition(RouteDefinition routeDefinition) {
Set<String> unavailableFilterDefinitions = routeDefinition.getFilters().stream().filter(rd -> !isAvailable(rd))
.map(FilterDefinition::getName).collect(Collectors.toSet());
Set<String> unavailableFilterDefinitions = routeDefinition.getFilters()
.stream()
.filter(rd -> !isAvailable(rd))
.map(FilterDefinition::getName)
.collect(Collectors.toSet());
Set<String> unavailablePredicatesDefinitions = routeDefinition.getPredicates().stream()
.filter(rd -> !isAvailable(rd)).map(PredicateDefinition::getName).collect(Collectors.toSet());
Set<String> unavailablePredicatesDefinitions = routeDefinition.getPredicates()
.stream()
.filter(rd -> !isAvailable(rd))
.map(PredicateDefinition::getName)
.collect(Collectors.toSet());
if (!unavailableFilterDefinitions.isEmpty()) {
handleUnavailableDefinition(FilterDefinition.class.getSimpleName(), unavailableFilterDefinitions);
}
@@ -298,12 +315,12 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
private boolean isAvailable(FilterDefinition filterDefinition) {
return GatewayFilters.stream()
.anyMatch(gatewayFilterFactory -> filterDefinition.getName().equals(gatewayFilterFactory.name()));
.anyMatch(gatewayFilterFactory -> filterDefinition.getName().equals(gatewayFilterFactory.name()));
}
private boolean isAvailable(PredicateDefinition predicateDefinition) {
return routePredicates.stream()
.anyMatch(routePredicate -> predicateDefinition.getName().equals(routePredicate.name()));
.anyMatch(routePredicate -> predicateDefinition.getName().equals(routePredicate.name()));
}
@DeleteMapping("/routes/{id}")
@@ -317,8 +334,9 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
@GetMapping("/routes/{id}/combinedfilters")
public Mono<HashMap<String, Object>> combinedfilters(@PathVariable String id) {
// TODO: missing global filters
return this.routeLocator.getRoutes().filter(route -> route.getId().equals(id)).reduce(new HashMap<>(),
this::putItem);
return this.routeLocator.getRoutes()
.filter(route -> route.getId().equals(id))
.reduce(new HashMap<>(), this::putItem);
}
}

View File

@@ -56,7 +56,7 @@ public class GatewayLegacyControllerEndpoint extends AbstractGatewayControllerEn
@GetMapping("/routes")
public Mono<List<Map<String, Object>>> routes() {
Mono<Map<String, RouteDefinition>> routeDefs = this.routeDefinitionLocator.getRouteDefinitions()
.collectMap(RouteDefinition::getId);
.collectMap(RouteDefinition::getId);
Mono<List<Route>> routes = this.routeLocator.getRoutes().collectList();
return Mono.zip(routeDefs, routes).map(tuple -> {
Map<String, RouteDefinition> defs = tuple.getT1();
@@ -103,8 +103,11 @@ public class GatewayLegacyControllerEndpoint extends AbstractGatewayControllerEn
@GetMapping("/routes/{id}")
public Mono<ResponseEntity<RouteDefinition>> route(@PathVariable String id) {
// TODO: missing RouteLocator
return this.routeDefinitionLocator.getRouteDefinitions().filter(route -> route.getId().equals(id))
.singleOrEmpty().map(ResponseEntity::ok).switchIfEmpty(Mono.just(ResponseEntity.notFound().build()));
return this.routeDefinitionLocator.getRouteDefinitions()
.filter(route -> route.getId().equals(id))
.singleOrEmpty()
.map(ResponseEntity::ok)
.switchIfEmpty(Mono.just(ResponseEntity.notFound().build()));
}
}

View File

@@ -87,7 +87,7 @@ public abstract class AbstractSslConfigurer<T, S> {
try {
if (ssl.getKeyStore() != null && ssl.getKeyStore().length() > 0) {
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
char[] keyPassword = ssl.getKeyPassword() != null ? ssl.getKeyPassword().toCharArray() : null;
if (keyPassword == null && ssl.getKeyStorePassword() != null) {

View File

@@ -106,8 +106,9 @@ class ConfigurableHintsRegistrationProcessor implements BeanFactoryInitializatio
private static void addGenericsForClass(Set<Class<?>> genericsToAdd, ResolvableType resolvableType) {
if (resolvableType.getSuperType().hasGenerics()) {
genericsToAdd.addAll(Arrays.stream(resolvableType.getSuperType().getGenerics()).map(ResolvableType::toClass)
.collect(Collectors.toSet()));
genericsToAdd.addAll(Arrays.stream(resolvableType.getSuperType().getGenerics())
.map(ResolvableType::toClass)
.collect(Collectors.toSet()));
}
}

View File

@@ -356,7 +356,7 @@ public class GatewayAutoConfiguration {
public GrpcSslConfigurer grpcSslConfigurer(HttpClientProperties properties)
throws KeyStoreException, NoSuchAlgorithmException {
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(KeyStore.getInstance(KeyStore.getDefaultType()));
return new GrpcSslConfigurer(properties.getSsl());
@@ -792,7 +792,7 @@ public class GatewayAutoConfiguration {
HttpClient httpClient) {
Supplier<WebsocketClientSpec.Builder> builderSupplier = () -> {
WebsocketClientSpec.Builder builder = WebsocketClientSpec.builder()
.handlePing(properties.getWebsocket().isProxyPing());
.handlePing(properties.getWebsocket().isProxyPing());
if (properties.getWebsocket().getMaxFramePayloadLength() != null) {
builder.maxFramePayloadLength(properties.getWebsocket().getMaxFramePayloadLength());
}
@@ -886,19 +886,19 @@ class GatewayHints implements RuntimeHintsRegistrar {
return;
}
hints.reflection()
.registerType(TypeReference.of(FilterDefinition.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference.of(PredicateDefinition.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference.of(AbstractNameValueGatewayFilterFactory.NameValueConfig.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference.of(
"org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator$DelegatingServiceInstance"),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS));
.registerType(TypeReference.of(FilterDefinition.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference.of(PredicateDefinition.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference.of(AbstractNameValueGatewayFilterFactory.NameValueConfig.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference
.of("org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator$DelegatingServiceInstance"),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS));
}
}

View File

@@ -27,8 +27,9 @@ public class GatewayEnvironmentPostProcessor implements EnvironmentPostProcessor
@Override
public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication application) {
env.getPropertySources().addFirst(new MapPropertySource("gateway-properties",
Collections.singletonMap("spring.webflux.hiddenmethod.filter.enabled", "false")));
env.getPropertySources()
.addFirst(new MapPropertySource("gateway-properties",
Collections.singletonMap("spring.webflux.hiddenmethod.filter.enabled", "false")));
}
}

View File

@@ -79,8 +79,10 @@ public class GatewayMetricsProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("enabled", enabled).append("prefix", prefix).append("tags", tags)
.toString();
return new ToStringCreator(this).append("enabled", enabled)
.append("prefix", prefix)
.append("tags", tags)
.toString();
}

View File

@@ -105,9 +105,11 @@ public class GatewayProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("routes", routes).append("defaultFilters", defaultFilters)
.append("streamingMediaTypes", streamingMediaTypes)
.append("failOnRouteDefinitionError", failOnRouteDefinitionError).toString();
return new ToStringCreator(this).append("routes", routes)
.append("defaultFilters", defaultFilters)
.append("streamingMediaTypes", streamingMediaTypes)
.append("failOnRouteDefinitionError", failOnRouteDefinitionError)
.toString();
}

View File

@@ -50,7 +50,10 @@ public class GatewayReactiveOAuth2AutoConfiguration {
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder
.builder().authorizationCode().refreshToken().build();
.builder()
.authorizationCode()
.refreshToken()
.build();
DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

View File

@@ -87,7 +87,7 @@ class GatewayRedisAutoConfiguration {
Jackson2JsonRedisSerializer<RouteDefinition> valueSerializer = new Jackson2JsonRedisSerializer<>(
RouteDefinition.class);
RedisSerializationContext.RedisSerializationContextBuilder<String, RouteDefinition> builder = RedisSerializationContext
.newSerializationContext(keySerializer);
.newSerializationContext(keySerializer);
RedisSerializationContext<String, RouteDefinition> context = builder.value(valueSerializer).build();
return new ReactiveRedisTemplate<>(factory, context);

View File

@@ -80,8 +80,8 @@ public class HttpClientFactory extends AbstractFactoryBean<HttpClient> {
ConnectionProvider connectionProvider = buildConnectionProvider(properties);
HttpClient httpClient = HttpClient.create(connectionProvider)
// TODO: move customizations to HttpClientCustomizers
.httpResponseDecoder(this::httpResponseDecoder);
// TODO: move customizations to HttpClientCustomizers
.httpResponseDecoder(this::httpResponseDecoder);
if (serverProperties.getHttp2().isEnabled()) {
httpClient = httpClient.protocol(HttpProtocol.HTTP11, HttpProtocol.H2);
@@ -170,13 +170,15 @@ public class HttpClientFactory extends AbstractFactoryBean<HttpClient> {
// create either Fixed or Elastic pool
ConnectionProvider.Builder builder = ConnectionProvider.builder(pool.getName());
if (pool.getType() == FIXED) {
builder.maxConnections(pool.getMaxConnections()).pendingAcquireMaxCount(-1)
.pendingAcquireTimeout(Duration.ofMillis(pool.getAcquireTimeout()));
builder.maxConnections(pool.getMaxConnections())
.pendingAcquireMaxCount(-1)
.pendingAcquireTimeout(Duration.ofMillis(pool.getAcquireTimeout()));
}
else {
// Elastic
builder.maxConnections(Integer.MAX_VALUE).pendingAcquireTimeout(Duration.ofMillis(0))
.pendingAcquireMaxCount(-1);
builder.maxConnections(Integer.MAX_VALUE)
.pendingAcquireTimeout(Duration.ofMillis(0))
.pendingAcquireMaxCount(-1);
}
if (pool.getMaxIdleTime() != null) {

View File

@@ -499,10 +499,11 @@ public class HttpClientProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("useInsecureTrustManager", useInsecureTrustManager)
.append("trustedX509Certificates", trustedX509Certificates)
.append("handshakeTimeout", handshakeTimeout)
.append("closeNotifyFlushTimeout", closeNotifyFlushTimeout)
.append("closeNotifyReadTimeout", closeNotifyReadTimeout).toString();
.append("trustedX509Certificates", trustedX509Certificates)
.append("handshakeTimeout", handshakeTimeout)
.append("closeNotifyFlushTimeout", closeNotifyFlushTimeout)
.append("closeNotifyReadTimeout", closeNotifyReadTimeout)
.toString();
}
}
@@ -534,7 +535,8 @@ public class HttpClientProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("maxFramePayloadLength", maxFramePayloadLength)
.append("proxyPing", proxyPing).toString();
.append("proxyPing", proxyPing)
.toString();
}
}

View File

@@ -68,9 +68,10 @@ public class HttpClientSslConfigurer extends AbstractSslConfigurer<HttpClient, H
}
});
sslContextSpec.sslContext(clientSslContext).handshakeTimeout(ssl.getHandshakeTimeout())
.closeNotifyFlushTimeout(ssl.getCloseNotifyFlushTimeout())
.closeNotifyReadTimeout(ssl.getCloseNotifyReadTimeout());
sslContextSpec.sslContext(clientSslContext)
.handshakeTimeout(ssl.getHandshakeTimeout())
.closeNotifyFlushTimeout(ssl.getCloseNotifyFlushTimeout())
.closeNotifyReadTimeout(ssl.getCloseNotifyReadTimeout());
}
}

View File

@@ -61,7 +61,7 @@ public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLoc
DiscoveryLocatorProperties properties) {
this(discoveryClient.getClass().getSimpleName(), properties);
serviceInstances = discoveryClient.getServices()
.flatMap(service -> discoveryClient.getInstances(service).collectList());
.flatMap(service -> discoveryClient.getInstances(service).collectList());
}
private DiscoveryClientRouteDefinitionLocator(String discoveryClientName, DiscoveryLocatorProperties properties) {
@@ -96,36 +96,39 @@ public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLoc
};
}
return serviceInstances.filter(instances -> !instances.isEmpty()).flatMap(Flux::fromIterable)
.filter(includePredicate).collectMap(ServiceInstance::getServiceId)
// remove duplicates
.flatMapMany(map -> Flux.fromIterable(map.values())).map(instance -> {
RouteDefinition routeDefinition = buildRouteDefinition(urlExpr, instance);
return serviceInstances.filter(instances -> !instances.isEmpty())
.flatMap(Flux::fromIterable)
.filter(includePredicate)
.collectMap(ServiceInstance::getServiceId)
// remove duplicates
.flatMapMany(map -> Flux.fromIterable(map.values()))
.map(instance -> {
RouteDefinition routeDefinition = buildRouteDefinition(urlExpr, instance);
final ServiceInstance instanceForEval = new DelegatingServiceInstance(instance, properties);
final ServiceInstance instanceForEval = new DelegatingServiceInstance(instance, properties);
for (PredicateDefinition original : this.properties.getPredicates()) {
PredicateDefinition predicate = new PredicateDefinition();
predicate.setName(original.getName());
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
String value = getValueFromExpr(evalCtxt, parser, instanceForEval, entry);
predicate.addArg(entry.getKey(), value);
}
routeDefinition.getPredicates().add(predicate);
for (PredicateDefinition original : this.properties.getPredicates()) {
PredicateDefinition predicate = new PredicateDefinition();
predicate.setName(original.getName());
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
String value = getValueFromExpr(evalCtxt, parser, instanceForEval, entry);
predicate.addArg(entry.getKey(), value);
}
routeDefinition.getPredicates().add(predicate);
}
for (FilterDefinition original : this.properties.getFilters()) {
FilterDefinition filter = new FilterDefinition();
filter.setName(original.getName());
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
String value = getValueFromExpr(evalCtxt, parser, instanceForEval, entry);
filter.addArg(entry.getKey(), value);
}
routeDefinition.getFilters().add(filter);
for (FilterDefinition original : this.properties.getFilters()) {
FilterDefinition filter = new FilterDefinition();
filter.setName(original.getName());
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
String value = getValueFromExpr(evalCtxt, parser, instanceForEval, entry);
filter.addArg(entry.getKey(), value);
}
routeDefinition.getFilters().add(filter);
}
return routeDefinition;
});
return routeDefinition;
});
}
protected RouteDefinition buildRouteDefinition(Expression urlExpr, ServiceInstance serviceInstance) {

View File

@@ -116,10 +116,14 @@ public class DiscoveryLocatorProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("enabled", enabled).append("routeIdPrefix", routeIdPrefix)
.append("includeExpression", includeExpression).append("urlExpression", urlExpression)
.append("lowerCaseServiceId", lowerCaseServiceId).append("predicates", predicates)
.append("filters", filters).toString();
return new ToStringCreator(this).append("enabled", enabled)
.append("routeIdPrefix", routeIdPrefix)
.append("includeExpression", includeExpression)
.append("urlExpression", urlExpression)
.append("lowerCaseServiceId", lowerCaseServiceId)
.append("predicates", predicates)
.append("filters", filters)
.toString();
}
}

View File

@@ -72,8 +72,9 @@ public class GatewayMetricsFilter implements GlobalFilter, Ordered {
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
Sample sample = Timer.start(meterRegistry);
return chain.filter(exchange).doOnSuccess(aVoid -> endTimerRespectingCommit(exchange, sample))
.doOnError(throwable -> endTimerRespectingCommit(exchange, sample));
return chain.filter(exchange)
.doOnSuccess(aVoid -> endTimerRespectingCommit(exchange, sample))
.doOnError(throwable -> endTimerRespectingCommit(exchange, sample));
}
private void endTimerRespectingCommit(ServerWebExchange exchange, Sample sample) {

View File

@@ -76,7 +76,8 @@ public class LoadBalancerServiceInstanceCookieFilter implements GlobalFilter, Or
ServerWebExchange newExchange = exchange.mutate().request(exchange.getRequest().mutate().headers((headers) -> {
List<String> cookieHeaders = new ArrayList<>(headers.getOrEmpty(HttpHeaders.COOKIE));
String serviceInstanceCookie = new HttpCookie(instanceIdCookieName,
serviceInstanceResponse.getServer().getInstanceId()).toString();
serviceInstanceResponse.getServer().getInstanceId())
.toString();
cookieHeaders.add(serviceInstanceCookie);
headers.put(HttpHeaders.COOKIE, cookieHeaders);
}).build()).build();

View File

@@ -131,69 +131,69 @@ public class NettyRoutingFilter implements GlobalFilter, Ordered {
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
Flux<HttpClientResponse> responseFlux = getHttpClientMono(route, exchange)
.flatMapMany(httpClient -> httpClient.headers(headers -> {
headers.add(httpHeaders);
// Will either be set below, or later by Netty
headers.remove(HttpHeaders.HOST);
if (preserveHost) {
String host = request.getHeaders().getFirst(HttpHeaders.HOST);
headers.add(HttpHeaders.HOST, host);
}
}).request(method).uri(url).send((req, nettyOutbound) -> {
if (log.isTraceEnabled()) {
nettyOutbound.withConnection(connection -> log.trace("outbound route: "
+ connection.channel().id().asShortText() + ", inbound: " + exchange.getLogPrefix()));
}
return nettyOutbound.send(request.getBody().map(this::getByteBuf));
}).responseConnection((res, connection) -> {
.flatMapMany(httpClient -> httpClient.headers(headers -> {
headers.add(httpHeaders);
// Will either be set below, or later by Netty
headers.remove(HttpHeaders.HOST);
if (preserveHost) {
String host = request.getHeaders().getFirst(HttpHeaders.HOST);
headers.add(HttpHeaders.HOST, host);
}
}).request(method).uri(url).send((req, nettyOutbound) -> {
if (log.isTraceEnabled()) {
nettyOutbound.withConnection(connection -> log.trace("outbound route: "
+ connection.channel().id().asShortText() + ", inbound: " + exchange.getLogPrefix()));
}
return nettyOutbound.send(request.getBody().map(this::getByteBuf));
}).responseConnection((res, connection) -> {
// Defer committing the response until all route filters have run
// Put client response as ServerWebExchange attribute and write
// response later NettyWriteResponseFilter
exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
exchange.getAttributes().put(CLIENT_RESPONSE_CONN_ATTR, connection);
// Defer committing the response until all route filters have run
// Put client response as ServerWebExchange attribute and write
// response later NettyWriteResponseFilter
exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
exchange.getAttributes().put(CLIENT_RESPONSE_CONN_ATTR, connection);
ServerHttpResponse response = exchange.getResponse();
// put headers and status so filters can modify the response
HttpHeaders headers = new HttpHeaders();
ServerHttpResponse response = exchange.getResponse();
// put headers and status so filters can modify the response
HttpHeaders headers = new HttpHeaders();
res.responseHeaders().forEach(entry -> headers.add(entry.getKey(), entry.getValue()));
res.responseHeaders().forEach(entry -> headers.add(entry.getKey(), entry.getValue()));
String contentTypeValue = headers.getFirst(HttpHeaders.CONTENT_TYPE);
if (StringUtils.hasLength(contentTypeValue)) {
exchange.getAttributes().put(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR, contentTypeValue);
}
String contentTypeValue = headers.getFirst(HttpHeaders.CONTENT_TYPE);
if (StringUtils.hasLength(contentTypeValue)) {
exchange.getAttributes().put(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR, contentTypeValue);
}
setResponseStatus(res, response);
setResponseStatus(res, response);
// make sure headers filters run after setting status so it is
// available in response
HttpHeaders filteredResponseHeaders = HttpHeadersFilter.filter(getHeadersFilters(), headers,
exchange, Type.RESPONSE);
// make sure headers filters run after setting status so it is
// available in response
HttpHeaders filteredResponseHeaders = HttpHeadersFilter.filter(getHeadersFilters(), headers, exchange,
Type.RESPONSE);
if (!filteredResponseHeaders.containsKey(HttpHeaders.TRANSFER_ENCODING)
&& filteredResponseHeaders.containsKey(HttpHeaders.CONTENT_LENGTH)) {
// It is not valid to have both the transfer-encoding header and
// the content-length header.
// Remove the transfer-encoding header in the response if the
// content-length header is present.
response.getHeaders().remove(HttpHeaders.TRANSFER_ENCODING);
}
if (!filteredResponseHeaders.containsKey(HttpHeaders.TRANSFER_ENCODING)
&& filteredResponseHeaders.containsKey(HttpHeaders.CONTENT_LENGTH)) {
// It is not valid to have both the transfer-encoding header and
// the content-length header.
// Remove the transfer-encoding header in the response if the
// content-length header is present.
response.getHeaders().remove(HttpHeaders.TRANSFER_ENCODING);
}
exchange.getAttributes().put(CLIENT_RESPONSE_HEADER_NAMES, filteredResponseHeaders.keySet());
exchange.getAttributes().put(CLIENT_RESPONSE_HEADER_NAMES, filteredResponseHeaders.keySet());
response.getHeaders().addAll(filteredResponseHeaders);
response.getHeaders().addAll(filteredResponseHeaders);
return Mono.just(res);
}));
return Mono.just(res);
}));
Duration responseTimeout = getResponseTimeout(route);
if (responseTimeout != null) {
responseFlux = responseFlux
.timeout(responseTimeout,
Mono.error(new TimeoutException("Response took longer than timeout: " + responseTimeout)))
.onErrorMap(TimeoutException.class,
th -> new ResponseStatusException(HttpStatus.GATEWAY_TIMEOUT, th.getMessage(), th));
.timeout(responseTimeout,
Mono.error(new TimeoutException("Response took longer than timeout: " + responseTimeout)))
.onErrorMap(TimeoutException.class,
th -> new ResponseStatusException(HttpStatus.GATEWAY_TIMEOUT, th.getMessage(), th));
}
return responseFlux.then(chain.filter(exchange));

View File

@@ -111,15 +111,15 @@ public class ReactiveLoadBalancerClientFilter implements GlobalFilter, Ordered {
URI requestUri = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
String serviceId = requestUri.getHost();
Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator
.getSupportedLifecycleProcessors(clientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
RequestDataContext.class, ResponseData.class, ServiceInstance.class);
.getSupportedLifecycleProcessors(clientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
RequestDataContext.class, ResponseData.class, ServiceInstance.class);
DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(new RequestDataContext(
new RequestData(exchange.getRequest(), exchange.getAttributes()), getHint(serviceId)));
return choose(lbRequest, serviceId, supportedLifecycleProcessors).doOnNext(response -> {
if (!response.hasServer()) {
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest, response)));
.onComplete(new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest, response)));
throw NotFoundException.create(properties.isUse404(), "Unable to find instance for " + url.getHost());
}
@@ -145,17 +145,18 @@ public class ReactiveLoadBalancerClientFilter implements GlobalFilter, Ordered {
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
exchange.getAttributes().put(GATEWAY_LOADBALANCER_RESPONSE_ATTR, response);
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, response));
}).then(chain.filter(exchange))
.doOnError(throwable -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.FAILED, throwable, lbRequest,
exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR)))))
.doOnSuccess(aVoid -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.SUCCESS, lbRequest,
exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR),
new ResponseData(exchange.getResponse(),
new RequestData(exchange.getRequest(), exchange.getAttributes()))))));
})
.then(chain.filter(exchange))
.doOnError(throwable -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.FAILED, throwable, lbRequest,
exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR)))))
.doOnSuccess(aVoid -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.SUCCESS, lbRequest,
exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR),
new ResponseData(exchange.getResponse(),
new RequestData(exchange.getRequest(), exchange.getAttributes()))))));
}
protected URI reconstructURI(ServiceInstance serviceInstance, URI original) {

View File

@@ -85,8 +85,12 @@ public class RouteToRequestUrlFilter implements GlobalFilter, Ordered {
}
URI mergedUrl = UriComponentsBuilder.fromUri(uri)
// .uri(routeUri)
.scheme(routeUri.getScheme()).host(routeUri.getHost()).port(routeUri.getPort()).build(encoded).toUri();
// .uri(routeUri)
.scheme(routeUri.getScheme())
.host(routeUri.getHost())
.port(routeUri.getPort())
.build(encoded)
.toUri();
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, mergedUrl);
return chain.filter(exchange);
}

View File

@@ -106,17 +106,17 @@ public class WebClientHttpRoutingFilter implements GlobalFilter, Ordered {
}
return headersSpec.exchangeToMono(Mono::just)
// .log("webClient route")
.flatMap(res -> {
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().putAll(res.headers().asHttpHeaders());
response.setStatusCode(res.statusCode());
// Defer committing the response until all route filters have run
// Put client response as ServerWebExchange attribute and write
// response later NettyWriteResponseFilter
exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
return chain.filter(exchange);
});
// .log("webClient route")
.flatMap(res -> {
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().putAll(res.headers().asHttpHeaders());
response.setStatusCode(res.statusCode());
// Defer committing the response until all route filters have run
// Put client response as ServerWebExchange attribute and write
// response later NettyWriteResponseFilter
exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
return chain.filter(exchange);
});
}
private boolean requiresBody(HttpMethod method) {

View File

@@ -58,8 +58,8 @@ public class WebClientWriteResponseFilter implements GlobalFilter, Ordered {
ServerHttpResponse response = exchange.getResponse();
return response.writeWith(clientResponse.body(BodyExtractors.toDataBuffers()))
// .log("webClient response")
.doOnCancel(() -> cleanup(exchange));
// .log("webClient response")
.doOnCancel(() -> cleanup(exchange));
}));
}

View File

@@ -244,28 +244,32 @@ public class WebsocketRoutingFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> handle(WebSocketSession proxySession) {
Mono<Void> serverClose = proxySession.closeStatus().filter(__ -> session.isOpen())
.map(this::adaptCloseStatus).flatMap(session::close);
Mono<Void> proxyClose = session.closeStatus().filter(__ -> proxySession.isOpen())
.map(this::adaptCloseStatus).flatMap(proxySession::close);
Mono<Void> serverClose = proxySession.closeStatus()
.filter(__ -> session.isOpen())
.map(this::adaptCloseStatus)
.flatMap(session::close);
Mono<Void> proxyClose = session.closeStatus()
.filter(__ -> proxySession.isOpen())
.map(this::adaptCloseStatus)
.flatMap(proxySession::close);
// Use retain() for Reactor Netty
Mono<Void> proxySessionSend = proxySession
.send(session.receive().doOnNext(WebSocketMessage::retain).doOnNext(webSocketMessage -> {
if (log.isTraceEnabled()) {
log.trace("proxySession(send from client): " + proxySession.getId()
+ ", corresponding session:" + session.getId() + ", packet: "
+ webSocketMessage.getPayloadAsText());
}
}));
.send(session.receive().doOnNext(WebSocketMessage::retain).doOnNext(webSocketMessage -> {
if (log.isTraceEnabled()) {
log.trace("proxySession(send from client): " + proxySession.getId()
+ ", corresponding session:" + session.getId() + ", packet: "
+ webSocketMessage.getPayloadAsText());
}
}));
// .log("proxySessionSend", Level.FINE);
Mono<Void> serverSessionSend = session.send(
proxySession.receive().doOnNext(WebSocketMessage::retain).doOnNext(webSocketMessage -> {
if (log.isTraceEnabled()) {
log.trace("session(send from backend): " + session.getId()
+ ", corresponding proxySession:" + proxySession.getId() + " packet: "
+ webSocketMessage.getPayloadAsText());
}
}));
Mono<Void> serverSessionSend = session
.send(proxySession.receive().doOnNext(WebSocketMessage::retain).doOnNext(webSocketMessage -> {
if (log.isTraceEnabled()) {
log.trace("session(send from backend): " + session.getId()
+ ", corresponding proxySession:" + proxySession.getId() + " packet: "
+ webSocketMessage.getPayloadAsText());
}
}));
// .log("sessionSend", Level.FINE);
// Ensure closeStatus from one propagates to the other
Mono.when(serverClose, proxyClose).subscribe();

View File

@@ -315,8 +315,11 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli
@Override
public String toString() {
return new ToStringCreator(this).append("group", group).append("weights", weights)
.append("normalizedWeights", normalizedWeights).append("rangeIndexes", rangeIndexes).toString();
return new ToStringCreator(this).append("group", group)
.append("weights", weights)
.append("normalizedWeights", normalizedWeights)
.append("rangeIndexes", rangeIndexes)
.toString();
}
}

View File

@@ -106,17 +106,17 @@ public class CorsGatewayFilterApplicationListener implements ApplicationListener
final CorsConfiguration corsConfiguration = new CorsConfiguration();
findValue(corsMetadata, "allowCredentials")
.ifPresent(value -> corsConfiguration.setAllowCredentials((Boolean) value));
.ifPresent(value -> corsConfiguration.setAllowCredentials((Boolean) value));
findValue(corsMetadata, "allowedHeaders")
.ifPresent(value -> corsConfiguration.setAllowedHeaders(asList(value)));
.ifPresent(value -> corsConfiguration.setAllowedHeaders(asList(value)));
findValue(corsMetadata, "allowedMethods")
.ifPresent(value -> corsConfiguration.setAllowedMethods(asList(value)));
.ifPresent(value -> corsConfiguration.setAllowedMethods(asList(value)));
findValue(corsMetadata, "allowedOriginPatterns")
.ifPresent(value -> corsConfiguration.setAllowedOriginPatterns(asList(value)));
.ifPresent(value -> corsConfiguration.setAllowedOriginPatterns(asList(value)));
findValue(corsMetadata, "allowedOrigins")
.ifPresent(value -> corsConfiguration.setAllowedOrigins(asList(value)));
.ifPresent(value -> corsConfiguration.setAllowedOrigins(asList(value)));
findValue(corsMetadata, "exposedHeaders")
.ifPresent(value -> corsConfiguration.setExposedHeaders(asList(value)));
.ifPresent(value -> corsConfiguration.setExposedHeaders(asList(value)));
findValue(corsMetadata, "maxAge").ifPresent(value -> corsConfiguration.setMaxAge(asLong(value)));
return Optional.of(corsConfiguration);

View File

@@ -37,8 +37,10 @@ public class AddRequestHeaderGatewayFilterFactory extends AbstractNameValueGatew
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String value = ServerWebExchangeUtils.expand(exchange, config.getValue());
ServerHttpRequest request = exchange.getRequest().mutate()
.headers(httpHeaders -> httpHeaders.add(config.getName(), value)).build();
ServerHttpRequest request = exchange.getRequest()
.mutate()
.headers(httpHeaders -> httpHeaders.add(config.getName(), value))
.build();
return chain.filter(exchange.mutate().request(request).build());
}
@@ -46,7 +48,8 @@ public class AddRequestHeaderGatewayFilterFactory extends AbstractNameValueGatew
@Override
public String toString() {
return filterToStringCreator(AddRequestHeaderGatewayFilterFactory.this)
.append(config.getName(), config.getValue()).toString();
.append(config.getName(), config.getValue())
.toString();
}
};
}

View File

@@ -69,8 +69,11 @@ public class AddRequestHeadersIfNotPresentGatewayFilterFactory
for (Map.Entry<String, List<String>> kv : aggregatedHeaders.entrySet()) {
String headerName = kv.getKey();
boolean headerIsMissingOrBlank = exchange.getRequest().getHeaders().getOrEmpty(headerName).stream()
.allMatch(h -> !StringUtils.hasText(h));
boolean headerIsMissingOrBlank = exchange.getRequest()
.getHeaders()
.getOrEmpty(headerName)
.stream()
.allMatch(h -> !StringUtils.hasText(h));
if (headerIsMissingOrBlank) {
if (requestBuilder == null) {
@@ -78,9 +81,10 @@ public class AddRequestHeadersIfNotPresentGatewayFilterFactory
}
ServerWebExchange finalExchange = exchange;
requestBuilder.headers(httpHeaders -> {
List<String> replacedValues = kv.getValue().stream()
.map(value -> ServerWebExchangeUtils.expand(finalExchange, value))
.collect(Collectors.toList());
List<String> replacedValues = kv.getValue()
.stream()
.map(value -> ServerWebExchangeUtils.expand(finalExchange, value))
.collect(Collectors.toList());
httpHeaders.addAll(headerName, replacedValues);
});
}

View File

@@ -60,8 +60,10 @@ public class AddRequestParameterGatewayFilterFactory extends AbstractNameValueGa
boolean encoded = containsEncodedParts(uri);
try {
URI newUri = UriComponentsBuilder.fromUri(uri).replaceQuery(query.toString()).build(encoded)
.toUri();
URI newUri = UriComponentsBuilder.fromUri(uri)
.replaceQuery(query.toString())
.build(encoded)
.toUri();
ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri).build();
@@ -75,7 +77,8 @@ public class AddRequestParameterGatewayFilterFactory extends AbstractNameValueGa
@Override
public String toString() {
return filterToStringCreator(AddRequestParameterGatewayFilterFactory.this)
.append(config.getName(), config.getValue()).toString();
.append(config.getName(), config.getValue())
.toString();
}
};
}

View File

@@ -42,7 +42,8 @@ public class AddResponseHeaderGatewayFilterFactory extends AbstractNameValueGate
@Override
public String toString() {
return filterToStringCreator(AddResponseHeaderGatewayFilterFactory.this)
.append(config.getName(), config.getValue()).toString();
.append(config.getName(), config.getValue())
.toString();
}
};
}

View File

@@ -77,23 +77,23 @@ public class CacheRequestBodyGatewayFilterFactory
return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> {
final ServerRequest serverRequest = ServerRequest
.create(exchange.mutate().request(serverHttpRequest).build(), messageReaders);
.create(exchange.mutate().request(serverHttpRequest).build(), messageReaders);
return serverRequest.bodyToMono((config.getBodyClass())).doOnNext(objectValue -> {
Object previousCachedBody = exchange.getAttributes()
.put(ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR, objectValue);
.put(ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR, objectValue);
if (previousCachedBody != null) {
// store previous cached body
exchange.getAttributes().put(CACHED_ORIGINAL_REQUEST_BODY_BACKUP_ATTR, previousCachedBody);
}
}).then(Mono.defer(() -> {
ServerHttpRequest cachedRequest = exchange
.getAttribute(CACHED_SERVER_HTTP_REQUEST_DECORATOR_ATTR);
.getAttribute(CACHED_SERVER_HTTP_REQUEST_DECORATOR_ATTR);
Assert.notNull(cachedRequest, "cache request shouldn't be null");
exchange.getAttributes().remove(CACHED_SERVER_HTTP_REQUEST_DECORATOR_ATTR);
return chain.filter(exchange.mutate().request(cachedRequest).build()).doFinally(s -> {
//
Object backupCachedBody = exchange.getAttributes()
.get(CACHED_ORIGINAL_REQUEST_BODY_BACKUP_ATTR);
.get(CACHED_ORIGINAL_REQUEST_BODY_BACKUP_ATTR);
if (backupCachedBody instanceof DataBuffer dataBuffer) {
DataBufferUtils.release(dataBuffer);
}
@@ -105,7 +105,8 @@ public class CacheRequestBodyGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(CacheRequestBodyGatewayFilterFactory.this)
.append("Body class", config.getBodyClass()).toString();
.append("Body class", config.getBodyClass())
.toString();
}
};
}

View File

@@ -93,13 +93,14 @@ public class DedupeResponseHeaderGatewayFilterFactory
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> dedupe(exchange.getResponse().getHeaders(), config)));
.then(Mono.fromRunnable(() -> dedupe(exchange.getResponse().getHeaders(), config)));
}
@Override
public String toString() {
return filterToStringCreator(DedupeResponseHeaderGatewayFilterFactory.this)
.append(config.getName(), config.getStrategy()).toString();
.append(config.getName(), config.getStrategy())
.toString();
}
};
}

View File

@@ -107,7 +107,7 @@ public class JsonToGrpcGatewayFilterFactory
ServerWebExchangeUtils.setAlreadyRouted(exchange);
return modifiedResponse.writeWith(exchange.getRequest().getBody())
.then(chain.filter(exchange.mutate().response(modifiedResponse).build()));
.then(chain.filter(exchange.mutate().response(modifiedResponse).build()));
}
@Override
@@ -190,7 +190,7 @@ public class JsonToGrpcGatewayFilterFactory
Resource protoFile = resourceLoader.getResource(config.getProtoFile());
descriptor = DescriptorProtos.FileDescriptorProto.parseFrom(descriptorFile.getInputStream())
.getDescriptorForType();
.getDescriptorForType();
Descriptors.MethodDescriptor methodDescriptor = getMethodDescriptor(config,
descriptorFile.getInputStream());
@@ -218,19 +218,25 @@ public class JsonToGrpcGatewayFilterFactory
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
exchange.getResponse().getHeaders().set("Content-Type", "application/json");
return getDelegate().writeWith(deserializeJSONRequest().map(callGRPCServer()).map(serialiseGRPCResponse())
.map(wrapGRPCResponse()).cast(DataBuffer.class).last());
return getDelegate().writeWith(deserializeJSONRequest().map(callGRPCServer())
.map(serialiseGRPCResponse())
.map(wrapGRPCResponse())
.cast(DataBuffer.class)
.last());
}
private ClientCall<DynamicMessage, DynamicMessage> createClientCallForType(Config config,
Descriptors.ServiceDescriptor serviceDescriptor, Descriptors.Descriptor outputType) {
MethodDescriptor.Marshaller<DynamicMessage> marshaller = ProtoUtils
.marshaller(DynamicMessage.newBuilder(outputType).build());
.marshaller(DynamicMessage.newBuilder(outputType).build());
MethodDescriptor<DynamicMessage, DynamicMessage> methodDescriptor = MethodDescriptor
.<DynamicMessage, DynamicMessage>newBuilder().setType(MethodDescriptor.MethodType.UNKNOWN)
.setFullMethodName(MethodDescriptor.generateFullMethodName(serviceDescriptor.getFullName(),
config.getMethod()))
.setRequestMarshaller(marshaller).setResponseMarshaller(marshaller).build();
.<DynamicMessage, DynamicMessage>newBuilder()
.setType(MethodDescriptor.MethodType.UNKNOWN)
.setFullMethodName(
MethodDescriptor.generateFullMethodName(serviceDescriptor.getFullName(), config.getMethod()))
.setRequestMarshaller(marshaller)
.setResponseMarshaller(marshaller)
.build();
Channel channel = createChannel();
return channel.newCall(methodDescriptor, CallOptions.DEFAULT);
}
@@ -238,7 +244,7 @@ public class JsonToGrpcGatewayFilterFactory
private Descriptors.MethodDescriptor getMethodDescriptor(Config config, InputStream descriptorFile)
throws IOException, Descriptors.DescriptorValidationException {
DescriptorProtos.FileDescriptorSet fileDescriptorSet = DescriptorProtos.FileDescriptorSet
.parseFrom(descriptorFile);
.parseFrom(descriptorFile);
DescriptorProtos.FileDescriptorProto fileProto = fileDescriptorSet.getFile(0);
Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor.buildFrom(fileProto,
new Descriptors.FileDescriptor[0]);
@@ -250,8 +256,10 @@ public class JsonToGrpcGatewayFilterFactory
List<Descriptors.MethodDescriptor> methods = serviceDescriptor.getMethods();
return methods.stream().filter(method -> method.getName().equals(config.getMethod())).findFirst()
.orElseThrow(() -> new NoSuchElementException("No Method found"));
return methods.stream()
.filter(method -> method.getName().equals(config.getMethod()))
.findFirst()
.orElseThrow(() -> new NoSuchElementException("No Method found"));
}
private ManagedChannel createChannel() {
@@ -296,7 +304,7 @@ public class JsonToGrpcGatewayFilterFactory
return jsonResponse -> {
try {
return new NettyDataBufferFactory(new PooledByteBufAllocator())
.wrap(Objects.requireNonNull(new ObjectMapper().writeValueAsBytes(jsonResponse)));
.wrap(Objects.requireNonNull(new ObjectMapper().writeValueAsBytes(jsonResponse)));
}
catch (JsonProcessingException e) {
return new NettyDataBufferFactory(new PooledByteBufAllocator()).allocateBuffer();

View File

@@ -64,8 +64,10 @@ public class MapRequestHeaderGatewayFilterFactory
}
List<String> headerValues = exchange.getRequest().getHeaders().get(config.getFromHeader());
ServerHttpRequest request = exchange.getRequest().mutate()
.headers(i -> i.addAll(config.getToHeader(), headerValues)).build();
ServerHttpRequest request = exchange.getRequest()
.mutate()
.headers(i -> i.addAll(config.getToHeader(), headerValues))
.build();
return chain.filter(exchange.mutate().request(request).build());
}

View File

@@ -92,7 +92,7 @@ public class PrefixPathGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(PrefixPathGatewayFilterFactory.this).append("prefix", config.getPrefix())
.toString();
.toString();
}
};
}

View File

@@ -102,8 +102,11 @@ public class RedirectToGatewayFilterFactory
String location;
if (includeRequestParams) {
location = UriComponentsBuilder.fromUri(uri).queryParams(exchange.getRequest().getQueryParams())
.build().toUri().toString();
location = UriComponentsBuilder.fromUri(uri)
.queryParams(exchange.getRequest().getQueryParams())
.build()
.toUri()
.toString();
}
else {
location = uri.toString();
@@ -126,7 +129,8 @@ public class RedirectToGatewayFilterFactory
status = httpStatus.getStatus().toString();
}
return filterToStringCreator(RedirectToGatewayFilterFactory.this).append(status, uri)
.append(INCLUDE_REQUEST_PARAMS_KEY, includeRequestParams).toString();
.append(INCLUDE_REQUEST_PARAMS_KEY, includeRequestParams)
.toString();
}
};
}

View File

@@ -139,7 +139,8 @@ public class RemoveJsonAttributesResponseBodyGatewayFilterFactory extends
@Override
public String toString() {
return new ToStringCreator(this).append("fieldList", fieldList)
.append("deleteRecursively", deleteRecursively).toString();
.append("deleteRecursively", deleteRecursively)
.toString();
}
}

View File

@@ -48,8 +48,10 @@ public class RemoveRequestHeaderGatewayFilterFactory
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest().mutate()
.headers(httpHeaders -> httpHeaders.remove(config.getName())).build();
ServerHttpRequest request = exchange.getRequest()
.mutate()
.headers(httpHeaders -> httpHeaders.remove(config.getName()))
.build();
return chain.filter(exchange.mutate().request(request).build());
}
@@ -57,7 +59,8 @@ public class RemoveRequestHeaderGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RemoveRequestHeaderGatewayFilterFactory.this)
.append("name", config.getName()).toString();
.append("name", config.getName())
.toString();
}
};
}

View File

@@ -58,7 +58,9 @@ public class RemoveRequestParameterGatewayFilterFactory
queryParams.remove(config.getName());
URI newUri = UriComponentsBuilder.fromUri(request.getURI())
.replaceQueryParams(unmodifiableMultiValueMap(queryParams)).build().toUri();
.replaceQueryParams(unmodifiableMultiValueMap(queryParams))
.build()
.toUri();
ServerHttpRequest updatedRequest = exchange.getRequest().mutate().uri(newUri).build();
@@ -68,7 +70,8 @@ public class RemoveRequestParameterGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RemoveRequestParameterGatewayFilterFactory.this)
.append("name", config.getName()).toString();
.append("name", config.getName())
.toString();
}
};
}

View File

@@ -48,13 +48,14 @@ public class RemoveResponseHeaderGatewayFilterFactory
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> exchange.getResponse().getHeaders().remove(config.getName())));
.then(Mono.fromRunnable(() -> exchange.getResponse().getHeaders().remove(config.getName())));
}
@Override
public String toString() {
return filterToStringCreator(RemoveResponseHeaderGatewayFilterFactory.this)
.append("name", config.getName()).toString();
.append("name", config.getName())
.toString();
}
};
}

View File

@@ -83,8 +83,9 @@ public class RequestHeaderSizeGatewayFilterFactory
if (!longHeaders.isEmpty()) {
exchange.getResponse().setStatusCode(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE);
exchange.getResponse().getHeaders().add(errorHeaderName,
getErrorMessage(longHeaders, config.getMaxSize()));
exchange.getResponse()
.getHeaders()
.add(errorHeaderName, getErrorMessage(longHeaders, config.getMaxSize()));
return exchange.getResponse().setComplete();
}
@@ -95,7 +96,8 @@ public class RequestHeaderSizeGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RequestHeaderSizeGatewayFilterFactory.this)
.append("maxSize", config.getMaxSize()).toString();
.append("maxSize", config.getMaxSize())
.toString();
}
};
}
@@ -103,7 +105,7 @@ public class RequestHeaderSizeGatewayFilterFactory
private static String getErrorMessage(HashMap<String, Long> longHeaders, DataSize maxSize) {
StringBuilder msg = new StringBuilder(String.format(ERROR_PREFIX, maxSize));
longHeaders
.forEach((header, size) -> msg.append(String.format(ERROR, header, DataSize.of(size, DataUnit.BYTES))));
.forEach((header, size) -> msg.append(String.format(ERROR, header, DataSize.of(size, DataUnit.BYTES))));
return msg.toString();
}

View File

@@ -59,7 +59,8 @@ public class RequestHeaderToRequestUriGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RequestHeaderToRequestUriGatewayFilterFactory.this)
.append("name", config.getName()).toString();
.append("name", config.getName())
.toString();
}
};
}

View File

@@ -94,7 +94,7 @@ public class RequestRateLimiterGatewayFilterFactory
RateLimiter<Object> limiter = getOrDefault(config.rateLimiter, defaultRateLimiter);
boolean denyEmpty = getOrDefault(config.denyEmptyKey, this.denyEmptyKey);
HttpStatusHolder emptyKeyStatus = HttpStatusHolder
.parse(getOrDefault(config.emptyKeyStatus, this.emptyKeyStatusCode));
.parse(getOrDefault(config.emptyKeyStatus, this.emptyKeyStatusCode));
return (exchange, chain) -> resolver.resolve(exchange).defaultIfEmpty(EMPTY_KEY).flatMap(key -> {
if (EMPTY_KEY.equals(key)) {

View File

@@ -75,8 +75,10 @@ public class RequestSizeGatewayFilterFactory
if (currentRequestSize > requestSizeConfig.getMaxSize().toBytes()) {
exchange.getResponse().setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE);
if (!exchange.getResponse().isCommitted()) {
exchange.getResponse().getHeaders().add("errorMessage",
getErrorMessage(currentRequestSize, requestSizeConfig.getMaxSize().toBytes()));
exchange.getResponse()
.getHeaders()
.add("errorMessage",
getErrorMessage(currentRequestSize, requestSizeConfig.getMaxSize().toBytes()));
}
return exchange.getResponse().setComplete();
}
@@ -87,7 +89,8 @@ public class RequestSizeGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RequestSizeGatewayFilterFactory.this)
.append("max", requestSizeConfig.getMaxSize()).toString();
.append("max", requestSizeConfig.getMaxSize())
.toString();
}
};
}

View File

@@ -118,7 +118,7 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory<Retr
};
statusCodeRepeat = Repeat.onlyIf(repeatPredicate)
.doOnRepeat(context -> reset(context.applicationContext()));
.doOnRepeat(context -> reset(context.applicationContext()));
BackoffConfig backoff = retryConfig.getBackoff();
if (backoff != null) {
@@ -157,7 +157,8 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory<Retr
return false;
};
exceptionRetry = Retry.onlyIf(retryContextPredicate)
.doOnRetry(context -> reset(context.applicationContext())).retryMax(retryConfig.getRetries());
.doOnRetry(context -> reset(context.applicationContext()))
.retryMax(retryConfig.getRetries());
BackoffConfig backoff = retryConfig.getBackoff();
if (backoff != null) {
exceptionRetry = exceptionRetry.backoff(getBackoff(backoff));
@@ -174,9 +175,12 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory<Retr
@Override
public String toString() {
return filterToStringCreator(RetryGatewayFilterFactory.this).append("routeId", retryConfig.getRouteId())
.append("retries", retryConfig.getRetries()).append("series", retryConfig.getSeries())
.append("statuses", retryConfig.getStatuses()).append("methods", retryConfig.getMethods())
.append("exceptions", retryConfig.getExceptions()).toString();
.append("retries", retryConfig.getRetries())
.append("series", retryConfig.getSeries())
.append("statuses", retryConfig.getStatuses())
.append("methods", retryConfig.getMethods())
.append("exceptions", retryConfig.getExceptions())
.toString();
}
};
}
@@ -234,14 +238,15 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory<Retr
// chain.filter returns a Mono<Void>
Publisher<Void> publisher = chain.filter(exchange)
// .log("retry-filter", Level.INFO)
.doOnSuccess(aVoid -> updateIteration(exchange)).doOnError(throwable -> updateIteration(exchange));
// .log("retry-filter", Level.INFO)
.doOnSuccess(aVoid -> updateIteration(exchange))
.doOnError(throwable -> updateIteration(exchange));
if (retry != null) {
// retryWhen returns a Mono<Void>
// retry needs to go before repeat
publisher = ((Mono<Void>) publisher)
.retryWhen(reactor.util.retry.Retry.withThrowable(retry.withApplicationContext(exchange)));
.retryWhen(reactor.util.retry.Retry.withThrowable(retry.withApplicationContext(exchange)));
}
if (repeat != null) {
// repeatWhen returns a Flux<Void>

View File

@@ -79,7 +79,8 @@ public class RewritePathGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RewritePathGatewayFilterFactory.this)
.append(config.getRegexp(), replacement).toString();
.append(config.getRegexp(), replacement)
.toString();
}
};
}

View File

@@ -72,7 +72,8 @@ public class RewriteRequestParameterGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RewriteRequestParameterGatewayFilterFactory.this)
.append(config.getName(), config.replacement).toString();
.append(config.getName(), config.replacement)
.toString();
}
};
}

View File

@@ -65,8 +65,10 @@ public class RewriteResponseHeaderGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RewriteResponseHeaderGatewayFilterFactory.this)
.append("name", config.getName()).append("regexp", config.getRegexp())
.append("replacement", config.getReplacement()).toString();
.append("name", config.getName())
.append("regexp", config.getRegexp())
.append("replacement", config.getReplacement())
.toString();
}
};
}

View File

@@ -78,7 +78,7 @@ public class SetPathGatewayFilterFactory extends AbstractGatewayFilterFactory<Se
@Override
public String toString() {
return filterToStringCreator(SetPathGatewayFilterFactory.this).append("template", config.getTemplate())
.toString();
.toString();
}
};
}

View File

@@ -37,8 +37,10 @@ public class SetRequestHeaderGatewayFilterFactory extends AbstractNameValueGatew
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String value = ServerWebExchangeUtils.expand(exchange, config.getValue());
ServerHttpRequest request = exchange.getRequest().mutate()
.headers(httpHeaders -> httpHeaders.set(config.name, value)).build();
ServerHttpRequest request = exchange.getRequest()
.mutate()
.headers(httpHeaders -> httpHeaders.set(config.name, value))
.build();
return chain.filter(exchange.mutate().request(request).build());
}
@@ -46,7 +48,8 @@ public class SetRequestHeaderGatewayFilterFactory extends AbstractNameValueGatew
@Override
public String toString() {
return filterToStringCreator(SetRequestHeaderGatewayFilterFactory.this)
.append(config.getName(), config.getValue()).toString();
.append(config.getName(), config.getValue())
.toString();
}
};
}

View File

@@ -66,7 +66,7 @@ public class SetRequestHostHeaderGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(SetRequestHostHeaderGatewayFilterFactory.this).append(config.getHost())
.toString();
.toString();
}
};
}

View File

@@ -37,13 +37,14 @@ public class SetResponseHeaderGatewayFilterFactory extends AbstractNameValueGate
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String value = ServerWebExchangeUtils.expand(exchange, config.getValue());
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> exchange.getResponse().getHeaders().set(config.name, value)));
.then(Mono.fromRunnable(() -> exchange.getResponse().getHeaders().set(config.name, value)));
}
@Override
public String toString() {
return filterToStringCreator(SetResponseHeaderGatewayFilterFactory.this)
.append(config.getName(), config.getValue()).toString();
.append(config.getName(), config.getValue())
.toString();
}
};
}

View File

@@ -78,8 +78,9 @@ public class SetStatusGatewayFilterFactory extends AbstractGatewayFilterFactory<
HttpStatusCode statusCode = exchange.getResponse().getStatusCode();
boolean isStatusCodeUpdated = setResponseStatus(exchange, statusHolder);
if (isStatusCodeUpdated && originalStatusHeaderName != null) {
exchange.getResponse().getHeaders().set(originalStatusHeaderName,
singletonList(statusCode.value()).toString());
exchange.getResponse()
.getHeaders()
.set(originalStatusHeaderName, singletonList(statusCode.value()).toString());
}
}));
}
@@ -87,7 +88,7 @@ public class SetStatusGatewayFilterFactory extends AbstractGatewayFilterFactory<
@Override
public String toString() {
return filterToStringCreator(SetStatusGatewayFilterFactory.this).append("status", config.getStatus())
.toString();
.toString();
}
};
}

View File

@@ -90,9 +90,12 @@ public abstract class SpringCloudCircuitBreakerFilterFactory
@Override
public GatewayFilter apply(Config config) {
ReactiveCircuitBreaker cb = reactiveCircuitBreakerFactory.create(config.getId());
Set<HttpStatus> statuses = config.getStatusCodes().stream().map(HttpStatusHolder::parse)
.filter(statusHolder -> statusHolder.getHttpStatus() != null).map(HttpStatusHolder::getHttpStatus)
.collect(Collectors.toSet());
Set<HttpStatus> statuses = config.getStatusCodes()
.stream()
.map(HttpStatusHolder::parse)
.filter(statusHolder -> statusHolder.getHttpStatus() != null)
.map(HttpStatusHolder::getHttpStatus)
.collect(Collectors.toSet());
return new GatewayFilter() {
@Override
@@ -118,8 +121,13 @@ public abstract class SpringCloudCircuitBreakerFilterFactory
config.getFallbackUri().getPath());
String fullFallbackUri = String.format("%s:%s", config.getFallbackUri().getScheme(),
expandedFallbackUri);
URI requestUrl = UriComponentsBuilder.fromUri(uri).host(null).port(null)
.uri(URI.create(fullFallbackUri)).scheme(null).build(encoded).toUri();
URI requestUrl = UriComponentsBuilder.fromUri(uri)
.host(null)
.port(null)
.uri(URI.create(fullFallbackUri))
.scheme(null)
.build(encoded)
.toUri();
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
addExceptionDetails(t, exchange);
@@ -135,7 +143,9 @@ public abstract class SpringCloudCircuitBreakerFilterFactory
@Override
public String toString() {
return filterToStringCreator(SpringCloudCircuitBreakerFilterFactory.this)
.append("name", config.getName()).append("fallback", config.fallbackUri).toString();
.append("name", config.getName())
.append("fallback", config.fallbackUri)
.toString();
}
};
}

View File

@@ -89,7 +89,7 @@ public class StripPrefixGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(StripPrefixGatewayFilterFactory.this).append("parts", config.getParts())
.toString();
.toString();
}
};
}

View File

@@ -58,13 +58,16 @@ public class TokenRelayGatewayFilterFactory
public GatewayFilter apply(NameConfig config) {
String defaultClientRegistrationId = (config == null) ? null : config.getName();
return (exchange, chain) -> exchange.getPrincipal()
// .log("token-relay-filter")
.filter(principal -> principal instanceof Authentication).cast(Authentication.class)
.flatMap(principal -> authorizationRequest(defaultClientRegistrationId, principal))
.flatMap(this::authorizedClient).map(OAuth2AuthorizedClient::getAccessToken)
.map(token -> withBearerAuth(exchange, token))
// TODO: adjustable behavior if empty
.defaultIfEmpty(exchange).flatMap(chain::filter);
// .log("token-relay-filter")
.filter(principal -> principal instanceof Authentication)
.cast(Authentication.class)
.flatMap(principal -> authorizationRequest(defaultClientRegistrationId, principal))
.flatMap(this::authorizedClient)
.map(OAuth2AuthorizedClient::getAccessToken)
.map(token -> withBearerAuth(exchange, token))
// TODO: adjustable behavior if empty
.defaultIfEmpty(exchange)
.flatMap(chain::filter);
}
private Mono<OAuth2AuthorizeRequest> authorizationRequest(String defaultClientRegistrationId,
@@ -73,8 +76,9 @@ public class TokenRelayGatewayFilterFactory
if (clientRegistrationId == null && principal instanceof OAuth2AuthenticationToken) {
clientRegistrationId = ((OAuth2AuthenticationToken) principal).getAuthorizedClientRegistrationId();
}
return Mono.justOrEmpty(clientRegistrationId).map(OAuth2AuthorizeRequest::withClientRegistrationId)
.map(builder -> builder.principal(principal).build());
return Mono.justOrEmpty(clientRegistrationId)
.map(OAuth2AuthorizeRequest::withClientRegistrationId)
.map(builder -> builder.principal(principal).build());
}
private Mono<OAuth2AuthorizedClient> authorizedClient(OAuth2AuthorizeRequest request) {
@@ -89,8 +93,9 @@ public class TokenRelayGatewayFilterFactory
}
private ServerWebExchange withBearerAuth(ServerWebExchange exchange, OAuth2AccessToken accessToken) {
return exchange.mutate().request(r -> r.headers(headers -> headers.setBearerAuth(accessToken.getTokenValue())))
.build();
return exchange.mutate()
.request(r -> r.headers(headers -> headers.setBearerAuth(accessToken.getTokenValue())))
.build();
}
}

View File

@@ -73,7 +73,7 @@ public class ResponseCacheGatewayFilter implements GatewayFilter, Ordered {
}
else {
return chain
.filter(exchange.mutate().response(new CachingResponseDecorator(metadataKey, exchange)).build());
.filter(exchange.mutate().response(new CachingResponseDecorator(metadataKey, exchange)).build());
}
}

View File

@@ -106,7 +106,7 @@ public class ResponseCacheManager {
final CachedResponseMetadata metadata = new CachedResponseMetadata(response.getHeaders().getVary());
final String key = resolveKey(exchange, metadata.varyOnHeaders());
CachedResponse.Builder cachedResponseBuilder = CachedResponse.create(response.getStatusCode())
.headers(response.getHeaders());
.headers(response.getHeaders());
CachedResponse toProcess = cachedResponseBuilder.build();
afterCacheExchangeMutators.forEach(processor -> processor.accept(exchange, toProcess));
@@ -152,7 +152,7 @@ public class ResponseCacheManager {
saveMetadataInCache(metadataKey, new CachedResponseMetadata(cachedResponse.headers().getVary()));
return response
.writeWith(Flux.fromIterable(cachedResponse.body()).map(data -> response.bufferFactory().wrap(data)));
.writeWith(Flux.fromIterable(cachedResponse.body()).map(data -> response.bufferFactory().wrap(data)));
}
private CachedResponseMetadata retrieveMetadata(String metadataKey) {

View File

@@ -41,9 +41,12 @@ class CookiesKeyValueGenerator implements KeyValueGenerator {
String cookiesData = null;
MultiValueMap<String, HttpCookie> cookies = request.getCookies();
if (!CollectionUtils.isEmpty(cookies)) {
cookiesData = cookies.values().stream().flatMap(Collection::stream)
.map(c -> String.format("%s=%s", c.getName(), c.getValue())).sorted()
.collect(Collectors.joining(valueSeparator));
cookiesData = cookies.values()
.stream()
.flatMap(Collection::stream)
.map(c -> String.format("%s=%s", c.getName(), c.getValue()))
.sorted()
.collect(Collectors.joining(valueSeparator));
}
return cookiesData;
}

View File

@@ -47,8 +47,9 @@ class HeaderKeyValueGenerator implements KeyValueGenerator {
HttpHeaders headers = request.getHeaders();
if (headers.get(header) != null) {
StringBuilder keyVaryHeaders = new StringBuilder();
keyVaryHeaders.append(header).append("=")
.append(getHeaderValues(headers).sorted().collect(Collectors.joining(valueSeparator)));
keyVaryHeaders.append(header)
.append("=")
.append(getHeaderValues(headers).sorted().collect(Collectors.joining(valueSeparator)));
return keyVaryHeaders.toString();
}
return null;

View File

@@ -33,8 +33,10 @@ public class SetCacheDirectivesByMaxAgeAfterCacheExchangeMutator implements Afte
@Override
public void accept(ServerWebExchange exchange, CachedResponse cachedResponse) {
Optional<Integer> maxAge = Optional.ofNullable(exchange.getResponse().getHeaders().getCacheControl())
.map(MAX_AGE_PATTERN::matcher).filter(Matcher::find).map(matcher -> matcher.group(1))
.map(Integer::parseInt);
.map(MAX_AGE_PATTERN::matcher)
.filter(Matcher::find)
.map(matcher -> matcher.group(1))
.map(Integer::parseInt);
if (maxAge.isPresent()) {
if (maxAge.get() > 0) {
@@ -66,7 +68,8 @@ public class SetCacheDirectivesByMaxAgeAfterCacheExchangeMutator implements Afte
List<String> cacheControlValues = Arrays.asList(cacheControl.split("\\s*,\\s*"));
String newCacheControl = cacheControlValues.stream()
.filter(s -> !s.matches("must-revalidate|no-cache|no-store")).collect(Collectors.joining(","));
.filter(s -> !s.matches("must-revalidate|no-cache|no-store"))
.collect(Collectors.joining(","));
exchange.getResponse().getHeaders().setCacheControl(newCacheControl);
}

View File

@@ -95,7 +95,8 @@ public class SetMaxAgeHeaderAfterCacheExchangeMutator implements AfterCacheExcha
if (value.contains(MAX_AGE_PREFIX)) {
if (seconds == -1) {
List<String> removedMaxAgeList = Arrays.stream(value.split(","))
.filter(i -> !i.trim().startsWith(MAX_AGE_PREFIX)).collect(Collectors.toList());
.filter(i -> !i.trim().startsWith(MAX_AGE_PREFIX))
.collect(Collectors.toList());
value = String.join(",", removedMaxAgeList);
}
else {

View File

@@ -78,7 +78,7 @@ public class CachedBodyOutputMessage implements ReactiveHttpOutputMessage {
public Flux<DataBuffer> getBody() {
if (body == null) {
return Flux
.error(new IllegalStateException("The body is not set. " + "Did handling complete with success?"));
.error(new IllegalStateException("The body is not set. " + "Did handling complete with success?"));
}
return this.body;
}

View File

@@ -70,8 +70,8 @@ public class ModifyRequestBodyGatewayFilterFactory
// TODO: flux or mono
Mono<?> modifiedBody = serverRequest.bodyToMono(inClass)
.flatMap(originalBody -> config.getRewriteFunction().apply(exchange, originalBody))
.switchIfEmpty(Mono.defer(() -> (Mono) config.getRewriteFunction().apply(exchange, null)));
.flatMap(originalBody -> config.getRewriteFunction().apply(exchange, originalBody))
.switchIfEmpty(Mono.defer(() -> (Mono) config.getRewriteFunction().apply(exchange, null)));
BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, config.getOutClass());
HttpHeaders headers = new HttpHeaders();
@@ -88,19 +88,22 @@ public class ModifyRequestBodyGatewayFilterFactory
}
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
return bodyInserter.insert(outputMessage, new BodyInserterContext())
// .log("modify_request", Level.INFO)
.then(Mono.defer(() -> {
ServerHttpRequest decorator = decorate(exchange, headers, outputMessage);
return chain.filter(exchange.mutate().request(decorator).build());
})).onErrorResume((Function<Throwable, Mono<Void>>) throwable -> release(exchange,
outputMessage, throwable));
// .log("modify_request", Level.INFO)
.then(Mono.defer(() -> {
ServerHttpRequest decorator = decorate(exchange, headers, outputMessage);
return chain.filter(exchange.mutate().request(decorator).build());
}))
.onErrorResume(
(Function<Throwable, Mono<Void>>) throwable -> release(exchange, outputMessage, throwable));
}
@Override
public String toString() {
return filterToStringCreator(ModifyRequestBodyGatewayFilterFactory.this)
.append("Content type", config.getContentType()).append("In class", config.getInClass())
.append("Out class", config.getOutClass()).toString();
.append("Content type", config.getContentType())
.append("In class", config.getInClass())
.append("Out class", config.getOutClass())
.toString();
}
};
}

View File

@@ -67,9 +67,9 @@ public class ModifyResponseBodyGatewayFilterFactory
super(Config.class);
this.messageReaders = messageReaders;
this.messageBodyDecoders = messageBodyDecoders.stream()
.collect(Collectors.toMap(MessageBodyDecoder::encodingType, identity()));
.collect(Collectors.toMap(MessageBodyDecoder::encodingType, identity()));
this.messageBodyEncoders = messageBodyEncoders.stream()
.collect(Collectors.toMap(MessageBodyEncoder::encodingType, identity()));
.collect(Collectors.toMap(MessageBodyEncoder::encodingType, identity()));
}
@Override
@@ -181,7 +181,9 @@ public class ModifyResponseBodyGatewayFilterFactory
public String toString() {
Object obj = (this.gatewayFilterFactory != null) ? this.gatewayFilterFactory : this;
return filterToStringCreator(obj).append("New content type", config.getNewContentType())
.append("In class", config.getInClass()).append("Out class", config.getOutClass()).toString();
.append("In class", config.getInClass())
.append("Out class", config.getOutClass())
.toString();
}
public void setFactory(GatewayFilterFactory<Config> gatewayFilterFactory) {
@@ -221,8 +223,8 @@ public class ModifyResponseBodyGatewayFilterFactory
// TODO: flux or mono
Mono modifiedBody = extractBody(exchange, clientResponse, inClass)
.flatMap(originalBody -> config.getRewriteFunction().apply(exchange, originalBody))
.switchIfEmpty(Mono.defer(() -> (Mono) config.getRewriteFunction().apply(exchange, null)));
.flatMap(originalBody -> config.getRewriteFunction().apply(exchange, originalBody))
.switchIfEmpty(Mono.defer(() -> (Mono) config.getRewriteFunction().apply(exchange, null)));
BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, outClass);
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange,
@@ -266,11 +268,12 @@ public class ModifyResponseBodyGatewayFilterFactory
for (String encoding : encodingHeaders) {
MessageBodyDecoder decoder = messageBodyDecoders.get(encoding);
if (decoder != null) {
return clientResponse.bodyToMono(byte[].class).publishOn(Schedulers.parallel()).map(decoder::decode)
.map(bytes -> exchange.getResponse().bufferFactory().wrap(bytes))
.map(buffer -> prepareClientResponse(Mono.just(buffer),
exchange.getResponse().getHeaders()))
.flatMap(response -> response.bodyToMono(inClass));
return clientResponse.bodyToMono(byte[].class)
.publishOn(Schedulers.parallel())
.map(decoder::decode)
.map(bytes -> exchange.getResponse().bufferFactory().wrap(bytes))
.map(buffer -> prepareClientResponse(Mono.just(buffer), exchange.getResponse().getHeaders()))
.flatMap(response -> response.bodyToMono(inClass));
}
}

View File

@@ -51,9 +51,9 @@ public class DefaultGatewayObservationConvention implements GatewayObservationCo
}
Route route = context.getServerWebExchange().getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
keyValues = keyValues
.and(ROUTE_URI.withValue(route.getUri().toString()),
METHOD.withValue(context.getRequest().getMethod().name()))
.and(ROUTE_ID.withValue(route.getId()));
.and(ROUTE_URI.withValue(route.getUri().toString()),
METHOD.withValue(context.getRequest().getMethod().name()))
.and(ROUTE_ID.withValue(route.getId()));
ServerHttpResponse response = context.getResponse();
if (response != null && response.getStatusCode() != null) {
keyValues = keyValues.and(STATUS.withValue(String.valueOf(response.getStatusCode().value())));

View File

@@ -53,9 +53,10 @@ public class GatewayPropagatingSenderTracingObservationHandler
@Override
public void onStart(GatewayContext context) {
this.propagator.fields().stream()
.filter(field -> !remoteFieldsLowerCase.contains(field.toLowerCase(Locale.ROOT)))
.forEach(s -> Objects.requireNonNull(context.getCarrier()).remove(s));
this.propagator.fields()
.stream()
.filter(field -> !remoteFieldsLowerCase.contains(field.toLowerCase(Locale.ROOT)))
.forEach(s -> Objects.requireNonNull(context.getCarrier()).remove(s));
super.onStart(context);
}

View File

@@ -58,8 +58,10 @@ public abstract class AbstractRateLimiter<C> extends AbstractStatefulConfigurabl
C routeConfig = newConfig();
if (this.configurationService != null) {
this.configurationService.with(routeConfig).name(this.configurationPropertyName).normalizedProperties(args)
.bind();
this.configurationService.with(routeConfig)
.name(this.configurationPropertyName)
.normalizedProperties(args)
.bind();
}
getConfig().put(routeId, routeConfig);
}
@@ -71,7 +73,9 @@ public abstract class AbstractRateLimiter<C> extends AbstractStatefulConfigurabl
@Override
public String toString() {
return new ToStringCreator(this).append("configurationPropertyName", configurationPropertyName)
.append("config", getConfig()).append("configClass", getConfigClass()).toString();
.append("config", getConfig())
.append("configClass", getConfigClass())
.toString();
}
}

View File

@@ -351,7 +351,9 @@ public class RedisRateLimiter extends AbstractRateLimiter<RedisRateLimiter.Confi
@Override
public String toString() {
return new ToStringCreator(this).append("replenishRate", replenishRate)
.append("burstCapacity", burstCapacity).append("requestedTokens", requestedTokens).toString();
.append("burstCapacity", burstCapacity)
.append("requestedTokens", requestedTokens)
.toString();
}

View File

@@ -87,21 +87,22 @@ public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
return Mono.deferContextual(contextView -> {
exchange.getAttributes().put(GATEWAY_REACTOR_CONTEXT_ATTR, contextView);
return lookupRoute(exchange)
// .log("route-predicate-handler-mapping", Level.FINER) //name this
.map((Function<Route, ?>) r -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isDebugEnabled()) {
logger.debug("Mapping [" + getExchangeDesc(exchange) + "] to " + r);
}
// .log("route-predicate-handler-mapping", Level.FINER) //name this
.map((Function<Route, ?>) r -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isDebugEnabled()) {
logger.debug("Mapping [" + getExchangeDesc(exchange) + "] to " + r);
}
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
return webHandler;
}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isTraceEnabled()) {
logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) + "]");
}
})));
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
return webHandler;
})
.switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isTraceEnabled()) {
logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) + "]");
}
})));
});
}
@@ -126,29 +127,29 @@ public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
return this.routeLocator.getRoutes()
// individually filter routes so that filterWhen error delaying is not a
// problem
.concatMap(route -> Mono.just(route).filterWhen(r -> {
// add the current route we are testing
exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
return r.getPredicate().apply(exchange);
})
// instead of immediately stopping main flux due to error, log and
// swallow it
.doOnError(e -> logger.error("Error applying predicate for route: " + route.getId(), e))
.onErrorResume(e -> Mono.empty()))
// .defaultIfEmpty() put a static Route not found
// or .switchIfEmpty()
// .switchIfEmpty(Mono.<Route>empty().log("noroute"))
.next()
// TODO: error handling
.map(route -> {
if (logger.isDebugEnabled()) {
logger.debug("Route matched: " + route.getId());
}
validateRoute(route, exchange);
return route;
});
// individually filter routes so that filterWhen error delaying is not a
// problem
.concatMap(route -> Mono.just(route).filterWhen(r -> {
// add the current route we are testing
exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
return r.getPredicate().apply(exchange);
})
// instead of immediately stopping main flux due to error, log and
// swallow it
.doOnError(e -> logger.error("Error applying predicate for route: " + route.getId(), e))
.onErrorResume(e -> Mono.empty()))
// .defaultIfEmpty() put a static Route not found
// or .switchIfEmpty()
// .switchIfEmpty(Mono.<Route>empty().log("noroute"))
.next()
// TODO: error handling
.map(route -> {
if (logger.isDebugEnabled()) {
logger.debug("Route matched: " + route.getId());
}
validateRoute(route, exchange);
return route;
});
/*
* TODO: trace logging if (logger.isTraceEnabled()) {

View File

@@ -54,7 +54,7 @@ public class CloudFoundryRouteServiceRoutePredicateFactory extends AbstractRoute
@Override
public Predicate<ServerWebExchange> apply(Object unused) {
return headerPredicate(X_CF_FORWARDED_URL).and(headerPredicate(X_CF_PROXY_SIGNATURE))
.and(headerPredicate(X_CF_PROXY_METADATA));
.and(headerPredicate(X_CF_PROXY_METADATA));
}
private Predicate<ServerWebExchange> headerPredicate(String header) {

View File

@@ -59,8 +59,9 @@ public class HeaderRoutePredicateFactory extends AbstractRoutePredicateFactory<H
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange exchange) {
List<String> values = exchange.getRequest().getHeaders().getOrDefault(config.header,
Collections.emptyList());
List<String> values = exchange.getRequest()
.getHeaders()
.getOrDefault(config.header, Collections.emptyList());
if (values.isEmpty()) {
return false;
}

View File

@@ -90,9 +90,9 @@ public class PathRoutePredicateFactory extends AbstractRoutePredicateFactory<Pat
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange exchange) {
PathContainer path = (PathContainer) exchange.getAttributes().computeIfAbsent(
GATEWAY_PREDICATE_PATH_CONTAINER_ATTR,
s -> parsePath(exchange.getRequest().getURI().getRawPath()));
PathContainer path = (PathContainer) exchange.getAttributes()
.computeIfAbsent(GATEWAY_PREDICATE_PATH_CONTAINER_ATTR,
s -> parsePath(exchange.getRequest().getURI().getRawPath()));
PathPattern match = null;
for (int i = 0; i < pathPatterns.size(); i++) {
@@ -179,7 +179,8 @@ public class PathRoutePredicateFactory extends AbstractRoutePredicateFactory<Pat
@Override
public String toString() {
return new ToStringCreator(this).append("patterns", patterns)
.append(MATCH_TRAILING_SLASH, matchTrailingSlash).toString();
.append(MATCH_TRAILING_SLASH, matchTrailingSlash)
.toString();
}
}

View File

@@ -90,10 +90,11 @@ public class ReadBodyRoutePredicateFactory extends AbstractRoutePredicateFactory
else {
return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange,
(serverHttpRequest) -> ServerRequest
.create(exchange.mutate().request(serverHttpRequest).build(), messageReaders)
.bodyToMono(inClass).doOnNext(objectValue -> exchange.getAttributes()
.put(CACHE_REQUEST_BODY_OBJECT_KEY, objectValue))
.map(objectValue -> config.getPredicate().test(objectValue)));
.create(exchange.mutate().request(serverHttpRequest).build(), messageReaders)
.bodyToMono(inClass)
.doOnNext(objectValue -> exchange.getAttributes()
.put(CACHE_REQUEST_BODY_OBJECT_KEY, objectValue))
.map(objectValue -> config.getPredicate().test(objectValue)));
}
}

View File

@@ -92,7 +92,7 @@ public class XForwardedRemoteAddrRoutePredicateFactory
RemoteAddrRoutePredicateFactory.Config wrappedConfig = new RemoteAddrRoutePredicateFactory.Config();
wrappedConfig.setSources(config.getSources());
wrappedConfig
.setRemoteAddressResolver(XForwardedRemoteAddressResolver.maxTrustedIndex(config.getMaxTrustedIndex()));
.setRemoteAddressResolver(XForwardedRemoteAddressResolver.maxTrustedIndex(config.getMaxTrustedIndex()));
RemoteAddrRoutePredicateFactory remoteAddrRoutePredicateFactory = new RemoteAddrRoutePredicateFactory();
Predicate<ServerWebExchange> wrappedPredicate = remoteAddrRoutePredicateFactory.apply(wrappedConfig);

View File

@@ -86,11 +86,11 @@ public class CachingRouteLocator
try {
if (this.cache.containsKey(CACHE_KEY) && event.isScoped()) {
final Mono<List<Route>> scopedRoutes = fetch(event.getMetadata()).collect(Collectors.toList())
.onErrorResume(s -> Mono.just(List.of()));
.onErrorResume(s -> Mono.just(List.of()));
scopedRoutes.subscribe(scopedRoutesList -> {
updateCache(Flux.concat(Flux.fromIterable(scopedRoutesList), getNonScopedRoutes(event))
.sort(AnnotationAwareOrderComparator.INSTANCE));
.sort(AnnotationAwareOrderComparator.INSTANCE));
}, this::handleRefreshError);
}
else {
@@ -104,8 +104,9 @@ public class CachingRouteLocator
}
private synchronized void updateCache(Flux<Route> routes) {
routes.materialize().collect(Collectors.toList()).subscribe(this::publishRefreshEvent,
this::handleRefreshError);
routes.materialize()
.collect(Collectors.toList())
.subscribe(this::publishRefreshEvent, this::handleRefreshError);
}
private void publishRefreshEvent(List<Signal<Route>> signals) {
@@ -115,7 +116,7 @@ public class CachingRouteLocator
private Flux<Route> getNonScopedRoutes(RefreshRoutesEvent scopedEvent) {
return this.getRoutes()
.filter(route -> !RouteLocator.matchMetadata(route.getMetadata(), scopedEvent.getMetadata()));
.filter(route -> !RouteLocator.matchMetadata(route.getMetadata(), scopedEvent.getMetadata()));
}
private void handleRefreshError(Throwable throwable) {

View File

@@ -50,18 +50,18 @@ public class CompositeRouteDefinitionLocator implements RouteDefinitionLocator {
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
return this.delegates.flatMapSequential(RouteDefinitionLocator::getRouteDefinitions)
.flatMap(routeDefinition -> {
if (routeDefinition.getId() == null) {
return randomId().map(id -> {
routeDefinition.setId(id);
if (log.isDebugEnabled()) {
log.debug("Id set on route definition: " + routeDefinition);
}
return routeDefinition;
});
}
return Mono.just(routeDefinition);
});
.flatMap(routeDefinition -> {
if (routeDefinition.getId() == null) {
return randomId().map(id -> {
routeDefinition.setId(id);
if (log.isDebugEnabled()) {
log.debug("Id set on route definition: " + routeDefinition);
}
return routeDefinition;
});
}
return Mono.just(routeDefinition);
});
}
protected Mono<String> randomId() {

View File

@@ -53,24 +53,25 @@ public class RedisRouteDefinitionRepository implements RouteDefinitionRepository
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
return reactiveRedisTemplate.scan(ScanOptions.scanOptions().match(createKey("*")).build())
.flatMap(key -> reactiveRedisTemplate.opsForValue().get(key))
.onErrorContinue((throwable, routeDefinition) -> {
if (log.isErrorEnabled()) {
log.error("get routes from redis error cause : {}", throwable.toString(), throwable);
}
});
.flatMap(key -> reactiveRedisTemplate.opsForValue().get(key))
.onErrorContinue((throwable, routeDefinition) -> {
if (log.isErrorEnabled()) {
log.error("get routes from redis error cause : {}", throwable.toString(), throwable);
}
});
}
@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
return route.flatMap(routeDefinition -> routeDefinitionReactiveValueOperations
.set(createKey(routeDefinition.getId()), routeDefinition).flatMap(success -> {
if (success) {
return Mono.empty();
}
return Mono.defer(() -> Mono.error(new RuntimeException(
String.format("Could not add route to redis repository: %s", routeDefinition))));
}));
.set(createKey(routeDefinition.getId()), routeDefinition)
.flatMap(success -> {
if (success) {
return Mono.empty();
}
return Mono.defer(() -> Mono.error(new RuntimeException(
String.format("Could not add route to redis repository: %s", routeDefinition))));
}));
}
@Override

View File

@@ -98,7 +98,7 @@ public class RouteDefinitionRouteLocator implements RouteLocator {
@Override
public Flux<Route> getRoutesByMetadata(Map<String, Object> metadata) {
return getRoutes(this.routeDefinitionLocator.getRouteDefinitions()
.filter(routeDef -> RouteLocator.matchMetadata(routeDef.getMetadata(), metadata)));
.filter(routeDef -> RouteLocator.matchMetadata(routeDef.getMetadata(), metadata)));
}
@Override

View File

@@ -43,9 +43,10 @@ public interface RouteLocator {
return true;
}
else {
return toCheck != null
&& expectedMetadata.entrySet().stream().allMatch(keyValue -> toCheck.containsKey(keyValue.getKey())
&& toCheck.get(keyValue.getKey()).equals(keyValue.getValue()));
return toCheck != null && expectedMetadata.entrySet()
.stream()
.allMatch(keyValue -> toCheck.containsKey(keyValue.getKey())
&& toCheck.get(keyValue.getKey()).equals(keyValue.getValue()));
}
}

View File

@@ -184,7 +184,7 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec addRequestHeader(String headerName, String headerValue) {
return filter(getBean(AddRequestHeaderGatewayFilterFactory.class)
.apply(c -> c.setName(headerName).setValue(headerValue)));
.apply(c -> c.setName(headerName).setValue(headerValue)));
}
/**
@@ -195,8 +195,10 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec addRequestHeadersIfNotPresent(String... headers) {
return filter(getBean(AddRequestHeadersIfNotPresentGatewayFilterFactory.class).apply(c -> {
KeyValue[] values = Arrays.stream(headers).map(header -> header.split(":"))
.map(parts -> new KeyValue(parts[0], parts[1])).toArray(size -> new KeyValue[size]);
KeyValue[] values = Arrays.stream(headers)
.map(header -> header.split(":"))
.map(parts -> new KeyValue(parts[0], parts[1]))
.toArray(size -> new KeyValue[size]);
c.setKeyValues(values);
}));
}
@@ -220,7 +222,7 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec addResponseHeader(String headerName, String headerValue) {
return filter(getBean(AddResponseHeaderGatewayFilterFactory.class)
.apply(c -> c.setName(headerName).setValue(headerValue)));
.apply(c -> c.setName(headerName).setValue(headerValue)));
}
/**
@@ -236,7 +238,7 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec localResponseCache(Duration timeToLive, DataSize size) {
return filter(getBean(LocalResponseCacheGatewayFilterFactory.class)
.apply(c -> c.setTimeToLive(timeToLive).setSize(size)));
.apply(c -> c.setTimeToLive(timeToLive).setSize(size)));
}
/**
@@ -248,7 +250,7 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec dedupeResponseHeader(String headerName, String strategy) {
return filter(getBean(DedupeResponseHeaderGatewayFilterFactory.class)
.apply(c -> c.setStrategy(Strategy.valueOf(strategy)).setName(headerName)));
.apply(c -> c.setStrategy(Strategy.valueOf(strategy)).setName(headerName)));
}
public GatewayFilterSpec circuitBreaker(Consumer<SpringCloudCircuitBreakerFilterFactory.Config> configConsumer) {
@@ -272,7 +274,9 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec jsonToGRPC(String protoDescriptor, String protoFile, String service, String method) {
return filter(getBean(JsonToGrpcGatewayFilterFactory.class).apply(c -> c.setMethod(method)
.setProtoDescriptor(protoDescriptor).setProtoFile(protoFile).setService(service)));
.setProtoDescriptor(protoDescriptor)
.setProtoFile(protoFile)
.setService(service)));
}
/**
@@ -283,7 +287,7 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec mapRequestHeader(String fromHeader, String toHeader) {
return filter(getBean(MapRequestHeaderGatewayFilterFactory.class)
.apply(c -> c.setFromHeader(fromHeader).setToHeader(toHeader)));
.apply(c -> c.setFromHeader(fromHeader).setToHeader(toHeader)));
}
/**
@@ -299,7 +303,7 @@ public class GatewayFilterSpec extends UriSpec {
public <T, R> GatewayFilterSpec modifyRequestBody(Class<T> inClass, Class<R> outClass,
RewriteFunction<T, R> rewriteFunction) {
return filter(getBean(ModifyRequestBodyGatewayFilterFactory.class)
.apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction)));
.apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction)));
}
/**
@@ -316,7 +320,7 @@ public class GatewayFilterSpec extends UriSpec {
public <T, R> GatewayFilterSpec modifyRequestBody(ParameterizedTypeReference<T> inClass,
ParameterizedTypeReference<R> outClass, RewriteFunction<T, R> rewriteFunction) {
return filter(getBean(ModifyRequestBodyGatewayFilterFactory.class)
.apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction)));
.apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction)));
}
/**
@@ -332,7 +336,7 @@ public class GatewayFilterSpec extends UriSpec {
public <T, R> GatewayFilterSpec modifyRequestBody(Class<T> inClass, Class<R> outClass, String newContentType,
RewriteFunction<T, R> rewriteFunction) {
return filter(getBean(ModifyRequestBodyGatewayFilterFactory.class)
.apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction).setContentType(newContentType)));
.apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction).setContentType(newContentType)));
}
/**
@@ -350,7 +354,7 @@ public class GatewayFilterSpec extends UriSpec {
public <T, R> GatewayFilterSpec modifyRequestBody(ParameterizedTypeReference<T> inClass,
ParameterizedTypeReference<R> outClass, String newContentType, RewriteFunction<T, R> rewriteFunction) {
return filter(getBean(ModifyRequestBodyGatewayFilterFactory.class)
.apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction).setContentType(newContentType)));
.apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction).setContentType(newContentType)));
}
/**
@@ -400,7 +404,7 @@ public class GatewayFilterSpec extends UriSpec {
public <T, R> GatewayFilterSpec modifyResponseBody(Class<T> inClass, Class<R> outClass,
RewriteFunction<T, R> rewriteFunction) {
return filter(getBean(ModifyResponseBodyGatewayFilterFactory.class)
.apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction)));
.apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction)));
}
/**
@@ -418,8 +422,8 @@ public class GatewayFilterSpec extends UriSpec {
// TODO: setup custom spec
public <T, R> GatewayFilterSpec modifyResponseBody(Class<T> inClass, Class<R> outClass, String newContentType,
RewriteFunction<T, R> rewriteFunction) {
return filter(getBean(ModifyResponseBodyGatewayFilterFactory.class).apply(
c -> c.setRewriteFunction(inClass, outClass, rewriteFunction).setNewContentType(newContentType)));
return filter(getBean(ModifyResponseBodyGatewayFilterFactory.class)
.apply(c -> c.setRewriteFunction(inClass, outClass, rewriteFunction).setNewContentType(newContentType)));
}
/**
@@ -603,7 +607,7 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec removeJsonAttributes(boolean deleteRecursively, String... attributes) {
return filter(getBean(RemoveJsonAttributesResponseBodyGatewayFilterFactory.class)
.apply(c -> c.setFieldList(Arrays.asList(attributes)).setDeleteRecursively(deleteRecursively)));
.apply(c -> c.setFieldList(Arrays.asList(attributes)).setDeleteRecursively(deleteRecursively)));
}
@@ -665,7 +669,7 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec rewritePath(String regex, String replacement) {
return filter(getBean(RewritePathGatewayFilterFactory.class)
.apply(c -> c.setRegexp(regex).setReplacement(replacement)));
.apply(c -> c.setRegexp(regex).setReplacement(replacement)));
}
/**
@@ -741,7 +745,7 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec setRequestHeader(String headerName, String headerValue) {
return filter(getBean(SetRequestHeaderGatewayFilterFactory.class)
.apply(c -> c.setName(headerName).setValue(headerValue)));
.apply(c -> c.setName(headerName).setValue(headerValue)));
}
/**
@@ -753,7 +757,7 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec setResponseHeader(String headerName, String headerValue) {
return filter(getBean(SetResponseHeaderGatewayFilterFactory.class)
.apply(c -> c.setName(headerName).setValue(headerValue)));
.apply(c -> c.setName(headerName).setValue(headerValue)));
}
/**
@@ -766,7 +770,7 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec rewriteResponseHeader(String headerName, String regex, String replacement) {
return filter(getBean(RewriteResponseHeaderGatewayFilterFactory.class)
.apply(c -> c.setReplacement(replacement).setRegexp(regex).setName(headerName)));
.apply(c -> c.setReplacement(replacement).setRegexp(regex).setName(headerName)));
}
/**
@@ -781,9 +785,11 @@ public class GatewayFilterSpec extends UriSpec {
*/
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)));
return filter(getBean(RewriteLocationResponseHeaderGatewayFilterFactory.class)
.apply(c -> c.setStripVersion(StripVersion.valueOf(stripVersionMode))
.setLocationHeaderName(locationHeaderName)
.setHostValue(hostValue)
.setProtocols(protocolsRegex)));
}
/**
@@ -794,7 +800,7 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec rewriteRequestParameter(String name, String replacement) {
return filter(getBean(RewriteRequestParameterGatewayFilterFactory.class)
.apply(c -> c.setReplacement(replacement).setName(name)));
.apply(c -> c.setReplacement(replacement).setName(name)));
}
/**

View File

@@ -97,7 +97,7 @@ public class PredicateSpec extends UriSpec {
*/
public BooleanSpec between(ZonedDateTime datetime1, ZonedDateTime datetime2) {
return asyncPredicate(getBean(BetweenRoutePredicateFactory.class)
.applyAsync(c -> c.setDatetime1(datetime1).setDatetime2(datetime2)));
.applyAsync(c -> c.setDatetime1(datetime1).setDatetime2(datetime2)));
}
/**
@@ -188,7 +188,7 @@ public class PredicateSpec extends UriSpec {
*/
public BooleanSpec path(boolean matchTrailingSlash, String... patterns) {
return asyncPredicate(getBean(PathRoutePredicateFactory.class)
.applyAsync(c -> c.setPatterns(Arrays.asList(patterns)).setMatchTrailingSlash(matchTrailingSlash)));
.applyAsync(c -> c.setPatterns(Arrays.asList(patterns)).setMatchTrailingSlash(matchTrailingSlash)));
}
/**
@@ -287,7 +287,7 @@ public class PredicateSpec extends UriSpec {
*/
public BooleanSpec weight(String group, int weight) {
return asyncPredicate(getBean(WeightRoutePredicateFactory.class)
.applyAsync(c -> c.setGroup(group).setRouteId(routeBuilder.getId()).setWeight(weight)));
.applyAsync(c -> c.setGroup(group).setRouteId(routeBuilder.getId()).setWeight(weight)));
}
public BooleanSpec cloudFoundryRouteService() {

View File

@@ -95,7 +95,7 @@ public class ConfigurationService implements ApplicationEventPublisherAware {
}
List<ConfigurationPropertySource> propertySources = Collections
.singletonList(new MapConfigurationPropertySource(properties));
.singletonList(new MapConfigurationPropertySource(properties));
return new Binder(propertySources, null, conversionService).bindOrCreate(configurationPropertyName, bindable,
handler);
@@ -137,8 +137,8 @@ public class ConfigurationService implements ApplicationEventPublisherAware {
@Override
protected Map<String, Object> normalizeProperties() {
if (this.service.beanFactory != null) {
return this.configurable.shortcutType().normalize(this.properties, this.configurable,
this.service.parser, this.service.beanFactory);
return this.configurable.shortcutType()
.normalize(this.properties, this.configurable, this.service.parser, this.service.beanFactory);
}
return super.normalizeProperties();
}

View File

@@ -299,7 +299,7 @@ public final class ServerWebExchangeUtils {
public static void putUriTemplateVariables(ServerWebExchange exchange, Map<String, String> uriVariables) {
if (exchange.getAttributes().containsKey(URI_TEMPLATE_VARIABLES_ATTRIBUTE)) {
Map<String, Object> existingVariables = (Map<String, Object>) exchange.getAttributes()
.get(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
.get(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
HashMap<String, Object> newVariables = new HashMap<>();
newVariables.putAll(existingVariables);
newVariables.putAll(uriVariables);
@@ -372,9 +372,11 @@ public final class ServerWebExchangeUtils {
ServerHttpResponse response = exchange.getResponse();
DataBufferFactory factory = response.bufferFactory();
// Join all the DataBuffers so we have a single DataBuffer for the body
return DataBufferUtils.join(exchange.getRequest().getBody()).defaultIfEmpty(factory.wrap(EMPTY_BYTES))
.map(dataBuffer -> decorate(exchange, dataBuffer, cacheDecoratedRequest))
.switchIfEmpty(Mono.just(exchange.getRequest())).flatMap(function);
return DataBufferUtils.join(exchange.getRequest().getBody())
.defaultIfEmpty(factory.wrap(EMPTY_BYTES))
.map(dataBuffer -> decorate(exchange, dataBuffer, cacheDecoratedRequest))
.switchIfEmpty(Mono.just(exchange.getRequest()))
.flatMap(function);
}
private static ServerHttpRequest decorate(ServerWebExchange exchange, DataBuffer dataBuffer,

View File

@@ -128,8 +128,11 @@ public interface ShortcutConfigurable {
Assert.isTrue(fieldOrder != null && fieldOrder.size() == 1,
"Shortcut Configuration Type GATHER_LIST must have shortcutFieldOrder of size 1");
String fieldName = fieldOrder.get(0);
map.put(fieldName, args.values().stream().map(value -> getValue(parser, beanFactory, value))
.collect(Collectors.toList()));
map.put(fieldName,
args.values()
.stream()
.map(value -> getValue(parser, beanFactory, value))
.collect(Collectors.toList()));
return map;
}
},
@@ -158,8 +161,10 @@ public interface ShortcutConfigurable {
}
}
String fieldName = fieldOrder.get(0);
map.put(fieldName, values.stream().map(value -> getValue(parser, beanFactory, value))
.collect(Collectors.toList()));
map.put(fieldName,
values.stream()
.map(value -> getValue(parser, beanFactory, value))
.collect(Collectors.toList()));
return map;
}
};
@@ -182,7 +187,8 @@ public interface ShortcutConfigurable {
Boolean.class, true);
if (restrictive) {
delegate = SimpleEvaluationContext.forPropertyAccessors(new RestrictivePropertyAccessor())
.withMethodResolvers((context, targetObject, name, argumentTypes) -> null).build();
.withMethodResolvers((context, targetObject, name, argumentTypes) -> null)
.build();
}
else {
delegate = SimpleEvaluationContext.forReadOnlyDataBinding().build();

View File

@@ -80,8 +80,10 @@ public class WeightConfig {
@Override
public String toString() {
return new ToStringCreator(this).append("group", group).append("routeId", routeId).append("weight", weight)
.toString();
return new ToStringCreator(this).append("group", group)
.append("routeId", routeId)
.append("weight", weight)
.toString();
}
}

View File

@@ -32,8 +32,10 @@ public class PropertiesTagsProvider implements GatewayTagsProvider {
private final Tags propertiesTags;
public PropertiesTagsProvider(Map<String, String> tagsMap) {
this.propertiesTags = Tags.of(tagsMap.entrySet().stream().map(entry -> Tag.of(entry.getKey(), entry.getValue()))
.collect(Collectors.toList()));
this.propertiesTags = Tags.of(tagsMap.entrySet()
.stream()
.map(entry -> Tag.of(entry.getKey(), entry.getValue()))
.collect(Collectors.toList()));
}
@Override

View File

@@ -70,75 +70,109 @@ public class GatewayControllerEndpointTests {
@Test
public void testEndpoints() {
testClient.get().uri("http://localhost:" + port + "/actuator/gateway").exchange().expectStatus().isOk()
.expectBodyList(Map.class).consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).isNotEmpty();
assertThat(responseBody).contains(Map.of("href", "/actuator/gateway/", "methods", List.of("GET")),
Map.of("href", "/actuator/gateway/globalfilters", "methods", List.of("GET")),
Map.of("href", "/actuator/gateway/refresh", "methods", List.of("POST")),
Map.of("href", "/actuator/gateway/routedefinitions", "methods", List.of("GET")),
Map.of("href", "/actuator/gateway/routefilters", "methods", List.of("GET")),
Map.of("href", "/actuator/gateway/routepredicates", "methods", List.of("GET")),
Map.of("href", "/actuator/gateway/routes", "methods", List.of("POST", "GET")),
Map.of("href", "/actuator/gateway/routes/test-service", "methods",
List.of("POST", "DELETE", "GET")),
Map.of("href", "/actuator/gateway/routes/route_with_metadata", "methods",
List.of("POST", "DELETE", "GET")));
});
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway")
.exchange()
.expectStatus()
.isOk()
.expectBodyList(Map.class)
.consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).isNotEmpty();
assertThat(responseBody).contains(Map.of("href", "/actuator/gateway/", "methods", List.of("GET")),
Map.of("href", "/actuator/gateway/globalfilters", "methods", List.of("GET")),
Map.of("href", "/actuator/gateway/refresh", "methods", List.of("POST")),
Map.of("href", "/actuator/gateway/routedefinitions", "methods", List.of("GET")),
Map.of("href", "/actuator/gateway/routefilters", "methods", List.of("GET")),
Map.of("href", "/actuator/gateway/routepredicates", "methods", List.of("GET")),
Map.of("href", "/actuator/gateway/routes", "methods", List.of("POST", "GET")),
Map.of("href", "/actuator/gateway/routes/test-service", "methods",
List.of("POST", "DELETE", "GET")),
Map.of("href", "/actuator/gateway/routes/route_with_metadata", "methods",
List.of("POST", "DELETE", "GET")));
});
}
@Test
public void testRefresh() {
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/refresh").exchange().expectStatus()
.isOk();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/refresh")
.exchange()
.expectStatus()
.isOk();
}
@Test
public void testRoutes() {
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routes").exchange().expectStatus().isOk()
.expectBodyList(Map.class).consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).isNotEmpty();
});
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routes")
.exchange()
.expectStatus()
.isOk()
.expectBodyList(Map.class)
.consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).isNotEmpty();
});
}
@Test
public void testGetSpecificRoute() {
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routes/test-service").exchange()
.expectStatus().isOk().expectBodyList(Map.class).consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).isNotNull();
assertThat(responseBody.size()).isEqualTo(1);
assertThat(responseBody).isNotEmpty();
});
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routes/test-service")
.exchange()
.expectStatus()
.isOk()
.expectBodyList(Map.class)
.consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).isNotNull();
assertThat(responseBody.size()).isEqualTo(1);
assertThat(responseBody).isNotEmpty();
});
}
@Test
public void testRouteReturnsMetadata() {
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routes/route_with_metadata").exchange()
.expectStatus().isOk().expectBody().jsonPath("$.metadata")
.value(map -> assertThat((Map<String, Object>) map).hasSize(3)
.containsEntry("optionName", "OptionValue").containsEntry("iAmNumber", 1)
.containsEntry("compositeObject", Maps.newHashMap("name", "value")));
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routes/route_with_metadata")
.exchange()
.expectStatus()
.isOk()
.expectBody()
.jsonPath("$.metadata")
.value(map -> assertThat((Map<String, Object>) map).hasSize(3)
.containsEntry("optionName", "OptionValue")
.containsEntry("iAmNumber", 1)
.containsEntry("compositeObject", Maps.newHashMap("name", "value")));
}
@Test
public void testRouteFilters() {
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routefilters").exchange().expectStatus()
.isOk().expectBody(Map.class).consumeWith(result -> {
Map<?, ?> responseBody = result.getResponseBody();
assertThat(responseBody).isNotEmpty();
});
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routefilters")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(result -> {
Map<?, ?> responseBody = result.getResponseBody();
assertThat(responseBody).isNotEmpty();
});
}
@Test
public void testRoutePredicates() {
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routepredicates").exchange().expectStatus()
.isOk().expectBody(Map.class).consumeWith(result -> {
Map<?, ?> responseBody = result.getResponseBody();
assertThat(responseBody).isNotEmpty();
});
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routepredicates")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(result -> {
Map<?, ?> responseBody = result.getResponseBody();
assertThat(responseBody).isNotEmpty();
});
}
@Test
@@ -150,15 +184,24 @@ public class GatewayControllerEndpointTests {
testRouteDefinition.setPredicates(Arrays.asList(methodRoutePredicateDefinition));
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/test-route-to-be-delete")
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/test-route-to-be-delete")
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isCreated();
testClient.delete().uri("http://localhost:" + port + "/actuator/gateway/routes/test-route-to-be-delete")
.exchange().expectStatus().isOk().expectBody(ResponseEntity.class).consumeWith(result -> {
HttpStatusCode httpStatus = result.getStatus();
Assertions.assertEquals(HttpStatus.OK, httpStatus);
});
testClient.delete()
.uri("http://localhost:" + port + "/actuator/gateway/routes/test-route-to-be-delete")
.exchange()
.expectStatus()
.isOk()
.expectBody(ResponseEntity.class)
.consumeWith(result -> {
HttpStatusCode httpStatus = result.getStatus();
Assertions.assertEquals(HttpStatus.OK, httpStatus);
});
}
@Test
@@ -169,8 +212,8 @@ public class GatewayControllerEndpointTests {
FilterDefinition prefixPathFilterDefinition = new FilterDefinition("PrefixPath=/test-path");
FilterDefinition redirectToFilterDefinition = new FilterDefinition("RemoveResponseHeader=Sensitive-Header");
FilterDefinition testFilterDefinition = new FilterDefinition("TestFilter");
testRouteDefinition.setFilters(
Arrays.asList(prefixPathFilterDefinition, redirectToFilterDefinition, testFilterDefinition));
testRouteDefinition
.setFilters(Arrays.asList(prefixPathFilterDefinition, redirectToFilterDefinition, testFilterDefinition));
PredicateDefinition hostRoutePredicateDefinition = new PredicateDefinition("Host=myhost.org");
PredicateDefinition methodRoutePredicateDefinition = new PredicateDefinition("Method=GET");
@@ -178,9 +221,13 @@ public class GatewayControllerEndpointTests {
testRouteDefinition.setPredicates(
Arrays.asList(hostRoutePredicateDefinition, methodRoutePredicateDefinition, testPredicateDefinition));
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/test-route")
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/test-route")
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isCreated();
}
@Test
@@ -191,27 +238,43 @@ public class GatewayControllerEndpointTests {
testRouteDefinition.setMetadata(Map.of("groupBy", group1));
String routeId1 = "route-1_" + UUID.randomUUID();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isCreated();
RouteDefinition testRouteDefinition2 = new RouteDefinition();
testRouteDefinition2.setUri(URI.create("http://example.org"));
String group2 = "group-2_" + UUID.randomUUID();
testRouteDefinition2.setMetadata(Map.of("groupBy", group2));
String routeId2 = "route-2_" + UUID.randomUUID();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId2)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition2)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId2)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition2))
.exchange()
.expectStatus()
.isCreated();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange().expectStatus().isOk();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange()
.expectStatus()
.isOk();
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routes").exchange().expectStatus().isOk()
.expectBodyList(Map.class).consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).extracting("route_id").contains(routeId1).doesNotContain(routeId2);
});
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routes")
.exchange()
.expectStatus()
.isOk()
.expectBodyList(Map.class)
.consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).extracting("route_id").contains(routeId1).doesNotContain(routeId2);
});
}
@Test
@@ -223,9 +286,13 @@ public class GatewayControllerEndpointTests {
testRouteDefinition.setMetadata(Map.of("groupBy", group1));
String routeId1 = "route-1_" + UUID.randomUUID();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isCreated();
RouteDefinition testRouteDefinition2 = new RouteDefinition();
testRouteDefinition2.setUri(URI.create("http://example.org"));
@@ -233,37 +300,68 @@ public class GatewayControllerEndpointTests {
String group2 = "group-2_" + UUID.randomUUID();
testRouteDefinition2.setMetadata(Map.of("groupBy", group2));
String routeId2 = "route-2_" + UUID.randomUUID();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId2)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition2)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId2)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition2))
.exchange()
.expectStatus()
.isCreated();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange().expectStatus().isOk();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group2)
.exchange().expectStatus().isOk();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange()
.expectStatus()
.isOk();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group2)
.exchange()
.expectStatus()
.isOk();
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routes").exchange().expectStatus().isOk()
.expectBodyList(Map.class).consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routes")
.exchange()
.expectStatus()
.isOk()
.expectBodyList(Map.class)
.consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
List ids = responseBody.stream().map(route -> route.get("route_id"))
.filter(id -> id.equals(routeId1) || id.equals(routeId2)).collect(Collectors.toList());
assertThat(ids).containsExactly(routeId2, routeId1);
});
List ids = responseBody.stream()
.map(route -> route.get("route_id"))
.filter(id -> id.equals(routeId1) || id.equals(routeId2))
.collect(Collectors.toList());
assertThat(ids).containsExactly(routeId2, routeId1);
});
testRouteDefinition2.setOrder(testRouteDefinition.getOrder() + 1);
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId2)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition2)).exchange()
.expectStatus().isCreated();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group2)
.exchange().expectStatus().isOk();
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routes").exchange().expectStatus().isOk()
.expectBodyList(Map.class).consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
List ids = responseBody.stream().map(route -> route.get("route_id"))
.filter(id -> id.equals(routeId1) || id.equals(routeId2)).collect(Collectors.toList());
assertThat(ids).containsExactly(routeId1, routeId2);
});
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId2)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition2))
.exchange()
.expectStatus()
.isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group2)
.exchange()
.expectStatus()
.isOk();
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routes")
.exchange()
.expectStatus()
.isOk()
.expectBodyList(Map.class)
.consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
List ids = responseBody.stream()
.map(route -> route.get("route_id"))
.filter(id -> id.equals(routeId1) || id.equals(routeId2))
.collect(Collectors.toList());
assertThat(ids).containsExactly(routeId1, routeId2);
});
}
@Test
@@ -274,24 +372,42 @@ public class GatewayControllerEndpointTests {
testRouteDefinition.setMetadata(Map.of("groupBy", group1));
String routeId1 = "route-1_" + UUID.randomUUID();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isCreated();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange().expectStatus().isOk();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange()
.expectStatus()
.isOk();
testClient.delete().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1).exchange()
.expectStatus().isOk();
testClient.delete()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1)
.exchange()
.expectStatus()
.isOk();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange().expectStatus().isOk();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange()
.expectStatus()
.isOk();
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routes").exchange().expectStatus().isOk()
.expectBodyList(Map.class).consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).extracting("route_id").doesNotContain(routeId1);
});
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routes")
.exchange()
.expectStatus()
.isOk()
.expectBodyList(Map.class)
.consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).extracting("route_id").doesNotContain(routeId1);
});
}
@Test
@@ -303,26 +419,42 @@ public class GatewayControllerEndpointTests {
testRouteDefinition.setFilters(List.of(new FilterDefinition("StripPrefix=wrong")));
String routeId1 = UUID.randomUUID().toString();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isCreated();
RouteDefinition testRouteDefinition2 = new RouteDefinition();
testRouteDefinition2.setUri(URI.create("http://valid.route"));
testRouteDefinition2.setMetadata(Map.of("groupBy", group1));
String routeId2 = UUID.randomUUID().toString();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId2)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition2)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId2)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition2))
.exchange()
.expectStatus()
.isCreated();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange().expectStatus().isOk();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange()
.expectStatus()
.isOk();
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routes").exchange().expectStatus().isOk()
.expectBodyList(Map.class).consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).extracting("route_id").doesNotContain(routeId1, routeId2);
});
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routes")
.exchange()
.expectStatus()
.isOk()
.expectBodyList(Map.class)
.consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).extracting("route_id").doesNotContain(routeId1, routeId2);
});
}
@Test
@@ -339,12 +471,20 @@ public class GatewayControllerEndpointTests {
testRouteDefinition2.setId(routeId2);
testRouteDefinition2.setUri(URI.create("http://valid-group-1.route"));
testRouteDefinition2.setMetadata(Map.of("groupBy", group1));
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isCreated();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId2)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition2)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId1)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId2)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition2))
.exchange()
.expectStatus()
.isCreated();
RouteDefinition testRouteDefinition3 = new RouteDefinition();
String routeId3 = UUID.randomUUID().toString();
@@ -357,27 +497,47 @@ public class GatewayControllerEndpointTests {
testRouteDefinition4.setId(routeId4);
testRouteDefinition4.setUri(URI.create("http://valid-group-2.route"));
testRouteDefinition4.setMetadata(Map.of("groupBy", group2));
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId3)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition3)).exchange()
.expectStatus().isCreated();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId4)
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition4)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId3)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition3))
.exchange()
.expectStatus()
.isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/" + routeId4)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition4))
.exchange()
.expectStatus()
.isCreated();
// When
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange().expectStatus().isOk();
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group2)
.exchange().expectStatus().isOk();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group1)
.exchange()
.expectStatus()
.isOk();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/refresh?metadata=groupBy:" + group2)
.exchange()
.expectStatus()
.isOk();
// Then
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routes").exchange().expectStatus().isOk()
.expectBodyList(Map.class).consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).extracting("route_id").doesNotContain(routeId1, routeId2)
.contains(routeId3, routeId4);
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routes")
.exchange()
.expectStatus()
.isOk()
.expectBodyList(Map.class)
.consumeWith(result -> {
List<Map> responseBody = result.getResponseBody();
assertThat(responseBody).extracting("route_id")
.doesNotContain(routeId1, routeId2)
.contains(routeId3, routeId4);
});
});
}
@Test
@@ -390,8 +550,8 @@ public class GatewayControllerEndpointTests {
FilterDefinition prefixPathFilterDefinition = new FilterDefinition("PrefixPath=/test-path");
FilterDefinition redirectToFilterDefinition = new FilterDefinition("RemoveResponseHeader=Sensitive-Header");
FilterDefinition testFilterDefinition = new FilterDefinition("TestFilter");
testRouteDefinition.setFilters(
Arrays.asList(prefixPathFilterDefinition, redirectToFilterDefinition, testFilterDefinition));
testRouteDefinition
.setFilters(Arrays.asList(prefixPathFilterDefinition, redirectToFilterDefinition, testFilterDefinition));
PredicateDefinition hostRoutePredicateDefinition = new PredicateDefinition("Host=myhost.org");
PredicateDefinition methodRoutePredicateDefinition = new PredicateDefinition("Method=GET");
@@ -407,8 +567,8 @@ public class GatewayControllerEndpointTests {
FilterDefinition prefixPathFilterDefinition2 = new FilterDefinition("PrefixPath=/test-path-2");
FilterDefinition redirectToFilterDefinition2 = new FilterDefinition("RemoveResponseHeader=Sensitive-Header-2");
FilterDefinition testFilterDefinition2 = new FilterDefinition("TestFilter");
testRouteDefinition2.setFilters(
Arrays.asList(prefixPathFilterDefinition2, redirectToFilterDefinition2, testFilterDefinition2));
testRouteDefinition2
.setFilters(Arrays.asList(prefixPathFilterDefinition2, redirectToFilterDefinition2, testFilterDefinition2));
PredicateDefinition hostRoutePredicateDefinition2 = new PredicateDefinition("Host=myhost-2.org");
PredicateDefinition methodRoutePredicateDefinition2 = new PredicateDefinition("Method=GET");
@@ -418,12 +578,20 @@ public class GatewayControllerEndpointTests {
List<RouteDefinition> multipleRouteDefs = List.of(testRouteDefinition, testRouteDefinition2);
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes")
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(multipleRouteDefs)).exchange()
.expectStatus().isOk();
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routedefinitions")
.accept(MediaType.APPLICATION_JSON).exchange().expectBody()
.jsonPath("[?(@.id in ['%s','%s'])].id".formatted(routeId1, routeId2)).exists();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes")
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(multipleRouteDefs))
.exchange()
.expectStatus()
.isOk();
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routedefinitions")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectBody()
.jsonPath("[?(@.id in ['%s','%s'])].id".formatted(routeId1, routeId2))
.exists();
}
@Test
@@ -437,8 +605,8 @@ public class GatewayControllerEndpointTests {
FilterDefinition prefixPathFilterDefinition = new FilterDefinition("PrefixPath=/test-path");
FilterDefinition redirectToFilterDefinition = new FilterDefinition("RemoveResponseHeader=Sensitive-Header");
FilterDefinition testFilterDefinition = new FilterDefinition("TestFilter");
testRouteDefinition.setFilters(
Arrays.asList(prefixPathFilterDefinition, redirectToFilterDefinition, testFilterDefinition));
testRouteDefinition
.setFilters(Arrays.asList(prefixPathFilterDefinition, redirectToFilterDefinition, testFilterDefinition));
PredicateDefinition hostRoutePredicateDefinition = new PredicateDefinition("Host=myhost.org");
PredicateDefinition methodRoutePredicateDefinition = new PredicateDefinition("Method=GET");
@@ -453,20 +621,28 @@ public class GatewayControllerEndpointTests {
List<RouteDefinition> multipleRouteDefs = List.of(testRouteDefinition, testRouteDefinition2);
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes")
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(multipleRouteDefs)).exchange()
.expectStatus().is4xxClientError();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes")
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(multipleRouteDefs))
.exchange()
.expectStatus()
.is4xxClientError();
testClient.get().uri("http://localhost:" + port + "/actuator/gateway/routedefinitions")
.accept(MediaType.APPLICATION_JSON).exchange().expectBody()
.jsonPath("[?(@.id in ['%s','%s'])].id".formatted(routeId1, routeId2)).doesNotExist();
testClient.get()
.uri("http://localhost:" + port + "/actuator/gateway/routedefinitions")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectBody()
.jsonPath("[?(@.id in ['%s','%s'])].id".formatted(routeId1, routeId2))
.doesNotExist();
}
@Test
public void testPostValidShortcutRouteDefinition() {
RouteDefinition testRouteDefinition = new RouteDefinition();
testRouteDefinition.setId(
"gatewaywithgrpcfiltertest-0-104014-8916263311295787431172436062-test-gateway-tls-client-mapping-0");
testRouteDefinition
.setId("gatewaywithgrpcfiltertest-0-104014-8916263311295787431172436062-test-gateway-tls-client-mapping-0");
testRouteDefinition.setUri(URI.create("https://localhost:8095"));
testRouteDefinition.setOrder(0);
testRouteDefinition.setMetadata(Collections.emptyMap());
@@ -488,9 +664,13 @@ public class GatewayControllerEndpointTests {
hostRoutePredicateDefinition.addArg("_genkey_0", "/json/hello");
testRouteDefinition.setPredicates(Arrays.asList(hostRoutePredicateDefinition));
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/test-route")
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isCreated();
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/test-route")
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isCreated();
}
@Test
@@ -502,10 +682,16 @@ public class GatewayControllerEndpointTests {
FilterDefinition filterDefinition = new FilterDefinition("NotExistingFilter=test-config");
testRouteDefinition.setFilters(Collections.singletonList(filterDefinition));
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/test-route")
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isBadRequest().expectBody().jsonPath("$.message")
.isEqualTo("Invalid FilterDefinition: [NotExistingFilter]");
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/test-route")
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isBadRequest()
.expectBody()
.jsonPath("$.message")
.isEqualTo("Invalid FilterDefinition: [NotExistingFilter]");
}
@Test
@@ -514,10 +700,16 @@ public class GatewayControllerEndpointTests {
RouteDefinition testRouteDefinition = new RouteDefinition();
testRouteDefinition.setUri(URI.create("example.org"));
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/no-scheme-test-route")
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isBadRequest().expectBody().jsonPath("$.message")
.isEqualTo("The URI format [example.org] is incorrect, scheme can not be empty");
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/no-scheme-test-route")
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isBadRequest()
.expectBody()
.jsonPath("$.message")
.isEqualTo("The URI format [example.org] is incorrect, scheme can not be empty");
}
@Test
@@ -526,9 +718,16 @@ public class GatewayControllerEndpointTests {
RouteDefinition testRouteDefinition = new RouteDefinition();
testRouteDefinition.setUri(null);
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/no-scheme-test-route")
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isBadRequest().expectBody().jsonPath("$.message").isEqualTo("The URI can not be empty");
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/no-scheme-test-route")
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isBadRequest()
.expectBody()
.jsonPath("$.message")
.isEqualTo("The URI can not be empty");
}
@Test
@@ -540,10 +739,16 @@ public class GatewayControllerEndpointTests {
PredicateDefinition predicateDefinition = new PredicateDefinition("NotExistingPredicate=test-config");
testRouteDefinition.setPredicates(Collections.singletonList(predicateDefinition));
testClient.post().uri("http://localhost:" + port + "/actuator/gateway/routes/test-route")
.accept(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(testRouteDefinition)).exchange()
.expectStatus().isBadRequest().expectBody().jsonPath("$.message")
.isEqualTo("Invalid PredicateDefinition: [NotExistingPredicate]");
testClient.post()
.uri("http://localhost:" + port + "/actuator/gateway/routes/test-route")
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(testRouteDefinition))
.exchange()
.expectStatus()
.isBadRequest()
.expectBody()
.jsonPath("$.message")
.isEqualTo("Invalid PredicateDefinition: [NotExistingPredicate]");
}
@SpringBootConfiguration
@@ -554,7 +759,8 @@ public class GatewayControllerEndpointTests {
@Bean
RouteLocator testRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
return routeLocatorBuilder.routes()
.route("test-service", r -> r.path("/test-service/**").uri("lb://test-service")).build();
.route("test-service", r -> r.path("/test-service/**").uri("lb://test-service"))
.build();
}
@Bean

View File

@@ -58,7 +58,8 @@ class ConfigurableHintsRegistrationProcessorTests {
@Test
void shouldRegisterReflectionHintsForTypeAndSuperTypesAndGenerics() {
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(SpringCloudCircuitBreakerResilience4JFilterFactory.class).getBeanDefinition();
.rootBeanDefinition(SpringCloudCircuitBreakerResilience4JFilterFactory.class)
.getBeanDefinition();
beanFactory.registerBeanDefinition("test", beanDefinition);
BeanFactoryInitializationAotContribution contribution = processor.processAheadOfTime(beanFactory);

View File

@@ -77,7 +77,7 @@ public class GatewayAutoConfigurationTests {
try (ConfigurableApplicationContext ctx = SpringApplication.run(Config.class, "--spring.jmx.enabled=false",
"--server.port=0")) {
assertThat(ctx.getEnvironment().getProperty("spring.webflux.hiddenmethod.filter.enabled"))
.isEqualTo("false");
.isEqualTo("false");
assertThat(ctx.getBeanNamesForType(HiddenHttpMethodFilter.class)).isEmpty();
}
}
@@ -85,83 +85,83 @@ public class GatewayAutoConfigurationTests {
@Test
public void nettyHttpClientDefaults() {
new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
ServerPropertiesConfig.class))
.withPropertyValues("debug=true").run(context -> {
assertThat(context).hasSingleBean(HttpClient.class);
HttpClient httpClient = context.getBean(HttpClient.class);
CustomHttpClientFactory factory = context.getBean(CustomHttpClientFactory.class);
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
ServerPropertiesConfig.class))
.withPropertyValues("debug=true")
.run(context -> {
assertThat(context).hasSingleBean(HttpClient.class);
HttpClient httpClient = context.getBean(HttpClient.class);
CustomHttpClientFactory factory = context.getBean(CustomHttpClientFactory.class);
assertThat(factory.connectionProvider).isNotNull();
assertThat(factory.connectionProvider.maxConnections()).isEqualTo(Integer.MAX_VALUE); // elastic
assertThat(factory.connectionProvider).isNotNull();
assertThat(factory.connectionProvider.maxConnections()).isEqualTo(Integer.MAX_VALUE); // elastic
assertThat(factory.proxyProvider).isNull();
assertThat(factory.isSslConfigured()).isFalse();
assertThat(factory.proxyProvider).isNull();
assertThat(factory.isSslConfigured()).isFalse();
assertThat(httpClient.configuration().isAcceptGzip()).isFalse();
assertThat(httpClient.configuration().loggingHandler()).isNull();
assertThat(httpClient.configuration().options())
.doesNotContainKey(ChannelOption.CONNECT_TIMEOUT_MILLIS);
});
assertThat(httpClient.configuration().isAcceptGzip()).isFalse();
assertThat(httpClient.configuration().loggingHandler()).isNull();
assertThat(httpClient.configuration().options())
.doesNotContainKey(ChannelOption.CONNECT_TIMEOUT_MILLIS);
});
}
@Test
public void nettyHttpClientConfigured() {
new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
HttpClientCustomizedConfig.class, ServerPropertiesConfig.class))
.withPropertyValues("spring.cloud.gateway.httpclient.ssl.use-insecure-trust-manager=true",
"spring.cloud.gateway.httpclient.connect-timeout=10",
"spring.cloud.gateway.httpclient.response-timeout=10s",
"spring.cloud.gateway.httpclient.pool.eviction-interval=10s",
"spring.cloud.gateway.httpclient.pool.type=fixed",
"spring.cloud.gateway.httpclient.pool.metrics=true",
"spring.cloud.gateway.httpclient.compression=true",
"spring.cloud.gateway.httpclient.wiretap=true",
// greater than integer max value
"spring.cloud.gateway.httpclient.max-initial-line-length=2147483647",
"spring.cloud.gateway.httpclient.proxy.host=myhost",
"spring.cloud.gateway.httpclient.websocket.max-frame-payload-length=1024")
.run(context -> {
assertThat(context).hasSingleBean(HttpClient.class);
HttpClient httpClient = context.getBean(HttpClient.class);
CustomHttpClientFactory factory = context.getBean(CustomHttpClientFactory.class);
HttpClientProperties properties = context.getBean(HttpClientProperties.class);
assertThat(properties.getMaxInitialLineLength().toBytes()).isLessThanOrEqualTo(Integer.MAX_VALUE);
assertThat(properties.isCompression()).isEqualTo(true);
assertThat(properties.getPool().getEvictionInterval()).hasSeconds(10);
assertThat(properties.getPool().isMetrics()).isEqualTo(true);
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
HttpClientCustomizedConfig.class, ServerPropertiesConfig.class))
.withPropertyValues("spring.cloud.gateway.httpclient.ssl.use-insecure-trust-manager=true",
"spring.cloud.gateway.httpclient.connect-timeout=10",
"spring.cloud.gateway.httpclient.response-timeout=10s",
"spring.cloud.gateway.httpclient.pool.eviction-interval=10s",
"spring.cloud.gateway.httpclient.pool.type=fixed",
"spring.cloud.gateway.httpclient.pool.metrics=true",
"spring.cloud.gateway.httpclient.compression=true", "spring.cloud.gateway.httpclient.wiretap=true",
// greater than integer max value
"spring.cloud.gateway.httpclient.max-initial-line-length=2147483647",
"spring.cloud.gateway.httpclient.proxy.host=myhost",
"spring.cloud.gateway.httpclient.websocket.max-frame-payload-length=1024")
.run(context -> {
assertThat(context).hasSingleBean(HttpClient.class);
HttpClient httpClient = context.getBean(HttpClient.class);
CustomHttpClientFactory factory = context.getBean(CustomHttpClientFactory.class);
HttpClientProperties properties = context.getBean(HttpClientProperties.class);
assertThat(properties.getMaxInitialLineLength().toBytes()).isLessThanOrEqualTo(Integer.MAX_VALUE);
assertThat(properties.isCompression()).isEqualTo(true);
assertThat(properties.getPool().getEvictionInterval()).hasSeconds(10);
assertThat(properties.getPool().isMetrics()).isEqualTo(true);
assertThat(httpClient.configuration().isAcceptGzip()).isTrue();
assertThat(httpClient.configuration().loggingHandler()).isNotNull();
assertThat(httpClient.configuration().options()).containsKey(ChannelOption.CONNECT_TIMEOUT_MILLIS);
assertThat(httpClient.configuration().options().get(ChannelOption.CONNECT_TIMEOUT_MILLIS))
.isEqualTo(10);
assertThat(httpClient.configuration().isAcceptGzip()).isTrue();
assertThat(httpClient.configuration().loggingHandler()).isNotNull();
assertThat(httpClient.configuration().options()).containsKey(ChannelOption.CONNECT_TIMEOUT_MILLIS);
assertThat(httpClient.configuration().options().get(ChannelOption.CONNECT_TIMEOUT_MILLIS))
.isEqualTo(10);
assertThat(factory.connectionProvider).isNotNull();
// fixed pool
assertThat(factory.connectionProvider.maxConnections())
.isEqualTo(ConnectionProvider.DEFAULT_POOL_MAX_CONNECTIONS);
assertThat(factory.connectionProvider).isNotNull();
// fixed pool
assertThat(factory.connectionProvider.maxConnections())
.isEqualTo(ConnectionProvider.DEFAULT_POOL_MAX_CONNECTIONS);
assertThat(factory.proxyProvider).isNotNull();
assertThat(factory.proxyProvider.build().getAddress().get().getHostName()).isEqualTo("myhost");
assertThat(factory.proxyProvider).isNotNull();
assertThat(factory.proxyProvider.build().getAddress().get().getHostName()).isEqualTo("myhost");
assertThat(factory.isSslConfigured()).isTrue();
assertThat(factory.isInsecureTrustManagerSet()).isTrue();
assertThat(factory.isSslConfigured()).isTrue();
assertThat(factory.isInsecureTrustManagerSet()).isTrue();
assertThat(context).hasSingleBean(ReactorNettyRequestUpgradeStrategy.class);
ReactorNettyRequestUpgradeStrategy upgradeStrategy = context
.getBean(ReactorNettyRequestUpgradeStrategy.class);
assertThat(upgradeStrategy.getWebsocketServerSpec().maxFramePayloadLength()).isEqualTo(1024);
assertThat(upgradeStrategy.getWebsocketServerSpec().handlePing()).isTrue();
assertThat(context).hasSingleBean(ReactorNettyWebSocketClient.class);
ReactorNettyWebSocketClient webSocketClient = context.getBean(ReactorNettyWebSocketClient.class);
assertThat(webSocketClient.getWebsocketClientSpec().maxFramePayloadLength()).isEqualTo(1024);
HttpClientCustomizedConfig config = context.getBean(HttpClientCustomizedConfig.class);
assertThat(config.called.get()).isTrue();
});
assertThat(context).hasSingleBean(ReactorNettyRequestUpgradeStrategy.class);
ReactorNettyRequestUpgradeStrategy upgradeStrategy = context
.getBean(ReactorNettyRequestUpgradeStrategy.class);
assertThat(upgradeStrategy.getWebsocketServerSpec().maxFramePayloadLength()).isEqualTo(1024);
assertThat(upgradeStrategy.getWebsocketServerSpec().handlePing()).isTrue();
assertThat(context).hasSingleBean(ReactorNettyWebSocketClient.class);
ReactorNettyWebSocketClient webSocketClient = context.getBean(ReactorNettyWebSocketClient.class);
assertThat(webSocketClient.getWebsocketClientSpec().maxFramePayloadLength()).isEqualTo(1024);
HttpClientCustomizedConfig config = context.getBean(HttpClientCustomizedConfig.class);
assertThat(config.called.get()).isTrue();
});
}
@Test
@@ -185,39 +185,39 @@ public class GatewayAutoConfigurationTests {
@Test
public void tokenRelayBeansAreCreated() {
new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
ReactiveOAuth2ClientAutoConfiguration.class, GatewayReactiveOAuth2AutoConfiguration.class,
GatewayAutoConfiguration.TokenRelayConfiguration.class))
.withPropertyValues(
"spring.security.oauth2.client.provider[testprovider].authorization-uri=http://localhost",
"spring.security.oauth2.client.provider[testprovider].token-uri=http://localhost/token",
"spring.security.oauth2.client.registration[test].provider=testprovider",
"spring.security.oauth2.client.registration[test].authorization-grant-type=authorization_code",
"spring.security.oauth2.client.registration[test].redirect-uri=http://localhost/redirect",
"spring.security.oauth2.client.registration[test].client-id=login-client")
.run(context -> {
assertThat(context).hasSingleBean(ReactiveOAuth2AuthorizedClientManager.class);
assertThat(context).hasSingleBean(TokenRelayGatewayFilterFactory.class);
});
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
ReactiveOAuth2ClientAutoConfiguration.class, GatewayReactiveOAuth2AutoConfiguration.class,
GatewayAutoConfiguration.TokenRelayConfiguration.class))
.withPropertyValues(
"spring.security.oauth2.client.provider[testprovider].authorization-uri=http://localhost",
"spring.security.oauth2.client.provider[testprovider].token-uri=http://localhost/token",
"spring.security.oauth2.client.registration[test].provider=testprovider",
"spring.security.oauth2.client.registration[test].authorization-grant-type=authorization_code",
"spring.security.oauth2.client.registration[test].redirect-uri=http://localhost/redirect",
"spring.security.oauth2.client.registration[test].client-id=login-client")
.run(context -> {
assertThat(context).hasSingleBean(ReactiveOAuth2AuthorizedClientManager.class);
assertThat(context).hasSingleBean(TokenRelayGatewayFilterFactory.class);
});
}
@Test
public void gatewayReactiveOAuth2AuthorizedClientManagerBacksOffForCustomBean() {
new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
ReactiveOAuth2ClientAutoConfiguration.class, GatewayReactiveOAuth2AutoConfiguration.class))
.withUserConfiguration(TestReactiveOAuth2AuthorizedClientManagerConfig.class)
.withPropertyValues(
"spring.security.oauth2.client.provider[testprovider].authorization-uri=http://localhost",
"spring.security.oauth2.client.provider[testprovider].token-uri=http://localhost/token",
"spring.security.oauth2.client.registration[test].provider=testprovider",
"spring.security.oauth2.client.registration[test].authorization-grant-type=authorization_code",
"spring.security.oauth2.client.registration[test].redirect-uri=http://localhost/redirect",
"spring.security.oauth2.client.registration[test].client-id=login-client")
.run(context -> {
assertThat(context).hasSingleBean(ReactiveOAuth2AuthorizedClientManager.class);
assertThat(context).hasBean("myReactiveOAuth2AuthorizedClientManager");
});
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
ReactiveOAuth2ClientAutoConfiguration.class, GatewayReactiveOAuth2AutoConfiguration.class))
.withUserConfiguration(TestReactiveOAuth2AuthorizedClientManagerConfig.class)
.withPropertyValues(
"spring.security.oauth2.client.provider[testprovider].authorization-uri=http://localhost",
"spring.security.oauth2.client.provider[testprovider].token-uri=http://localhost/token",
"spring.security.oauth2.client.registration[test].provider=testprovider",
"spring.security.oauth2.client.registration[test].authorization-grant-type=authorization_code",
"spring.security.oauth2.client.registration[test].redirect-uri=http://localhost/redirect",
"spring.security.oauth2.client.registration[test].client-id=login-client")
.run(context -> {
assertThat(context).hasSingleBean(ReactiveOAuth2AuthorizedClientManager.class);
assertThat(context).hasBean("myReactiveOAuth2AuthorizedClientManager");
});
}
@Test
@@ -235,14 +235,14 @@ public class GatewayAutoConfigurationTests {
assertThat(ctx.getBeanNamesForType(GatewayLegacyControllerEndpoint.class)).hasSize(1);
}
}).hasRootCauseInstanceOf(IllegalStateException.class)
.hasMessageContaining("No TokenRelayGatewayFilterFactory bean was found. Did you include");
.hasMessageContaining("No TokenRelayGatewayFilterFactory bean was found. Did you include");
}
@Test // gh-2159
public void reactorNettyRequestUpgradeStrategyWebSocketSpecBuilderIsUniquePerRequest()
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ReactorNettyRequestUpgradeStrategy strategy = new GatewayAutoConfiguration.NettyConfiguration()
.reactorNettyRequestUpgradeStrategy(new HttpClientProperties());
.reactorNettyRequestUpgradeStrategy(new HttpClientProperties());
// Method "buildSpec" was introduced for Tests, but has only default visiblity
Method buildSpec = ReactorNettyRequestUpgradeStrategy.class.getDeclaredMethod("buildSpec", String.class);
@@ -258,7 +258,7 @@ public class GatewayAutoConfigurationTests {
public void webSocketClientSpecBuilderIsUniquePerReactorNettyWebSocketClient()
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ReactorNettyWebSocketClient websocketClient = new GatewayAutoConfiguration.NettyConfiguration()
.reactorNettyWebSocketClient(new HttpClientProperties(), HttpClient.create());
.reactorNettyWebSocketClient(new HttpClientProperties(), HttpClient.create());
// Method "buildSpec" has only private visibility
Method buildSpec = ReactorNettyWebSocketClient.class.getDeclaredMethod("buildSpec", String.class);
@@ -274,53 +274,56 @@ public class GatewayAutoConfigurationTests {
@Test
public void gRPCFiltersConfiguredWhenHTTP2Enabled() {
new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
HttpClientCustomizedConfig.class, ServerPropertiesConfig.class))
.withPropertyValues("server.http2.enabled=true").run(context -> {
assertThat(context).hasSingleBean(GRPCRequestHeadersFilter.class);
assertThat(context).hasSingleBean(GRPCResponseHeadersFilter.class);
HttpClient httpClient = context.getBean(HttpClient.class);
assertThat(httpClient.configuration().protocols()).contains(HttpProtocol.HTTP11, HttpProtocol.H2);
});
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
HttpClientCustomizedConfig.class, ServerPropertiesConfig.class))
.withPropertyValues("server.http2.enabled=true")
.run(context -> {
assertThat(context).hasSingleBean(GRPCRequestHeadersFilter.class);
assertThat(context).hasSingleBean(GRPCResponseHeadersFilter.class);
HttpClient httpClient = context.getBean(HttpClient.class);
assertThat(httpClient.configuration().protocols()).contains(HttpProtocol.HTTP11, HttpProtocol.H2);
});
}
@Test
public void gRPCFiltersNotConfiguredWhenHTTP2Disabled() {
new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
HttpClientCustomizedConfig.class, ServerPropertiesConfig.class))
.withPropertyValues("server.http2.enabled=false").run(context -> {
assertThat(context).doesNotHaveBean(GRPCRequestHeadersFilter.class);
assertThat(context).doesNotHaveBean(GRPCResponseHeadersFilter.class);
});
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
HttpClientCustomizedConfig.class, ServerPropertiesConfig.class))
.withPropertyValues("server.http2.enabled=false")
.run(context -> {
assertThat(context).doesNotHaveBean(GRPCRequestHeadersFilter.class);
assertThat(context).doesNotHaveBean(GRPCResponseHeadersFilter.class);
});
}
@Test
public void insecureTrustManagerNotEnabledByDefaultWhenHTTP2Enabled() {
new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
HttpClientCustomizedConfig.class, ServerPropertiesConfig.class))
.withPropertyValues("server.http2.enabled=true").run(context -> {
assertThat(context).hasSingleBean(HttpClient.class);
CustomHttpClientFactory factory = context.getBean(CustomHttpClientFactory.class);
assertThat(factory.isInsecureTrustManagerSet()).isFalse();
});
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
HttpClientCustomizedConfig.class, ServerPropertiesConfig.class))
.withPropertyValues("server.http2.enabled=true")
.run(context -> {
assertThat(context).hasSingleBean(HttpClient.class);
CustomHttpClientFactory factory = context.getBean(CustomHttpClientFactory.class);
assertThat(factory.isInsecureTrustManagerSet()).isFalse();
});
}
@Test
public void customHttpClientWorks() {
new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
HttpClientCustomizedConfig.class, CustomHttpClientConfig.class))
.run(context -> {
assertThat(context).hasSingleBean(HttpClient.class);
HttpClient httpClient = context.getBean(HttpClient.class);
assertThat(httpClient).isInstanceOf(CustomHttpClient.class);
});
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
HttpClientCustomizedConfig.class, CustomHttpClientConfig.class))
.run(context -> {
assertThat(context).hasSingleBean(HttpClient.class);
HttpClient httpClient = context.getBean(HttpClient.class);
assertThat(httpClient).isInstanceOf(CustomHttpClient.class);
});
}
@Configuration
@@ -447,8 +450,8 @@ public class GatewayAutoConfigurationTests {
@Bean
public RouteLocator myRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("test", r -> r.alwaysTrue().filters(GatewayFilterSpec::tokenRelay).uri("http://localhost"))
.build();
.route("test", r -> r.alwaysTrue().filters(GatewayFilterSpec::tokenRelay).uri("http://localhost"))
.build();
}
}

View File

@@ -119,14 +119,14 @@ public class GatewayMetricsAutoConfigurationTests {
@Test
public void observabilityBeansMissing() {
assertThat(beanFactory.getBeanProvider(ObservedRequestHttpHeadersFilter.class).getIfAvailable(() -> null))
.isNull();
.isNull();
assertThat(beanFactory.getBeanProvider(ObservedResponseHttpHeadersFilter.class).getIfAvailable(() -> null))
.isNull();
.isNull();
assertThat(
beanFactory.getBeanProvider(ObservationClosingWebExceptionHandler.class).getIfAvailable(() -> null))
.isNull();
.isNull();
assertThat(beanFactory.getBeanProvider(GatewayPropagatingSenderTracingObservationHandler.class)
.getIfAvailable(() -> null)).isNull();
.getIfAvailable(() -> null)).isNull();
}
}

View File

@@ -32,23 +32,25 @@ public class LocalResponseCacheAutoConfigurationTests {
@Test
void onlyOneCacheManagerBeanCreated() {
new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(LocalResponseCacheAutoConfiguration.class))
.withPropertyValues("spring.cloud.gateway.filter.local-response-cache.enabled=true").run(context -> {
context.containsBean(LocalResponseCacheAutoConfiguration.RESPONSE_CACHE_MANAGER_NAME);
context.assertThat().hasSingleBean(GlobalLocalResponseCacheGatewayFilter.class);
});
.withConfiguration(AutoConfigurations.of(LocalResponseCacheAutoConfiguration.class))
.withPropertyValues("spring.cloud.gateway.filter.local-response-cache.enabled=true")
.run(context -> {
context.containsBean(LocalResponseCacheAutoConfiguration.RESPONSE_CACHE_MANAGER_NAME);
context.assertThat().hasSingleBean(GlobalLocalResponseCacheGatewayFilter.class);
});
}
@Test
void twoCacheManagerBeans() {
new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(CustomCacheManagerConfig.class,
LocalResponseCacheAutoConfiguration.class))
.withPropertyValues("spring.cloud.gateway.filter.local-response-cache.enabled=true").run(context -> {
context.containsBean(LocalResponseCacheAutoConfiguration.RESPONSE_CACHE_MANAGER_NAME);
context.containsBean("myCacheManager");
context.assertThat().hasSingleBean(GlobalLocalResponseCacheGatewayFilter.class);
});
.withConfiguration(
AutoConfigurations.of(CustomCacheManagerConfig.class, LocalResponseCacheAutoConfiguration.class))
.withPropertyValues("spring.cloud.gateway.filter.local-response-cache.enabled=true")
.run(context -> {
context.containsBean(LocalResponseCacheAutoConfiguration.RESPONSE_CACHE_MANAGER_NAME);
context.containsBean("myCacheManager");
context.assertThat().hasSingleBean(GlobalLocalResponseCacheGatewayFilter.class);
});
}
@Configuration(proxyBeanMethods = false)

View File

@@ -67,8 +67,9 @@ public class DisableBuiltInFiltersTests {
@Test
public void shouldInjectOnlyEnabledBuiltInFilters() {
assertThat(gatewayFilters).hasSizeGreaterThan(0);
assertThat(gatewayFilters).allSatisfy(filter -> assertThat(filter).isNotInstanceOfAny(
AddRequestHeaderGatewayFilterFactory.class, MapRequestHeaderGatewayFilterFactory.class));
assertThat(gatewayFilters)
.allSatisfy(filter -> assertThat(filter).isNotInstanceOfAny(AddRequestHeaderGatewayFilterFactory.class,
MapRequestHeaderGatewayFilterFactory.class));
}
}

View File

@@ -68,7 +68,7 @@ public class DisableBuiltInGlobalFiltersTests {
public void shouldInjectOnlyEnabledBuiltInFilters() {
assertThat(globalFilters).hasSizeGreaterThan(0);
assertThat(globalFilters).allSatisfy(filter -> assertThat(filter)
.isNotInstanceOfAny(RemoveCachedBodyFilter.class, RouteToRequestUrlFilter.class));
.isNotInstanceOfAny(RemoveCachedBodyFilter.class, RouteToRequestUrlFilter.class));
}
}

View File

@@ -68,7 +68,7 @@ public class DisableBuiltInPredicatesTests {
public void shouldInjectOnlyEnabledBuiltInPredicates() {
assertThat(predicates).hasSizeGreaterThan(0);
assertThat(predicates).allSatisfy(filter -> assertThat(filter)
.isNotInstanceOfAny(AfterRoutePredicateFactory.class, BeforeRoutePredicateFactory.class));
.isNotInstanceOfAny(AfterRoutePredicateFactory.class, BeforeRoutePredicateFactory.class));
}
}

View File

@@ -73,7 +73,7 @@ class OnEnabledComponentTests {
private AnnotatedTypeMetadata mockMetaData(Class<?> value) {
AnnotatedTypeMetadata metadata = mock(AnnotatedTypeMetadata.class);
when(metadata.getAnnotationAttributes(eq(ConditionalOnEnabledFilter.class.getName())))
.thenReturn(Collections.singletonMap("value", value));
.thenReturn(Collections.singletonMap("value", value));
return metadata;
}

View File

@@ -49,11 +49,15 @@ class OnEnabledFilterTests {
FallbackHeadersGatewayFilterFactory.class, MapRequestHeaderGatewayFilterFactory.class,
SpringCloudCircuitBreakerResilience4JFilterFactory.class);
List<String> resultNames = predicates.stream().map(onEnabledFilter::normalizeComponentName)
.collect(Collectors.toList());
List<String> resultNames = predicates.stream()
.map(onEnabledFilter::normalizeComponentName)
.collect(Collectors.toList());
List<String> expectedNames = Stream.of("add-request-header", "dedupe-response-header", "fallback-headers",
"map-request-header", "circuit-breaker").map(s -> "filter." + s).collect(Collectors.toList());
List<String> expectedNames = Stream
.of("add-request-header", "dedupe-response-header", "fallback-headers", "map-request-header",
"circuit-breaker")
.map(s -> "filter." + s)
.collect(Collectors.toList());
assertThat(resultNames).isEqualTo(expectedNames);
}

View File

@@ -45,11 +45,13 @@ class OnEnabledGlobalFilterTests {
List<Class<? extends GlobalFilter>> predicates = Arrays.asList(ForwardPathFilter.class,
AdaptCachedBodyGlobalFilter.class, WebsocketRoutingFilter.class);
List<String> resultNames = predicates.stream().map(onEnabledGlobalFilter::normalizeComponentName)
.collect(Collectors.toList());
List<String> resultNames = predicates.stream()
.map(onEnabledGlobalFilter::normalizeComponentName)
.collect(Collectors.toList());
List<String> expectedNames = Stream.of("forward-path", "adapt-cached-body", "websocket-routing")
.map(s -> "global-filter." + s).collect(Collectors.toList());
.map(s -> "global-filter." + s)
.collect(Collectors.toList());
assertThat(resultNames).isEqualTo(expectedNames);
}

View File

@@ -47,11 +47,13 @@ class OnEnabledPredicateTests {
CloudFoundryRouteServiceRoutePredicateFactory.class, ReadBodyRoutePredicateFactory.class,
RemoteAddrRoutePredicateFactory.class);
List<String> resultNames = predicates.stream().map(onEnabledPredicate::normalizeComponentName)
.collect(Collectors.toList());
List<String> resultNames = predicates.stream()
.map(onEnabledPredicate::normalizeComponentName)
.collect(Collectors.toList());
List<String> expectedNames = Stream.of("after", "cloud-foundry-route-service", "read-body", "remote-addr")
.map(s -> "predicate." + s).collect(Collectors.toList());
.map(s -> "predicate." + s)
.collect(Collectors.toList());
assertThat(resultNames).isEqualTo(expectedNames);
}

View File

@@ -46,28 +46,39 @@ public class CorsGlobalTests extends BaseWebClientTests {
@Test
public void testPreFlightCorsRequest() {
ClientResponse clientResponse = webClient.options().uri("/abc/123/function").header("Origin", "domain.com")
.header("Access-Control-Request-Method", "GET").exchangeToMono(Mono::just).block();
ClientResponse clientResponse = webClient.options()
.uri("/abc/123/function")
.header("Origin", "domain.com")
.header("Access-Control-Request-Method", "GET")
.exchangeToMono(Mono::just)
.block();
HttpHeaders asHttpHeaders = clientResponse.headers().asHttpHeaders();
Mono<String> bodyToMono = clientResponse.bodyToMono(String.class);
// pre-flight request shouldn't return the response body
assertThat(bodyToMono.block()).isNull();
assertThat(asHttpHeaders.getAccessControlAllowOrigin())
.as("Missing header value in response: " + HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN).isEqualTo("*");
.as("Missing header value in response: " + HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)
.isEqualTo("*");
assertThat(asHttpHeaders.getAccessControlAllowMethods())
.as("Missing header value in response: " + HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)
.isEqualTo(Arrays.asList(new HttpMethod[] { HttpMethod.GET }));
.as("Missing header value in response: " + HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS)
.isEqualTo(Arrays.asList(new HttpMethod[] { HttpMethod.GET }));
assertThat(clientResponse.statusCode()).as("Pre Flight call failed.").isEqualTo(HttpStatus.OK);
}
@Test
public void testCorsRequest() {
ResponseEntity<String> response = webClient.get().uri("/abc/123/function").header("Origin", "domain.com")
.header(HttpHeaders.HOST, "www.path.org").retrieve().toEntity(String.class).block();
ResponseEntity<String> response = webClient.get()
.uri("/abc/123/function")
.header("Origin", "domain.com")
.header(HttpHeaders.HOST, "www.path.org")
.retrieve()
.toEntity(String.class)
.block();
assertThat(response).isNotNull();
assertThat(response.getBody()).isNotNull();
assertThat(response.getHeaders().getAccessControlAllowOrigin())
.as("Missing header value in response: " + HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN).isEqualTo("*");
.as("Missing header value in response: " + HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)
.isEqualTo("*");
assertThat(response.getStatusCode()).as("CORS request failed.").isEqualTo(HttpStatus.OK);
}

View File

@@ -48,59 +48,79 @@ public class CorsPerRouteTests extends BaseWebClientTests {
@Test
public void testPreFlightCorsRequest() {
testClient.options().uri("/abc").header("Origin", "domain.com").header("Access-Control-Request-Method", "GET")
.exchange().expectBody(Map.class).consumeWith(result -> {
assertThat(result.getResponseBody()).isNull();
assertThat(result.getStatus()).isEqualTo(HttpStatus.OK);
testClient.options()
.uri("/abc")
.header("Origin", "domain.com")
.header("Access-Control-Request-Method", "GET")
.exchange()
.expectBody(Map.class)
.consumeWith(result -> {
assertThat(result.getResponseBody()).isNull();
assertThat(result.getStatus()).isEqualTo(HttpStatus.OK);
HttpHeaders responseHeaders = result.getResponseHeaders();
assertThat(responseHeaders.getAccessControlAllowOrigin())
.as(missingHeader(ACCESS_CONTROL_ALLOW_ORIGIN)).isEqualTo("domain.com");
assertThat(responseHeaders.getAccessControlAllowMethods())
.as(missingHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS))
.containsExactlyInAnyOrder(HttpMethod.GET, HttpMethod.POST);
assertThat(responseHeaders.getAccessControlMaxAge()).as(missingHeader(ACCESS_CONTROL_MAX_AGE))
.isEqualTo(30L);
assertThat(responseHeaders.getAccessControlAllowCredentials())
.as(missingHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS)).isEqualTo(true);
});
HttpHeaders responseHeaders = result.getResponseHeaders();
assertThat(responseHeaders.getAccessControlAllowOrigin()).as(missingHeader(ACCESS_CONTROL_ALLOW_ORIGIN))
.isEqualTo("domain.com");
assertThat(responseHeaders.getAccessControlAllowMethods())
.as(missingHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS))
.containsExactlyInAnyOrder(HttpMethod.GET, HttpMethod.POST);
assertThat(responseHeaders.getAccessControlMaxAge()).as(missingHeader(ACCESS_CONTROL_MAX_AGE))
.isEqualTo(30L);
assertThat(responseHeaders.getAccessControlAllowCredentials())
.as(missingHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS))
.isEqualTo(true);
});
}
@Test
public void testPreFlightCorsRequestJavaConfig() {
testClient.options().uri("/route-test").header("Origin", "another-domain.com")
.header("Host", "www.javaconfhost.org").header("Access-Control-Request-Method", "GET").exchange()
.expectBody(Map.class).consumeWith(result -> {
assertThat(result.getResponseBody()).isNull();
assertThat(result.getStatus()).isEqualTo(HttpStatus.OK);
testClient.options()
.uri("/route-test")
.header("Origin", "another-domain.com")
.header("Host", "www.javaconfhost.org")
.header("Access-Control-Request-Method", "GET")
.exchange()
.expectBody(Map.class)
.consumeWith(result -> {
assertThat(result.getResponseBody()).isNull();
assertThat(result.getStatus()).isEqualTo(HttpStatus.OK);
HttpHeaders responseHeaders = result.getResponseHeaders();
assertThat(responseHeaders.getAccessControlAllowOrigin())
.as(missingHeader(ACCESS_CONTROL_ALLOW_ORIGIN)).isEqualTo("another-domain.com");
assertThat(responseHeaders.getAccessControlAllowMethods())
.as(missingHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS))
.containsExactlyInAnyOrder(HttpMethod.GET);
assertThat(responseHeaders.getAccessControlMaxAge()).as(missingHeader(ACCESS_CONTROL_MAX_AGE))
.isEqualTo(50L);
});
HttpHeaders responseHeaders = result.getResponseHeaders();
assertThat(responseHeaders.getAccessControlAllowOrigin()).as(missingHeader(ACCESS_CONTROL_ALLOW_ORIGIN))
.isEqualTo("another-domain.com");
assertThat(responseHeaders.getAccessControlAllowMethods())
.as(missingHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS))
.containsExactlyInAnyOrder(HttpMethod.GET);
assertThat(responseHeaders.getAccessControlMaxAge()).as(missingHeader(ACCESS_CONTROL_MAX_AGE))
.isEqualTo(50L);
});
}
@Test
public void testPreFlightForbiddenCorsRequest() {
testClient.get().uri("/cors").header("Origin", "domain.com").header("Access-Control-Request-Method", "GET")
.exchange().expectBody(Map.class).consumeWith(result -> {
assertThat(result.getResponseBody()).isNull();
assertThat(result.getStatus()).isEqualTo(HttpStatus.FORBIDDEN);
});
testClient.get()
.uri("/cors")
.header("Origin", "domain.com")
.header("Access-Control-Request-Method", "GET")
.exchange()
.expectBody(Map.class)
.consumeWith(result -> {
assertThat(result.getResponseBody()).isNull();
assertThat(result.getStatus()).isEqualTo(HttpStatus.FORBIDDEN);
});
}
@Test
public void testCorsValidatedRequest() {
testClient.get().uri("/cors/status/201").header("Origin", "https://test.com").exchange()
.expectBody(String.class).consumeWith(result -> {
assertThat(result.getResponseBody()).endsWith("201");
assertThat(result.getStatus()).isEqualTo(HttpStatus.CREATED);
});
testClient.get()
.uri("/cors/status/201")
.header("Origin", "https://test.com")
.exchange()
.expectBody(String.class)
.consumeWith(result -> {
assertThat(result.getResponseBody()).endsWith("201");
assertThat(result.getStatus()).isEqualTo(HttpStatus.CREATED);
});
}
private String missingHeader(String accessControlAllowOrigin) {
@@ -118,13 +138,16 @@ public class CorsPerRouteTests extends BaseWebClientTests {
@Bean
public RouteLocator testRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("cors_route_java_test",
r -> r.host("*.javaconfhost.org").and().path("/route-test/**")
.filters(f -> f.stripPrefix(1).prefixPath("/httpbin"))
.metadata(Map.of("cors", Map.of("allowedOrigins", "another-domain.com",
"allowedMethods", HttpMethod.GET.name(), "maxAge", 50)))
.uri(uri))
.build();
.route("cors_route_java_test",
r -> r.host("*.javaconfhost.org")
.and()
.path("/route-test/**")
.filters(f -> f.stripPrefix(1).prefixPath("/httpbin"))
.metadata(Map.of("cors",
Map.of("allowedOrigins", "another-domain.com", "allowedMethods",
HttpMethod.GET.name(), "maxAge", 50)))
.uri(uri))
.build();
}
}

Some files were not shown because too many files have changed in this diff Show More