diff options
-rw-r--r-- | .rr.yaml | 9 | ||||
-rw-r--r-- | service/http/config.go | 13 | ||||
-rw-r--r-- | service/http/service.go | 45 |
3 files changed, 65 insertions, 2 deletions
@@ -30,13 +30,18 @@ http: # HTTP service provides built-in middlewares middlewares: + # Middleware to handle CORS requests + cors: + AllowedOrigin: "*" + allowedHeaders: "*" + allowedMethods: "GET,POST,PUT,DELETE" + allowCredentials: true + maxAge: 600 # Middleware that adding Headers to the Request / Response headers: customRequestHeaders: "Example-Request-Header": "Value" customResponseHeaders: - "Access-Control-Allow-Origin": "*" - "Access-Control-Allow-Headers": "GET,POST,PUT,DELETE" "X-Powered-By": "RoadRunner" # HTTP service provides FastCGI as frontend diff --git a/service/http/config.go b/service/http/config.go index 2b8cf049..2897d1f7 100644 --- a/service/http/config.go +++ b/service/http/config.go @@ -42,6 +42,15 @@ type Config struct { type MiddlewaresConfig struct { Headers *HeaderMiddlewareConfig + CORS *CORSMiddlewareConfig +} + +type CORSMiddlewareConfig struct { + AllowedOrigin string + AllowedMethods string + AllowedHeaders string + AllowCredentials *bool + MaxAge int } type HeaderMiddlewareConfig struct { @@ -49,6 +58,10 @@ type HeaderMiddlewareConfig struct { CustomResponseHeaders map[string]string } +func (c *MiddlewaresConfig) EnableCORS() bool { + return c.CORS != nil +} + func (c *MiddlewaresConfig) EnableHeaders() bool { return c.Headers.CustomRequestHeaders != nil || c.Headers.CustomResponseHeaders != nil } diff --git a/service/http/service.go b/service/http/service.go index 59e7dd5a..3d9f196e 100644 --- a/service/http/service.go +++ b/service/http/service.go @@ -12,6 +12,7 @@ import ( "net/http" "net/http/fcgi" "net/url" + "strconv" "strings" "sync" ) @@ -271,10 +272,54 @@ func (s *Service) headersMiddleware(f http.HandlerFunc) http.HandlerFunc { } } +func handlePreflight(w http.ResponseWriter, r *http.Request, options *CORSMiddlewareConfig) { + headers := w.Header() + + headers.Add("Vary", "Origin") + headers.Add("Vary", "Access-Control-Request-Method") + headers.Add("Vary", "Access-Control-Request-Headers") + + if options.AllowedOrigin != "" { + headers.Set("Access-Control-Allow-Origin", options.AllowedOrigin) + } + + if options.AllowedHeaders != "" { + headers.Set("Access-Control-Allow-Headers", options.AllowedHeaders) + } + + if options.AllowedMethods != "" { + headers.Set("Access-Control-Allow-Methods", options.AllowedMethods) + } + + if options.AllowCredentials != nil { + headers.Set("Access-Control-Allow-Credentials", strconv.FormatBool(*options.AllowCredentials)) + } + + if options.MaxAge > 0 { + headers.Set("Access-Control-Max-Age", strconv.Itoa(options.MaxAge)) + } +} + +func (s *Service) corsMiddleware(f http.HandlerFunc) http.HandlerFunc { + // Define the http.HandlerFunc + return func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodOptions { + handlePreflight(w, r, s.cfg.Middlewares.CORS) + w.WriteHeader(http.StatusOK); + } else { + f(w, r) + } + } +} + func (s *Service) initMiddlewares() error { if s.cfg.Middlewares.EnableHeaders() { s.AddMiddleware(s.headersMiddleware) } + if s.cfg.Middlewares.EnableCORS() { + s.AddMiddleware(s.corsMiddleware) + } + return nil } |