diff options
Diffstat (limited to 'weed/s3api/s3api_server.go')
| -rw-r--r-- | weed/s3api/s3api_server.go | 84 |
1 files changed, 57 insertions, 27 deletions
diff --git a/weed/s3api/s3api_server.go b/weed/s3api/s3api_server.go index 426535fe0..5d113c645 100644 --- a/weed/s3api/s3api_server.go +++ b/weed/s3api/s3api_server.go @@ -121,6 +121,35 @@ func NewS3ApiServerWithStore(router *mux.Router, option *S3ApiServerOption, expl return s3ApiServer, nil } +// handleCORSOriginValidation handles the common CORS origin validation logic +func (s3a *S3ApiServer) handleCORSOriginValidation(w http.ResponseWriter, r *http.Request) bool { + origin := r.Header.Get("Origin") + if origin != "" { + if len(s3a.option.AllowedOrigins) == 0 || s3a.option.AllowedOrigins[0] == "*" { + origin = "*" + } else { + originFound := false + for _, allowedOrigin := range s3a.option.AllowedOrigins { + if origin == allowedOrigin { + originFound = true + break + } + } + if !originFound { + writeFailureResponse(w, r, http.StatusForbidden) + return false + } + } + } + + w.Header().Set("Access-Control-Allow-Origin", origin) + w.Header().Set("Access-Control-Expose-Headers", "*") + w.Header().Set("Access-Control-Allow-Methods", "*") + w.Header().Set("Access-Control-Allow-Headers", "*") + w.Header().Set("Access-Control-Allow-Credentials", "true") + return true +} + func (s3a *S3ApiServer) registerRouter(router *mux.Router) { // API Router apiRouter := router.PathPrefix("/").Subrouter() @@ -129,33 +158,6 @@ func (s3a *S3ApiServer) registerRouter(router *mux.Router) { apiRouter.Methods(http.MethodGet).Path("/status").HandlerFunc(s3a.StatusHandler) apiRouter.Methods(http.MethodGet).Path("/healthz").HandlerFunc(s3a.StatusHandler) - apiRouter.Methods(http.MethodOptions).HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { - origin := r.Header.Get("Origin") - if origin != "" { - if len(s3a.option.AllowedOrigins) == 0 || s3a.option.AllowedOrigins[0] == "*" { - origin = "*" - } else { - originFound := false - for _, allowedOrigin := range s3a.option.AllowedOrigins { - if origin == allowedOrigin { - originFound = true - } - } - if !originFound { - writeFailureResponse(w, r, http.StatusForbidden) - return - } - } - } - - w.Header().Set("Access-Control-Allow-Origin", origin) - w.Header().Set("Access-Control-Expose-Headers", "*") - w.Header().Set("Access-Control-Allow-Methods", "*") - w.Header().Set("Access-Control-Allow-Headers", "*") - writeSuccessResponseEmpty(w, r) - }) - var routers []*mux.Router if s3a.option.DomainName != "" { domainNames := strings.Split(s3a.option.DomainName, ",") @@ -168,7 +170,16 @@ func (s3a *S3ApiServer) registerRouter(router *mux.Router) { } routers = append(routers, apiRouter.PathPrefix("/{bucket}").Subrouter()) + // Get CORS middleware instance with caching + corsMiddleware := s3a.getCORSMiddleware() + for _, bucket := range routers { + // Apply CORS middleware to bucket routers for automatic CORS header handling + bucket.Use(corsMiddleware.Handler) + + // Bucket-specific OPTIONS handler for CORS preflight requests + // Use PathPrefix to catch all bucket-level preflight routes including /bucket/object + bucket.PathPrefix("/").Methods(http.MethodOptions).HandlerFunc(corsMiddleware.HandleOptionsRequest) // each case should follow the next rule: // - requesting object with query must precede any other methods @@ -330,6 +341,25 @@ func (s3a *S3ApiServer) registerRouter(router *mux.Router) { } + // Global OPTIONS handler for service-level requests (non-bucket requests) + // This handles requests like OPTIONS /, OPTIONS /status, OPTIONS /healthz + // Place this after bucket handlers to avoid interfering with bucket CORS middleware + apiRouter.Methods(http.MethodOptions).PathPrefix("/").HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + // Only handle if this is not a bucket-specific request + vars := mux.Vars(r) + bucket := vars["bucket"] + if bucket != "" { + // This is a bucket-specific request, let bucket CORS middleware handle it + http.NotFound(w, r) + return + } + + if s3a.handleCORSOriginValidation(w, r) { + writeSuccessResponseEmpty(w, r) + } + }) + // ListBuckets apiRouter.Methods(http.MethodGet).Path("/").HandlerFunc(track(s3a.ListBucketsHandler, "LIST")) |
