6 files changed,
51 insertions(+),
18 deletions(-)
Author:
Olexandr Smirnov
ss2316544@gmail.com
Committed by:
GitHub
noreply@github.com
Committed at:
2025-07-15 14:03:33 +0300
Parent:
d309c75
M
.env.example
@@ -50,3 +50,7 @@
RATELIMITER_RPS=100 RATELIMITER_BURST=10 RATELIMITER_TTL=3m + +SLOW_RATELIMITER_RPS=2 +SLOW_RATELIMITER_BURST=1 +SLOW_RATELIMITER_TTL=1m
M
cmd/api/main.go
@@ -124,6 +124,12 @@ TTL: cfg.RateLimiterTTL,
Burst: cfg.RateLimiterBurst, } + slowRateLimiterConfig := ratelimit.Config{ + RPS: cfg.SlowRateLimiterRPS, + TTL: cfg.SlowRateLimiterTTL, + Burst: cfg.SlowRateLimiterBurst, + } + handler := httptransport.NewTransport( usersrv, notesrv,@@ -132,6 +138,7 @@ cfg.AppURL,
cfg.CORSAllowedOrigins, cfg.CORSMaxAge, rateLimiterConfig, + slowRateLimiterConfig, ) // http server
M
e2e/e2e_test.go
@@ -143,6 +143,7 @@ cfg.AppURL,
cfg.CORSAllowedOrigins, cfg.CORSMaxAge, ratelimitCfg, + ratelimitCfg, ) e.router = handler.Handler() }
M
internal/config/config.go
@@ -60,9 +60,12 @@ LogLevel string
LogFormat string LogShowLine bool - RateLimiterRPS int - RateLimiterBurst int - RateLimiterTTL time.Duration + RateLimiterRPS int + RateLimiterBurst int + RateLimiterTTL time.Duration + SlowRateLimiterRPS int + SlowRateLimiterBurst int + SlowRateLimiterTTL time.Duration } func NewConfig() *Config {@@ -116,9 +119,12 @@ LogLevel: getenvOrDefault("LOG_LEVEL", "debug"),
LogFormat: getenvOrDefault("LOG_FORMAT", "json"), LogShowLine: getenvOrDefault("LOG_SHOW_LINE", "true") == "true", - RateLimiterRPS: mustGetenvOrDefaultInt("RATELIMITER_RPS", 100), - RateLimiterBurst: mustGetenvOrDefaultInt("RATELIMITER_BURST", 10), - RateLimiterTTL: mustParseDuration(getenvOrDefault("RATELIMITER_TTL", "1m")), + RateLimiterRPS: mustGetenvOrDefaultInt("RATELIMITER_RPS", 100), + RateLimiterBurst: mustGetenvOrDefaultInt("RATELIMITER_BURST", 10), + RateLimiterTTL: mustParseDuration(getenvOrDefault("RATELIMITER_TTL", "1m")), + SlowRateLimiterRPS: mustGetenvOrDefaultInt("SLOW_RATELIMITER_RPS", 2), + SlowRateLimiterBurst: mustGetenvOrDefaultInt("SLOW_RATELIMITER_BURST", 2), + SlowRateLimiterTTL: mustParseDuration(getenvOrDefault("SLOW_RATELIMITER_TTL", "1m")), } }
M
internal/transport/http/apiv1/apiv1.go
@@ -5,26 +5,30 @@ "github.com/gin-gonic/gin"
"github.com/olexsmir/onasty/internal/config" "github.com/olexsmir/onasty/internal/service/notesrv" "github.com/olexsmir/onasty/internal/service/usersrv" + "github.com/olexsmir/onasty/internal/transport/http/ratelimit" ) type APIV1 struct { - usersrv usersrv.UserServicer - notesrv notesrv.NoteServicer - env config.Environment - domain string + usersrv usersrv.UserServicer + notesrv notesrv.NoteServicer + slowRatelimitCfg ratelimit.Config + env config.Environment + domain string } func NewAPIV1( us usersrv.UserServicer, ns notesrv.NoteServicer, + slowRatelimitCfg ratelimit.Config, env config.Environment, domain string, ) *APIV1 { return &APIV1{ - usersrv: us, - notesrv: ns, - env: env, - domain: domain, + usersrv: us, + notesrv: ns, + slowRatelimitCfg: slowRatelimitCfg, + env: env, + domain: domain, } }@@ -36,8 +40,8 @@ auth.POST("/signup", a.signUpHandler)
auth.POST("/signin", a.signInHandler) auth.POST("/refresh-tokens", a.refreshTokensHandler) auth.GET("/verify/:token", a.verifyHandler) - auth.POST("/resend-verification-email", a.resendVerificationEmailHandler) - auth.POST("/reset-password", a.requestResetPasswordHandler) + auth.POST("/resend-verification-email", a.slowRateLimit(), a.resendVerificationEmailHandler) + auth.POST("/reset-password", a.slowRateLimit(), a.requestResetPasswordHandler) auth.POST("/reset-password/:token", a.resetPasswordHandler) oauth := r.Group("/oauth")@@ -75,3 +79,7 @@ authorized.DELETE(":slug", a.deleteNoteHandler)
} } } + +func (a *APIV1) slowRateLimit() gin.HandlerFunc { + return ratelimit.MiddlewareWithConfig(a.slowRatelimitCfg) +}
M
internal/transport/http/http.go
@@ -23,6 +23,7 @@
corsAllowedOrigins []string corsMaxAge time.Duration ratelimitCfg ratelimit.Config + slowRatelimitCfg ratelimit.Config } func NewTransport(@@ -33,6 +34,7 @@ domain string,
corsAllowedOrigins []string, corsMaxAge time.Duration, ratelimitCfg ratelimit.Config, + slowRatelimitCfg ratelimit.Config, ) *Transport { return &Transport{ usersrv: us,@@ -42,6 +44,7 @@ domain: domain,
corsAllowedOrigins: corsAllowedOrigins, corsMaxAge: corsMaxAge, ratelimitCfg: ratelimitCfg, + slowRatelimitCfg: slowRatelimitCfg, } }@@ -56,8 +59,12 @@ ratelimit.MiddlewareWithConfig(t.ratelimitCfg),
) api := r.Group("/api") - api.GET("/ping", t.pingHandler) - apiv1.NewAPIV1(t.usersrv, t.notesrv, t.env, t.domain).Routes(api.Group("/v1")) + { + api.GET("/ping", t.pingHandler) + apiv1. + NewAPIV1(t.usersrv, t.notesrv, t.slowRatelimitCfg, t.env, t.domain). + Routes(api.Group("/v1")) + } return r.Handler() }