diff --git a/spring-cloud/spring-cloud-gateway/pom.xml b/spring-cloud/spring-cloud-gateway/pom.xml index ada32ae85f..c692eed7ec 100644 --- a/spring-cloud/spring-cloud-gateway/pom.xml +++ b/spring-cloud/spring-cloud-gateway/pom.xml @@ -1,7 +1,7 @@ + xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-cloud-gateway spring-cloud-gateway @@ -54,7 +54,21 @@ org.springframework.cloud spring-cloud-starter-circuitbreaker-reactor-resilience4j - + + + + org.springframework.boot + spring-boot-starter-data-redis-reactive + + + + + it.ozimov + embedded-redis + ${redis.version} + test + + org.hibernate hibernate-validator-cdi @@ -75,8 +89,8 @@ test - org.springframework.boot - spring-boot-devtools + org.springframework.boot + spring-boot-devtools @@ -93,6 +107,7 @@ Hoxton.SR3 2.2.6.RELEASE 6.0.2.Final + 0.7.2 diff --git a/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/webfilters/config/RequestRateLimiterResolverConfig.java b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/webfilters/config/RequestRateLimiterResolverConfig.java new file mode 100644 index 0000000000..f80a742fa6 --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/webfilters/config/RequestRateLimiterResolverConfig.java @@ -0,0 +1,16 @@ +package com.baeldung.springcloudgateway.webfilters.config; + +import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import reactor.core.publisher.Mono; + +@Configuration +public class RequestRateLimiterResolverConfig { + + @Bean + KeyResolver userKeyResolver() { + return exchange -> Mono.just("1"); + } +} diff --git a/spring-cloud/spring-cloud-gateway/src/main/resources/application-webfilters.yml b/spring-cloud/spring-cloud-gateway/src/main/resources/application-webfilters.yml index 9b3ec64f96..3348cbbba0 100644 --- a/spring-cloud/spring-cloud-gateway/src/main/resources/application-webfilters.yml +++ b/spring-cloud/spring-cloud-gateway/src/main/resources/application-webfilters.yml @@ -1,4 +1,12 @@ +logging: + level: + org.springframework.cloud.gateway: INFO + reactor.netty.http.client: INFO + spring: + redis: + host: localhost + port: 6379 cloud: gateway: routes: @@ -81,13 +89,14 @@ spring: factor: 2 basedOnPreviousValue: false - - id: circuitbreaker_route + - id: request_rate_limiter uri: https://httpbin.org predicates: - - Path=/status/504 + - Path=/redis/get/** filters: - - name: CircuitBreaker + - StripPrefix=1 + - name: RequestRateLimiter args: - name: myCircuitBreaker - fallbackUri: forward:/anything - - RewritePath=/status/504, /anything \ No newline at end of file + redis-rate-limiter.replenishRate: 10 + redis-rate-limiter.burstCapacity: 5 + key-resolver: "#{@userKeyResolver}" \ No newline at end of file diff --git a/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/webfilters/RedisWebFilterFactoriesLiveTest.java b/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/webfilters/RedisWebFilterFactoriesLiveTest.java new file mode 100644 index 0000000000..a28eb68775 --- /dev/null +++ b/spring-cloud/spring-cloud-gateway/src/test/java/com/baeldung/springcloudgateway/webfilters/RedisWebFilterFactoriesLiveTest.java @@ -0,0 +1,64 @@ +package com.baeldung.springcloudgateway.webfilters; + +import org.junit.After; +import org.junit.Before; +import org.junit.jupiter.api.RepeatedTest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.ActiveProfiles; + +import redis.embedded.RedisServer; + +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@ActiveProfiles("webfilters") +@TestConfiguration +public class RedisWebFilterFactoriesLiveTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(RedisWebFilterFactoriesLiveTest.class); + + private RedisServer redisServer; + + public RedisWebFilterFactoriesLiveTest() { + } + + @Before + public void postConstruct() { + this.redisServer = new RedisServer(6379); + redisServer.start(); + } + + @LocalServerPort + String port; + + @Autowired + private TestRestTemplate restTemplate; + + @Autowired + TestRestTemplate template; + + @RepeatedTest(25) + public void whenCallRedisGetThroughGateway_thenOKStatusOrIsReceived() { + String url = "http://localhost:" + port + "/redis/get"; + + ResponseEntity r = restTemplate.getForEntity(url, String.class); + // assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + + LOGGER.info("Received: status->{}, reason->{}, remaining->{}", + r.getStatusCodeValue(), r.getStatusCode().getReasonPhrase(), + r.getHeaders().get("X-RateLimit-Remaining")); + } + + @After + public void preDestroy() { + redisServer.stop(); + } + +} diff --git a/spring-cloud/spring-cloud-gateway/src/test/resources/logback-test.xml b/spring-cloud/spring-cloud-gateway/src/test/resources/logback-test.xml index 6fcdb6317f..6980d119b1 100644 --- a/spring-cloud/spring-cloud-gateway/src/test/resources/logback-test.xml +++ b/spring-cloud/spring-cloud-gateway/src/test/resources/logback-test.xml @@ -3,7 +3,15 @@ + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + \ No newline at end of file