From ed4120722027353765fb13efd73dfae5457f6004 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Tue, 2 Jan 2024 20:37:06 +0530 Subject: [PATCH] Added rate limiter for order serivce --- src/order_service/api/middleware.go | 27 +++++++++++++++++++++++++++ src/order_service/api/routes.go | 3 +++ src/order_service/go.mod | 1 + src/order_service/go.sum | 2 ++ 4 files changed, 33 insertions(+) diff --git a/src/order_service/api/middleware.go b/src/order_service/api/middleware.go index 8572371..a1f5108 100644 --- a/src/order_service/api/middleware.go +++ b/src/order_service/api/middleware.go @@ -6,6 +6,7 @@ import ( "time" "github.com/gin-gonic/gin" + "github.com/go-redis/redis_rate/v10" log "github.com/sirupsen/logrus" "github.com/thejasmeetsingh/go-ecommerce/order_service/shared" ) @@ -62,3 +63,29 @@ func PrometheusMiddleware() gin.HandlerFunc { httpRequestDuration.WithLabelValues(c.FullPath(), c.Request.Method).Observe(duration) } } + +// Middleware for an IP based rate limiting +func RateLimiter(apiCfg *APIConfig) gin.HandlerFunc { + limiter := redis_rate.NewLimiter(apiCfg.Cache) + return func(ctx *gin.Context) { + // Key is based on the client's IP address + key := ctx.ClientIP() + + // Allow only 10 requests per minute per IP address + result, err := limiter.Allow(ctx, key, redis_rate.PerMinute(10)) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"message": "Internal Server Error"}) + ctx.Abort() + return + } + + if result.Allowed == 0 { + ctx.JSON(http.StatusTooManyRequests, gin.H{"message": "Rate Limit Exceeded"}) + ctx.Abort() + return + } + + // Continue processing the request + ctx.Next() + } +} diff --git a/src/order_service/api/routes.go b/src/order_service/api/routes.go index 630004c..9b9ade7 100644 --- a/src/order_service/api/routes.go +++ b/src/order_service/api/routes.go @@ -15,6 +15,9 @@ func GetRoutes(engine *gin.Engine, apiCfg *APIConfig) { }) }) + // Add Rate limiter middleware + engine.Use(RateLimiter(apiCfg)) + // Add prometheus middleware and route engine.Use(PrometheusMiddleware()) engine.GET("/metrics/", gin.WrapH(promhttp.Handler())) diff --git a/src/order_service/go.mod b/src/order_service/go.mod index 8a1efc3..651ff1d 100644 --- a/src/order_service/go.mod +++ b/src/order_service/go.mod @@ -4,6 +4,7 @@ go 1.21.1 require ( github.com/gin-gonic/gin v1.9.1 + github.com/go-redis/redis_rate/v10 v10.0.1 github.com/go-resty/resty/v2 v2.11.0 github.com/google/uuid v1.5.0 github.com/joho/godotenv v1.5.1 diff --git a/src/order_service/go.sum b/src/order_service/go.sum index 1a922bb..a786140 100644 --- a/src/order_service/go.sum +++ b/src/order_service/go.sum @@ -32,6 +32,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-redis/redis_rate/v10 v10.0.1 h1:calPxi7tVlxojKunJwQ72kwfozdy25RjA0bCj1h0MUo= +github.com/go-redis/redis_rate/v10 v10.0.1/go.mod h1:EMiuO9+cjRkR7UvdvwMO7vbgqJkltQHtwbdIQvaBKIU= github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=