From d7da8f133146de4fba1db13bfbc63242c917f817 Mon Sep 17 00:00:00 2001 From: Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> Date: Thu, 31 Oct 2024 22:37:31 +0300 Subject: backend: add rate limiting --- backend/api/rate.go | 20 ++++++++++++++++++++ backend/api/routes.go | 28 ++++++++++++++-------------- backend/go.mod | 1 + backend/go.sum | 2 ++ 4 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 backend/api/rate.go diff --git a/backend/api/rate.go b/backend/api/rate.go new file mode 100644 index 0000000..1e262af --- /dev/null +++ b/backend/api/rate.go @@ -0,0 +1,20 @@ +package api + +import ( + "net/http" + + "golang.org/x/time/rate" + + "github.com/gin-gonic/gin" +) + +func RateLimit(c *gin.Context) { + limiter := rate.NewLimiter(1, 5) // don't know if this is too much or not enough tbh + if limiter.Allow() { + c.Next() + } else { + c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{ + "error": "Rate limit exceeded", + }) + } +} diff --git a/backend/api/routes.go b/backend/api/routes.go index ecfb54b..c3124f9 100644 --- a/backend/api/routes.go +++ b/backend/api/routes.go @@ -18,29 +18,29 @@ func InitRoutes(router *gin.Engine) { c.File("docs/index.html") }) // Tokens, login - v1.GET("/token", handlers.GetCookie) - v1.DELETE("/token", handlers.DeleteCookie) - v1.GET("/login", handlers.Login) + v1.GET("/token", RateLimit, handlers.GetCookie) + v1.DELETE("/token", RateLimit, handlers.DeleteCookie) + v1.GET("/login", RateLimit, handlers.Login) // Users, profiles - v1.GET("/profile", IsAuthenticated, handlers.Profile) + v1.GET("/profile", RateLimit, IsAuthenticated, handlers.Profile) v1.PUT("/profile", IsAuthenticated, handlers.UpdateCountryCode) v1.POST("/profile", IsAuthenticated, handlers.UpdateUser) v1.GET("/users/:userid", IsAuthenticated, handlers.FetchUser) // Maps // - Summary - v1.GET("/maps/:mapid/summary", handlers.FetchMapSummary) + v1.GET("/maps/:mapid/summary", RateLimit, handlers.FetchMapSummary) v1.POST("/maps/:mapid/summary", IsAuthenticated, handlers.CreateMapSummary) v1.PUT("/maps/:mapid/summary", IsAuthenticated, handlers.EditMapSummary) v1.DELETE("/maps/:mapid/summary", IsAuthenticated, handlers.DeleteMapSummary) v1.PUT("/maps/:mapid/image", IsAuthenticated, handlers.EditMapImage) // - Leaderboards - v1.GET("/maps/:mapid/leaderboards", handlers.FetchMapLeaderboards) + v1.GET("/maps/:mapid/leaderboards", RateLimit, handlers.FetchMapLeaderboards) v1.POST("/maps/:mapid/record", IsAuthenticated, handlers.CreateRecordWithDemo) v1.DELETE("/maps/:mapid/record/:recordid", IsAuthenticated, handlers.DeleteRecord) - v1.GET("/demos", handlers.DownloadDemoWithID) + v1.GET("/demos", RateLimit, handlers.DownloadDemoWithID) // - Discussions - v1.GET("/maps/:mapid/discussions", handlers.FetchMapDiscussions) - v1.GET("/maps/:mapid/discussions/:discussionid", handlers.FetchMapDiscussion) + v1.GET("/maps/:mapid/discussions", RateLimit, handlers.FetchMapDiscussions) + v1.GET("/maps/:mapid/discussions/:discussionid", RateLimit, handlers.FetchMapDiscussion) v1.POST("/maps/:mapid/discussions", IsAuthenticated, handlers.CreateMapDiscussion) v1.POST("/maps/:mapid/discussions/:discussionid", IsAuthenticated, handlers.CreateMapDiscussionComment) v1.PUT("/maps/:mapid/discussions/:discussionid", IsAuthenticated, handlers.EditMapDiscussion) @@ -50,12 +50,12 @@ func InitRoutes(router *gin.Engine) { v1.GET("/rankings/steam", handlers.RankingsSteam) v1.GET("/search", handlers.SearchWithQuery) // Games, chapters, maps - v1.GET("/games", handlers.FetchGames) - v1.GET("/games/:gameid", handlers.FetchChapters) - v1.GET("/chapters/:chapterid", handlers.FetchChapterMaps) - v1.GET("/games/:gameid/maps", handlers.FetchMaps) + v1.GET("/games", RateLimit, handlers.FetchGames) + v1.GET("/games/:gameid", RateLimit, handlers.FetchChapters) + v1.GET("/chapters/:chapterid", RateLimit, handlers.FetchChapterMaps) + v1.GET("/games/:gameid/maps", RateLimit, handlers.FetchMaps) // Logs - v1.GET("/logs/score", handlers.ScoreLogs) + v1.GET("/logs/score", RateLimit, handlers.ScoreLogs) // v1.GET("/logs/mod", IsAuthenticated, handlers.ModLogs) } } diff --git a/backend/go.mod b/backend/go.mod index f6eef48..17308f3 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -14,6 +14,7 @@ require ( github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.3 + golang.org/x/time v0.6.0 ) require ( diff --git a/backend/go.sum b/backend/go.sum index 10504e4..647f6f9 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -219,6 +219,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -- cgit v1.2.3