From b4aba437e5aab66be37478b85f3f199c2e1ca159 Mon Sep 17 00:00:00 2001 From: atridadl Date: Wed, 24 Jan 2024 20:07:42 -0700 Subject: [PATCH] Decoupled middleware --- go.mod | 5 ++-- go.sum | 6 ++--- main.go | 6 ++--- middleware/ratelimit.go | 60 ----------------------------------------- middleware/requestid.go | 41 ---------------------------- middleware/secure.go | 21 --------------- 6 files changed, 8 insertions(+), 131 deletions(-) delete mode 100644 middleware/ratelimit.go delete mode 100644 middleware/requestid.go delete mode 100644 middleware/secure.go diff --git a/go.mod b/go.mod index 8f51c80..8c0917f 100644 --- a/go.mod +++ b/go.mod @@ -24,14 +24,15 @@ require ( require ( github.com/alecthomas/assert/v2 v2.4.1 + github.com/atridadl/bunrouter.middleware v0.2.0 github.com/go-redis/redismock/v9 v9.2.0 - github.com/google/uuid v1.6.0 + github.com/google/uuid v1.6.0 // indirect github.com/joho/godotenv v1.5.1 github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/redis/go-redis/v9 v9.4.0 github.com/resendlabs/resend-go v1.7.0 - github.com/unrolled/secure v1.14.0 + github.com/unrolled/secure v1.14.0 // indirect github.com/uptrace/bunrouter v1.0.21 github.com/uptrace/bunrouter/extra/reqlog v1.0.21 github.com/yuin/goldmark v1.6.0 diff --git a/go.sum b/go.sum index db22b68..bf4a170 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/alecthomas/chroma/v2 v2.12.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurG github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= github.com/alecthomas/repr v0.3.0 h1:NeYzUPfjjlqHY4KtzgKJiWd6sVq2eNUPTi34PiFGjY8= github.com/alecthomas/repr v0.3.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/atridadl/bunrouter.middleware v0.2.0 h1:pEcQuYL9CJD/25Ff2ljtXfoDXgAo89iwndeeC4R0wJs= +github.com/atridadl/bunrouter.middleware v0.2.0/go.mod h1:ranjgPw1Y8Rds6sV5ZducCligVzhVukraOuVrD7EVBE= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= @@ -69,12 +71,8 @@ github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= diff --git a/main.go b/main.go index 4451bdb..8e38030 100644 --- a/main.go +++ b/main.go @@ -7,9 +7,9 @@ import ( "text/template" "goth.stack/api" - "goth.stack/middleware" "goth.stack/pages" + bunroutermiddleware "github.com/atridadl/bunrouter.middleware" "github.com/joho/godotenv" "github.com/uptrace/bunrouter" "github.com/uptrace/bunrouter/extra/reqlog" @@ -30,7 +30,7 @@ func main() { // Initialize router router := bunrouter.New( - bunrouter.Use(reqlog.NewMiddleware(), middleware.RequestID, middleware.SecureHeaders), + bunrouter.Use(reqlog.NewMiddleware(), bunroutermiddleware.RequestID, bunroutermiddleware.SecureHeaders), ) // Static server @@ -42,7 +42,7 @@ func main() { }) // Page routes - pageGroup := router.NewGroup("", bunrouter.Use(middleware.NewRateLimiter(50).RateLimit)) + pageGroup := router.NewGroup("", bunrouter.Use(bunroutermiddleware.NewRateLimiter(50).RateLimit)) pageGroup.GET("/", pages.Home) pageGroup.GET("/blog", pages.Blog) pageGroup.GET("/post/:post", pages.Post) diff --git a/middleware/ratelimit.go b/middleware/ratelimit.go deleted file mode 100644 index 7e4a25d..0000000 --- a/middleware/ratelimit.go +++ /dev/null @@ -1,60 +0,0 @@ -package middleware - -import ( - "net" - "net/http" - "sync" - "time" - - "github.com/uptrace/bunrouter" -) - -type rateLimiter struct { - visitors map[string]*visitor - mu sync.Mutex - rps int -} - -type visitor struct { - firstSeen time.Time - requests int -} - -func NewRateLimiter(rps int) *rateLimiter { - return &rateLimiter{ - visitors: make(map[string]*visitor), - rps: rps, - } -} - -func (rl *rateLimiter) RateLimit(next bunrouter.HandlerFunc) bunrouter.HandlerFunc { - return func(w http.ResponseWriter, req bunrouter.Request) error { - rl.mu.Lock() - defer rl.mu.Unlock() - - ip, _, err := net.SplitHostPort(req.RemoteAddr) - if err != nil { - // handle error, e.g., return an HTTP 500 error - http.Error(w, "Internal server error", http.StatusInternalServerError) - return nil - } - - v, exists := rl.visitors[ip] - if !exists || time.Since(v.firstSeen) > 1*time.Minute { - v = &visitor{ - firstSeen: time.Now(), - } - rl.visitors[ip] = v - } - - v.requests++ - - // Limit each IP to rps requests per minute - if v.requests > rl.rps { - http.Error(w, "Too many requests", http.StatusTooManyRequests) - return nil - } - - return next(w, req) - } -} diff --git a/middleware/requestid.go b/middleware/requestid.go deleted file mode 100644 index 30ce060..0000000 --- a/middleware/requestid.go +++ /dev/null @@ -1,41 +0,0 @@ -package middleware - -import ( - "context" - "net/http" - - "github.com/google/uuid" - "github.com/uptrace/bunrouter" -) - -type contextKey string - -func (c contextKey) String() string { - return string(c) -} - -var ( - HeaderXRequestID = "X-Request-ID" - requestIDKey = contextKey("requestID") -) - -func RequestID(next bunrouter.HandlerFunc) bunrouter.HandlerFunc { - return func(w http.ResponseWriter, req bunrouter.Request) error { - reqID := req.Header.Get(HeaderXRequestID) - if reqID == "" { - reqID = uuid.New().String() - } - - ctx := context.WithValue(req.Context(), requestIDKey, reqID) - - w.Header().Set(HeaderXRequestID, reqID) - return next(w, req.WithContext(ctx)) - } -} - -func GetRequestID(ctx context.Context) string { - if reqID, ok := ctx.Value(requestIDKey).(string); ok { - return reqID - } - return "" -} diff --git a/middleware/secure.go b/middleware/secure.go deleted file mode 100644 index fe97e05..0000000 --- a/middleware/secure.go +++ /dev/null @@ -1,21 +0,0 @@ -package middleware - -import ( - "net/http" - - "github.com/unrolled/secure" - "github.com/uptrace/bunrouter" -) - -func SecureHeaders(next bunrouter.HandlerFunc) bunrouter.HandlerFunc { - secureMiddleware := secure.New(secure.Options{ - FrameDeny: true, - ContentTypeNosniff: true, - BrowserXssFilter: true, - }) - - return func(w http.ResponseWriter, req bunrouter.Request) error { - secureMiddleware.HandlerFuncWithNext(w, req.Request, nil) - return next(w, req) - } -}