From bdeb04b0914c2d1cafd85b0d73b54315d2e29369 Mon Sep 17 00:00:00 2001 From: 01JAMIL Date: Mon, 7 Sep 2026 20:37:00 +0100 Subject: [PATCH 1/2] feat: configure CORS middleware --- cmd/api/routes.go | 2 + internal/middleware/cors.go | 77 +++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 internal/middleware/cors.go diff --git a/cmd/api/routes.go b/cmd/api/routes.go index b6b852b..5a0a371 100644 --- a/cmd/api/routes.go +++ b/cmd/api/routes.go @@ -7,6 +7,7 @@ import ( "gin-api-1/internal/email" "gin-api-1/internal/integrations" "gin-api-1/internal/messages" + "gin-api-1/internal/middleware" "gin-api-1/internal/payment" "gin-api-1/internal/projects" "gin-api-1/internal/subscriptions" @@ -21,6 +22,7 @@ import ( func (app *application) routes() http.Handler { r := gin.Default() + r.Use(middleware.CORS()) emailService := email.NewEmailService(app.resend) paymentService := payment.NewStripeService(app.stripe, repo.New(app.db)) diff --git a/internal/middleware/cors.go b/internal/middleware/cors.go new file mode 100644 index 0000000..9aa0ddb --- /dev/null +++ b/internal/middleware/cors.go @@ -0,0 +1,77 @@ +package middleware + +import ( + "net/http" + "strings" + + "gin-api-1/internal/env" + + "github.com/gin-gonic/gin" +) + +const ( + allowCredentialsValue = "true" + allowedMethodsValue = "GET, POST, PATCH, PUT, DELETE, OPTIONS" + allowedHeadersValue = "Authorization, Content-Type, X-Requested-With" + exposedHeadersValue = "Content-Length" + maxAgeValue = "86400" +) + +func allowedOrigins() []string { + origins := env.GetEnvString("CORS_ALLOWED_ORIGINS", "") + if origins == "" { + return []string{ + "http://localhost:3000", + "http://localhost:3700", + "http://127.0.0.1:3000", + "http://127.0.0.1:3700", + } + } + + var result []string + for _, origin := range strings.Split(origins, ",") { + if trimmed := strings.TrimSpace(origin); trimmed != "" { + result = append(result, trimmed) + } + } + return result +} + +func CORS() gin.HandlerFunc { + allowed := allowedOrigins() + + return func(c *gin.Context) { + origin := c.GetHeader("Origin") + if origin == "" { + c.Next() + return + } + + allowedOrigin := "" + for _, o := range allowed { + if o == origin { + allowedOrigin = o + break + } + } + + if allowedOrigin == "" { + c.Next() + return + } + + c.Header("Access-Control-Allow-Origin", allowedOrigin) + c.Header("Access-Control-Allow-Methods", allowedMethodsValue) + c.Header("Access-Control-Allow-Headers", allowedHeadersValue) + c.Header("Access-Control-Allow-Credentials", allowCredentialsValue) + c.Header("Access-Control-Expose-Headers", exposedHeadersValue) + + if c.Request.Method == http.MethodOptions { + c.Header("Access-Control-Max-Age", maxAgeValue) + c.AbortWithStatus(http.StatusNoContent) + return + } + + c.Next() + } +} \ No newline at end of file From 28b8e82ccab302f3ea798b20c5e1616fddd5a9b3 Mon Sep 17 00:00:00 2001 From: 01JAMIL Date: Mon, 7 Sep 2026 20:42:43 +0100 Subject: [PATCH 2/2] fix: add missing newline at end of file in cors.go --- internal/middleware/cors.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/middleware/cors.go b/internal/middleware/cors.go index 9aa0ddb..9e89acd 100644 --- a/internal/middleware/cors.go +++ b/internal/middleware/cors.go @@ -74,4 +74,4 @@ func CORS() gin.HandlerFunc { c.Next() } -} \ No newline at end of file +}