polish and update tests

This commit is contained in:
spencergibb
2021-07-27 21:33:34 -04:00
parent 4d5f4abb0d
commit 5002fe2e0a
5 changed files with 118 additions and 109 deletions

View File

@@ -72,8 +72,7 @@ class GatewayRedisAutoConfiguration {
}
@Bean
@ConditionalOnProperty(
value = "spring.cloud.gateway.redis-route-definition-repository.enabled",
@ConditionalOnProperty(value = "spring.cloud.gateway.redis-route-definition-repository.enabled",
havingValue = "true")
@ConditionalOnClass(ReactiveRedisTemplate.class)
public RedisRouteDefinitionRepository redisRouteDefinitionRepository(
@@ -89,8 +88,7 @@ class GatewayRedisAutoConfiguration {
RouteDefinition.class);
RedisSerializationContext.RedisSerializationContextBuilder<String, RouteDefinition> builder = RedisSerializationContext
.newSerializationContext(keySerializer);
RedisSerializationContext<String, RouteDefinition> context = builder
.value(valueSerializer).build();
RedisSerializationContext<String, RouteDefinition> context = builder.value(valueSerializer).build();
return new ReactiveRedisTemplate<>(factory, context);
}

View File

@@ -16,6 +16,8 @@
package org.springframework.cloud.gateway.route;
import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Flux;
@@ -63,7 +65,7 @@ public class CompositeRouteDefinitionLocator implements RouteDefinitionLocator {
}
protected Mono<String> randomId() {
return Mono.fromSupplier(idGenerator::toString).publishOn(Schedulers.boundedElastic());
return Mono.fromSupplier(idGenerator::generateId).map(UUID::toString).publishOn(Schedulers.boundedElastic());
}
}

View File

@@ -43,16 +43,14 @@ public class RedisRouteDefinitionRepository implements RouteDefinitionRepository
private ReactiveValueOperations<String, RouteDefinition> routeDefinitionReactiveValueOperations;
public RedisRouteDefinitionRepository(
ReactiveRedisTemplate<String, RouteDefinition> reactiveRedisTemplate) {
public RedisRouteDefinitionRepository(ReactiveRedisTemplate<String, RouteDefinition> reactiveRedisTemplate) {
this.reactiveRedisTemplate = reactiveRedisTemplate;
this.routeDefinitionReactiveValueOperations = reactiveRedisTemplate.opsForValue();
}
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
return reactiveRedisTemplate.keys(createKey("*"))
.flatMap(key -> reactiveRedisTemplate.opsForValue().get(key))
return reactiveRedisTemplate.keys(createKey("*")).flatMap(key -> reactiveRedisTemplate.opsForValue().get(key))
.onErrorContinue((throwable, routeDefinition) -> {
if (log.isErrorEnabled()) {
log.error("get routes from redis error cause : {}", throwable.toString(), throwable);
@@ -63,28 +61,24 @@ public class RedisRouteDefinitionRepository implements RouteDefinitionRepository
@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
return route.flatMap(routeDefinition -> routeDefinitionReactiveValueOperations
.set(createKey(routeDefinition.getId()), routeDefinition)
.flatMap(success -> {
.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))));
String.format("Could not add route to redis repository: %s", routeDefinition))));
}));
}
@Override
public Mono<Void> delete(Mono<String> routeId) {
return routeId.flatMap(id -> routeDefinitionReactiveValueOperations
.delete(createKey(id)).flatMap(success -> {
if (success) {
return Mono.empty();
}
return Mono.defer(() -> Mono.error(new NotFoundException(String
.format("Could not remove route from redis repository with id: %s",
routeId))));
}));
return routeId.flatMap(id -> routeDefinitionReactiveValueOperations.delete(createKey(id)).flatMap(success -> {
if (success) {
return Mono.empty();
}
return Mono.defer(() -> Mono.error(new NotFoundException(
String.format("Could not remove route from redis repository with id: %s", routeId))));
}));
}
private String createKey(String routeId) {

View File

@@ -16,40 +16,55 @@
package org.springframework.cloud.gateway.config;
import java.io.IOException;
import java.util.function.Predicate;
import javax.annotation.PreDestroy;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import redis.embedded.RedisServer;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.route.RedisRouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RedisRouteDefinitionRepositoryTests;
import org.springframework.context.annotation.Bean;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.web.server.ServerWebExchange;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(Enclosed.class)
public class GatewayRedisAutoConfigurationTests {
@SpringBootConfiguration
@EnableAutoConfiguration
protected static class Config {
// TODO: figure out why I need these
@Bean
RedisRouteDefinitionRepositoryTests.TestGatewayFilterFactory testGatewayFilterFactory() {
return new RedisRouteDefinitionRepositoryTests.TestGatewayFilterFactory();
}
@Bean
RedisRouteDefinitionRepositoryTests.TestFilterGatewayFilterFactory testFilterGatewayFilterFactory() {
return new RedisRouteDefinitionRepositoryTests.TestFilterGatewayFilterFactory();
}
@Bean
RedisRouteDefinitionRepositoryTests.TestRoutePredicateFactory testRoutePredicateFactory() {
return new RedisRouteDefinitionRepositoryTests.TestRoutePredicateFactory();
}
}
@RunWith(SpringRunner.class)
@Nested
@SpringBootTest(classes = Config.class)
public static class EnabledByDefault {
class EnabledByDefault {
@Autowired(required = false)
private RedisScript redisRequestRateLimiterScript;
@@ -65,9 +80,9 @@ public class GatewayRedisAutoConfigurationTests {
}
@RunWith(SpringRunner.class)
@Nested
@SpringBootTest(classes = Config.class, properties = "spring.cloud.gateway.redis.enabled=false")
public static class DisabledByProperty {
class DisabledByProperty {
@Autowired(required = false)
private RedisScript redisRequestRateLimiterScript;
@@ -86,12 +101,11 @@ public class GatewayRedisAutoConfigurationTests {
/**
* @author Dennis Menge
*/
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = RedisRouteDefinitionRepositoryDisabledByProperty.TestConfig.class,
@Nested
@SpringBootTest(classes = GatewayRedisAutoConfigurationTests.Config.class,
properties = "spring.cloud.gateway.redis-route-definition-repository.enabled=false")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public static class RedisRouteDefinitionRepositoryDisabledByProperty {
class RedisRouteDefinitionRepositoryDisabledByProperty {
@Autowired(required = false)
private RedisRouteDefinitionRepository redisRouteDefinitionRepository;
@@ -101,23 +115,19 @@ public class GatewayRedisAutoConfigurationTests {
assertThat(redisRouteDefinitionRepository).isNull();
}
@EnableAutoConfiguration
@SpringBootConfiguration
public static class TestConfig {
}
}
/**
* @author Dennis Menge
*/
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = RedisRouteDefinitionRepositoryEnabledByProperty.TestConfig.class,
@Nested
@SpringBootTest(classes = GatewayRedisAutoConfigurationTests.Config.class,
properties = "spring.cloud.gateway.redis-route-definition-repository.enabled=true")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public static class RedisRouteDefinitionRepositoryEnabledByProperty {
class RedisRouteDefinitionRepositoryEnabledByProperty {
@Container
public GenericContainer redis = new GenericContainer<>("redis:5.0.9-alpine").withExposedPorts(6379);
@Autowired(required = false)
private RedisRouteDefinitionRepository redisRouteDefinitionRepository;
@@ -127,25 +137,6 @@ public class GatewayRedisAutoConfigurationTests {
assertThat(redisRouteDefinitionRepository).isNotNull();
}
@EnableAutoConfiguration
@SpringBootConfiguration
public static class TestConfig {
private RedisServer redisServer;
@Bean
public RedisServer redisServer() throws IOException {
redisServer = new RedisServer();
redisServer.start();
return redisServer;
}
@PreDestroy
public void destroy() {
redisServer.stop();
}
}
}
}

View File

@@ -16,44 +16,51 @@
package org.springframework.cloud.gateway.route;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PreDestroy;
import java.util.function.Predicate;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import reactor.core.publisher.Mono;
import redis.embedded.RedisServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.server.ServerWebExchange;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Dennis Menge
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@SpringBootTest(properties = { "debug=true", "logging.level.org.springframework.cloud.gateway=trace" })
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@ActiveProfiles("redis-route-repository")
@Testcontainers
public class RedisRouteDefinitionRepositoryTests {
@Container
public GenericContainer redis = new GenericContainer<>("redis:5.0.9-alpine").withExposedPorts(6379);
@Autowired
private RedisRouteDefinitionRepository redisRouteDefinitionRepository;
@Disabled
@Test
public void testAddRouteToRedis() {
@@ -61,13 +68,14 @@ public class RedisRouteDefinitionRepositoryTests {
redisRouteDefinitionRepository.save(Mono.just(testRouteDefinition)).block();
List<RouteDefinition> routeDefinitions = redisRouteDefinitionRepository
.getRouteDefinitions().collectList().block();
List<RouteDefinition> routeDefinitions = redisRouteDefinitionRepository.getRouteDefinitions().collectList()
.block();
assertThat(routeDefinitions.size()).isEqualTo(1);
assertThat(routeDefinitions.get(0)).isEqualTo(testRouteDefinition);
}
@Disabled
@Test
public void testRemoveRouteFromRedis() {
@@ -75,8 +83,8 @@ public class RedisRouteDefinitionRepositoryTests {
redisRouteDefinitionRepository.save(Mono.just(testRouteDefinition)).block();
List<RouteDefinition> routeDefinitions = redisRouteDefinitionRepository
.getRouteDefinitions().collectList().block();
List<RouteDefinition> routeDefinitions = redisRouteDefinitionRepository.getRouteDefinitions().collectList()
.block();
String routeId = routeDefinitions.get(0).getId();
// Assert that route has been added.
@@ -86,31 +94,27 @@ public class RedisRouteDefinitionRepositoryTests {
redisRouteDefinitionRepository.delete(Mono.just(routeId)).block();
// Assert that route has been removed.
assertThat(redisRouteDefinitionRepository.getRouteDefinitions().collectList()
.block().size()).isEqualTo(0);
assertThat(redisRouteDefinitionRepository.getRouteDefinitions().collectList().block().size()).isEqualTo(0);
}
@NotNull
private RouteDefinition defaultTestRoute() {
RouteDefinition testRouteDefinition = new RouteDefinition();
testRouteDefinition.setId("test-route");
testRouteDefinition.setUri(URI.create("http://example.org"));
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));
FilterDefinition prefixPathFilterDefinition = new FilterDefinition("PrefixPath=/test-path");
FilterDefinition redirectToFilterDefinition = new FilterDefinition("RemoveResponseHeader=Sensitive-Header");
FilterDefinition testFilterDefinition = new FilterDefinition();
testFilterDefinition.setName("Test");
testRouteDefinition.setFilters(
Arrays.asList(prefixPathFilterDefinition, redirectToFilterDefinition, testFilterDefinition));
PredicateDefinition hostRoutePredicateDefinition = new PredicateDefinition(
"Host=myhost.org");
PredicateDefinition methodRoutePredicateDefinition = new PredicateDefinition(
"Method=GET");
PredicateDefinition testPredicateDefinition = new PredicateDefinition(
"Test=value");
testRouteDefinition.setPredicates(Arrays.asList(hostRoutePredicateDefinition,
methodRoutePredicateDefinition, testPredicateDefinition));
PredicateDefinition hostRoutePredicateDefinition = new PredicateDefinition("Host=myhost.org");
PredicateDefinition methodRoutePredicateDefinition = new PredicateDefinition("Method=GET");
PredicateDefinition testPredicateDefinition = new PredicateDefinition("Test=value");
testRouteDefinition.setPredicates(
Arrays.asList(hostRoutePredicateDefinition, methodRoutePredicateDefinition, testPredicateDefinition));
return testRouteDefinition;
}
@@ -118,21 +122,41 @@ public class RedisRouteDefinitionRepositoryTests {
@SpringBootConfiguration
public static class TestConfig {
RedisServer redisServer;
@Bean
TestGatewayFilterFactory testGatewayFilterFactory() {
return new TestGatewayFilterFactory();
}
@Bean
public RedisServer redisServer() throws IOException {
redisServer = new RedisServer();
redisServer.start();
return redisServer;
TestFilterGatewayFilterFactory testFilterGatewayFilterFactory() {
return new TestFilterGatewayFilterFactory();
}
@PreDestroy
public void destroy() {
redisServer.stop();
@Bean
TestRoutePredicateFactory testRoutePredicateFactory() {
return new TestRoutePredicateFactory();
}
}
public static class TestGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> chain.filter(exchange);
}
}
public static class TestFilterGatewayFilterFactory extends TestGatewayFilterFactory {
}
public static class TestRoutePredicateFactory extends AbstractRoutePredicateFactory<Object> {
public TestRoutePredicateFactory() {
super(Object.class);
}
@Override
public Predicate<ServerWebExchange> apply(Object config) {
return exchange -> true;
}
}
}