Skip to content

Commit

Permalink
feature: #159-Api Rate Limiter Filter 적용
Browse files Browse the repository at this point in the history
  • Loading branch information
mclub4 committed May 8, 2024
1 parent 3675cf5 commit ffb1147
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 31 deletions.
19 changes: 19 additions & 0 deletions back-gateway/redis-server.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## Test Version

version: '3'

services:
redis:
image: redis:7.2.0-alpine
container_name: redis
hostname: redis
restart: unless-stopped
environment:
TZ: "Asia/Seoul"
ports:
- 6379:6379
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
interval: 5s
timeout: 3s
retries: 10
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ public class GatewayConfig {
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder,
AuthorizationHeaderFilter authFilter,
RequestRateLimitFilter limitFilter) {
/**
* 여기에 JWT토큰 및 API Rate Limiter가 필요한 Api Routing을 작성해주세요.
* Spring Security와 비슷한 느낌으로 해주시면 됩니다.
*/
return builder.routes()
.route("chatbot-docs",r -> r.path("/docs", "/openapi.json")
.uri(chatbotUrl))
Expand All @@ -26,7 +30,7 @@ public RouteLocator gatewayRoutes(RouteLocatorBuilder builder,
.filter(authFilter.apply(config -> {config.setRequiredRole("role_user");}))
.filter(limitFilter.apply(config -> {
config.setRateLimiter(redisRateLimiter());
config.setRouteId("chat");
config.setRouteId("chatbot");
}))
)
.uri(chatbotUrl))
Expand All @@ -45,20 +49,19 @@ public RouteLocator gatewayRoutes(RouteLocatorBuilder builder,
.route("spring", r -> r.path("/api/**")
.filters(f->f
.filter(authFilter.apply(config -> {config.setRequiredRole("role_user");}))
.requestRateLimiter(c -> {
c.setRateLimiter(redisRateLimiter());
})
.filter(limitFilter.apply(config -> {
config.setRateLimiter(redisRateLimiter());
config.setRouteId("spring");
}))
)
.uri("http://spring:8080"))
.build();
}

//TODO: Custom RedisRateLimiter로 변경 예정
@Bean
public RedisRateLimiter redisRateLimiter() {
return new RedisRateLimiter(1, 1, 1); // 기본 replenishRate 및 burstCapacity 값을 지정합니다
}

public UserIdKeyResolver userKeyResolver() {
return new UserIdKeyResolver();
// 기본 replenishRate 및 burstCapacity 값을 지정합니다
return new RedisRateLimiter(20, 60, 3);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.gateway.backgateway.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
Expand All @@ -12,10 +13,13 @@
@Configuration
public class RedisConfig {

@Value("${spring.data.redis.host}")
String redishost;

@Bean
@Primary
public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
return new LettuceConnectionFactory("redis", 6379);
return new LettuceConnectionFactory(redishost, 6379);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ else if (ex instanceof TooManyRequestException) {
errorCode = TOO_MANY_REQUESTS;
response.setStatusCode(HttpStatus.valueOf(errorCode.getStatus()));
}
else if (ex instanceof BusinessException) {
errorCode = ((BusinessException) ex).getErrorCode();
response.setStatusCode(HttpStatus.valueOf(String.valueOf(((BusinessException) ex).getErrorCode())));
}
else{
errorCode = INTERNAL_SERVER_ERROR;
response.setStatusCode(HttpStatus.valueOf(errorCode.getStatus()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,10 @@
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.security.Key;
import java.util.Map;
import java.util.function.Function;

@Component
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
package com.gateway.backgateway.filter;

import com.gateway.backgateway.config.UserIdKeyResolver;
import com.gateway.backgateway.exception.BusinessException;
import com.gateway.backgateway.exception.ErrorCode;
import com.gateway.backgateway.exception.TooManyRequestException;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.support.HasRouteId;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import static com.gateway.backgateway.exception.ErrorCode.TOO_MANY_REQUESTS;

@Component
@Slf4j
public class RequestRateLimitFilter extends AbstractGatewayFilterFactory<RequestRateLimitFilter.Config> {
Expand All @@ -43,18 +36,12 @@ public GatewayFilter apply(Config config) {
log.info("여기 필터 지나는지 확인 2222222");

return keyResolver.resolve(exchange)
.doOnNext(key -> log.info("Resolved key: {}", key))
.flatMap(key -> {
log.info("Calling rate limiter with routeId: {} and key: {}", routeId, key);
return rateLimiter.isAllowed(routeId, key);
})
.flatMap(key -> rateLimiter.isAllowed(routeId, key))
.flatMap(rateLimitResponse -> {
log.info("Rate limiter response: {}", rateLimitResponse);
log.info("여기 필터 지나는지 확인 2222222");
if (rateLimitResponse.isAllowed()) {
return chain.filter(exchange);
} else {
throw new BusinessException(TOO_MANY_REQUESTS);
throw TooManyRequestException.INSTANCE;
}
});
};
Expand Down

0 comments on commit ffb1147

Please sign in to comment.