From 6a7d58436d45d4727e841e5d749711260da37f9c Mon Sep 17 00:00:00 2001 From: "Alessandro (Ale) Segala" <43508+ItalyPaleAle@users.noreply.github.com> Date: Wed, 14 Dec 2022 08:43:40 -0800 Subject: [PATCH] Fix ratelimit middleware not working (#2349) We need to set a value for the X-Forwarded-For header or the upstream library won't rate-limit requests. Additionally, upgraded the tollbooth library to v7. Fixes #2343 Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> --- go.mod | 3 +- go.sum | 6 ++-- .../http/ratelimit/ratelimit_middleware.go | 29 +++++++++++++++++-- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index da7ab44ff..d99eff8c5 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,7 @@ require ( github.com/denisenkom/go-mssqldb v0.12.3 github.com/dghubble/go-twitter v0.0.0-20221024160433-0cc1e72ed6d8 github.com/dghubble/oauth1 v0.7.1 - github.com/didip/tollbooth v4.0.2+incompatible + github.com/didip/tollbooth/v7 v7.0.1 github.com/eclipse/paho.mqtt.golang v1.4.2 github.com/fasthttp-contrib/sessions v0.0.0-20160905201309-74f6ac73d5d5 github.com/ghodss/yaml v1.0.0 @@ -204,6 +204,7 @@ require ( github.com/go-openapi/jsonreference v0.19.5 // indirect github.com/go-openapi/swag v0.19.14 // indirect github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect + github.com/go-pkgz/expirable-cache v0.1.0 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator/v10 v10.11.0 // indirect diff --git a/go.sum b/go.sum index d1ba277ba..3b9e4831a 100644 --- a/go.sum +++ b/go.sum @@ -445,8 +445,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= -github.com/didip/tollbooth v4.0.2+incompatible h1:fVSa33JzSz0hoh2NxpwZtksAzAgd7zjmGO20HCZtF4M= -github.com/didip/tollbooth v4.0.2+incompatible/go.mod h1:A9b0665CE6l1KmzpDws2++elm/CsuWBMa5Jv4WY0PEY= +github.com/didip/tollbooth/v7 v7.0.1 h1:TkT4sBKoQoHQFPf7blQ54iHrZiTDnr8TceU+MulVAog= +github.com/didip/tollbooth/v7 v7.0.1/go.mod h1:VZhDSGl5bDSPj4wPsih3PFa4Uh9Ghv8hgacaTm5PRT4= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= @@ -575,6 +575,8 @@ github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5F github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es= github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= +github.com/go-pkgz/expirable-cache v0.1.0 h1:3bw0m8vlTK8qlwz5KXuygNBTkiKRTPrAGXU0Ej2AC1g= +github.com/go-pkgz/expirable-cache v0.1.0/go.mod h1:GTrEl0X+q0mPNqN6dtcQXksACnzCBQ5k/k1SwXJsZKs= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= diff --git a/middleware/http/ratelimit/ratelimit_middleware.go b/middleware/http/ratelimit/ratelimit_middleware.go index 97b1294d9..a28e39664 100644 --- a/middleware/http/ratelimit/ratelimit_middleware.go +++ b/middleware/http/ratelimit/ratelimit_middleware.go @@ -18,7 +18,8 @@ import ( "net/http" "strconv" - "github.com/didip/tollbooth" + tollbooth "github.com/didip/tollbooth/v7" + libstring "github.com/didip/tollbooth/v7/libstring" "github.com/dapr/components-contrib/middleware" "github.com/dapr/kit/logger" @@ -54,7 +55,31 @@ func (m *Middleware) GetHandler(metadata middleware.Metadata) (func(next http.Ha limiter := tollbooth.NewLimiter(meta.MaxRequestsPerSecond, nil) return func(next http.Handler) http.Handler { - return tollbooth.LimitHandler(limiter, next) + // Adapted from toolbooth.LimitHandler + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // The tollbooth library requires a remote IP. If this isn't present in the request's headers, then we need to set a value for X-Forwarded-For or the rate limiter won't work + remoteIP := libstring.RemoteIP(limiter.GetIPLookups(), limiter.GetForwardedForIndexFromBehind(), r) + remoteIP = libstring.CanonicalizeIP(remoteIP) + if remoteIP == "" { + // Forcefully set a remote IP + r.Header.Set("X-Forwarded-For", "0.0.0.0") + } + + httpError := tollbooth.LimitByRequest(limiter, w, r) + if httpError != nil { + limiter.ExecOnLimitReached(w, r) + if limiter.GetOverrideDefaultResponseWriter() { + return + } + w.Header().Add("Content-Type", limiter.GetMessageContentType()) + w.WriteHeader(httpError.StatusCode) + w.Write([]byte(httpError.Message)) + return + } + + // There's no rate-limit error, serve the next handler. + next.ServeHTTP(w, r) + }) }, nil }