feat(api): add rate limiting

This commit is contained in:
Sam 2022-05-26 00:41:06 +02:00
parent 52a03b4aa6
commit 2ee1087eec
4 changed files with 41 additions and 0 deletions

View file

@ -3,11 +3,14 @@ package server
import (
"net/http"
"os"
"strconv"
"time"
"codeberg.org/u1f320/pronouns.cc/backend/db"
"codeberg.org/u1f320/pronouns.cc/backend/server/auth"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/httprate"
"github.com/go-chi/render"
)
@ -41,6 +44,33 @@ func New() (*Server, error) {
// enable authentication for all routes (but don't require it)
s.Router.Use(s.maybeAuth)
// rate limit handling
// - 120 req/minute (2/s)
// - keyed by Authorization header if valid token is provided, otherwise by IP
// - returns rate limit reset info in error
s.Router.Use(httprate.Limit(
120, time.Minute,
httprate.WithKeyFuncs(func(r *http.Request) (string, error) {
_, ok := ClaimsFromContext(r.Context())
if token := r.Header.Get("Authorization"); ok && token != "" {
return token, nil
}
ip, err := httprate.KeyByIP(r)
return ip, err
}),
httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) {
reset, _ := strconv.Atoi(w.Header().Get("X-RateLimit-Reset"))
render.Status(r, http.StatusTooManyRequests)
render.JSON(w, r, APIError{
Code: ErrTooManyRequests,
Message: errCodeMessages[ErrTooManyRequests],
RatelimitReset: &reset,
})
}),
))
// return an API error for not found + method not allowed
s.Router.NotFound(func(w http.ResponseWriter, r *http.Request) {
render.Status(r, errCodeStatuses[ErrNotFound])