mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-09-09 05:08:27 +00:00
bee8458a2d
* feat: add rate limit middleware * chore: update vendor dir * chore: update readme with new dependency * chore: add rate limit infos to swagger.md file * refactor: add ipv6 mask limiter option Add IPv6 CIDR /64 mask * refactor: increase rate limit to 1000 Address https://github.com/superseriousbusiness/gotosocial/pull/741#discussion_r945584800 Co-authored-by: tobi <31960611+tsmethurst@users.noreply.github.com>
65 lines
1.4 KiB
Go
65 lines
1.4 KiB
Go
package gin
|
|
|
|
import (
|
|
"strconv"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/ulule/limiter/v3"
|
|
)
|
|
|
|
// Middleware is the middleware for gin.
|
|
type Middleware struct {
|
|
Limiter *limiter.Limiter
|
|
OnError ErrorHandler
|
|
OnLimitReached LimitReachedHandler
|
|
KeyGetter KeyGetter
|
|
ExcludedKey func(string) bool
|
|
}
|
|
|
|
// NewMiddleware return a new instance of a gin middleware.
|
|
func NewMiddleware(limiter *limiter.Limiter, options ...Option) gin.HandlerFunc {
|
|
middleware := &Middleware{
|
|
Limiter: limiter,
|
|
OnError: DefaultErrorHandler,
|
|
OnLimitReached: DefaultLimitReachedHandler,
|
|
KeyGetter: DefaultKeyGetter,
|
|
ExcludedKey: nil,
|
|
}
|
|
|
|
for _, option := range options {
|
|
option.apply(middleware)
|
|
}
|
|
|
|
return func(ctx *gin.Context) {
|
|
middleware.Handle(ctx)
|
|
}
|
|
}
|
|
|
|
// Handle gin request.
|
|
func (middleware *Middleware) Handle(c *gin.Context) {
|
|
key := middleware.KeyGetter(c)
|
|
if middleware.ExcludedKey != nil && middleware.ExcludedKey(key) {
|
|
c.Next()
|
|
return
|
|
}
|
|
|
|
context, err := middleware.Limiter.Get(c, key)
|
|
if err != nil {
|
|
middleware.OnError(c, err)
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
c.Header("X-RateLimit-Limit", strconv.FormatInt(context.Limit, 10))
|
|
c.Header("X-RateLimit-Remaining", strconv.FormatInt(context.Remaining, 10))
|
|
c.Header("X-RateLimit-Reset", strconv.FormatInt(context.Reset, 10))
|
|
|
|
if context.Reached {
|
|
middleware.OnLimitReached(c)
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
c.Next()
|
|
}
|