Browse Source

address comments

pull/6987/head
chrislu 3 months ago
parent
commit
d2184282d7
  1. 13
      weed/s3api/cors/cors.go
  2. 2
      weed/s3api/s3api_bucket_config.go
  3. 76
      weed/s3api/s3api_server.go

13
weed/s3api/cors/cors.go

@ -14,6 +14,9 @@ import (
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
)
// S3 metadata file name constant to avoid typos and reduce duplication
const S3MetadataFileName = ".s3metadata"
// CORSRule represents a single CORS rule
type CORSRule struct {
ID string `xml:"ID,omitempty" json:"ID,omitempty"`
@ -429,7 +432,7 @@ func NewStorage(filerClient FilerClient, entryGetter EntryGetter, bucketsPath st
// Store stores CORS configuration in the filer
func (s *Storage) Store(bucket string, config *CORSConfiguration) error {
// Store in bucket metadata
bucketMetadataPath := fmt.Sprintf("%s/%s/.s3metadata", s.bucketsPath, bucket)
bucketMetadataPath := fmt.Sprintf("%s/%s/%s", s.bucketsPath, bucket, S3MetadataFileName)
// Get existing metadata
existingEntry, err := s.entryGetter.GetEntry("", bucketMetadataPath)
@ -456,7 +459,7 @@ func (s *Storage) Store(bucket string, config *CORSConfiguration) error {
request := &filer_pb.CreateEntryRequest{
Directory: s.bucketsPath + "/" + bucket,
Entry: &filer_pb.Entry{
Name: ".s3metadata",
Name: S3MetadataFileName,
IsDirectory: false,
Attributes: &filer_pb.FuseAttributes{
Crtime: time.Now().Unix(),
@ -474,7 +477,7 @@ func (s *Storage) Store(bucket string, config *CORSConfiguration) error {
// Load loads CORS configuration from the filer
func (s *Storage) Load(bucket string) (*CORSConfiguration, error) {
bucketMetadataPath := fmt.Sprintf("%s/%s/.s3metadata", s.bucketsPath, bucket)
bucketMetadataPath := fmt.Sprintf("%s/%s/%s", s.bucketsPath, bucket, S3MetadataFileName)
entry, err := s.entryGetter.GetEntry("", bucketMetadataPath)
if err != nil || entry == nil {
@ -511,7 +514,7 @@ func (s *Storage) Load(bucket string) (*CORSConfiguration, error) {
// Delete deletes CORS configuration from the filer
func (s *Storage) Delete(bucket string) error {
bucketMetadataPath := fmt.Sprintf("%s/%s/.s3metadata", s.bucketsPath, bucket)
bucketMetadataPath := fmt.Sprintf("%s/%s/%s", s.bucketsPath, bucket, S3MetadataFileName)
entry, err := s.entryGetter.GetEntry("", bucketMetadataPath)
if err != nil || entry == nil {
@ -540,7 +543,7 @@ func (s *Storage) Delete(bucket string) error {
request := &filer_pb.CreateEntryRequest{
Directory: s.bucketsPath + "/" + bucket,
Entry: &filer_pb.Entry{
Name: ".s3metadata",
Name: S3MetadataFileName,
IsDirectory: false,
Attributes: &filer_pb.FuseAttributes{
Crtime: time.Now().Unix(),

2
weed/s3api/s3api_bucket_config.go

@ -269,7 +269,7 @@ func (s3a *S3ApiServer) loadCORSFromMetadata(bucket string) (*cors.CORSConfigura
return nil, fmt.Errorf("invalid bucket name: %s", bucket)
}
bucketMetadataPath := fmt.Sprintf("%s/%s/.s3metadata", s3a.option.BucketsPath, bucket)
bucketMetadataPath := fmt.Sprintf("%s/%s/%s", s3a.option.BucketsPath, bucket, cors.S3MetadataFileName)
entry, err := s3a.getEntry("", bucketMetadataPath)
if err != nil || entry == nil {

76
weed/s3api/s3api_server.go

@ -129,43 +129,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)
// Global OPTIONS handler for service-level requests (non-bucket requests)
// This handles requests like OPTIONS /, OPTIONS /status, OPTIONS /healthz
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, skip
return
}
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, ",")
@ -349,6 +312,45 @@ 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
}
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)
})
// ListBuckets
apiRouter.Methods(http.MethodGet).Path("/").HandlerFunc(track(s3a.ListBucketsHandler, "LIST"))

Loading…
Cancel
Save