Browse Source

weed/s3api: added new bucket handlers for more compatibility with AWS S3

Protocol

Otherwise any requests to the underlying handlers results in calls to
ListObjects (v1) that may intensively load gateway and volume servers.

Added the following handlers with default responses:
- GetBucketLocation
- GetBucketRequestPayment

Added the following handlers with NotFound and NotImplemented responses:
- PutBucketAcl
- GetBucketPolicy
- PutBucketPolicy
- DeleteBucketPolicy
- GetBucketCors
- PutBucketCors
- DeleteBucketCors
pull/2631/head
zerospiel 3 years ago
parent
commit
b54a65ba5a
  1. 19
      weed/s3api/s3api_bucket_handlers.go
  2. 49
      weed/s3api/s3api_bucket_skip_handlers.go
  3. 44
      weed/s3api/s3api_server.go
  4. 4
      weed/s3api/s3api_xsd_generated.go
  5. 1
      weed/s3api/s3err/s3-error.go
  6. 12
      weed/s3api/s3err/s3api_errors.go

19
weed/s3api/s3api_bucket_handlers.go

@ -4,13 +4,14 @@ import (
"context" "context"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"github.com/chrislusf/seaweedfs/weed/filer"
"github.com/chrislusf/seaweedfs/weed/s3api/s3_constants"
"github.com/chrislusf/seaweedfs/weed/storage/needle"
"math" "math"
"net/http" "net/http"
"time" "time"
"github.com/chrislusf/seaweedfs/weed/filer"
"github.com/chrislusf/seaweedfs/weed/s3api/s3_constants"
"github.com/chrislusf/seaweedfs/weed/storage/needle"
xhttp "github.com/chrislusf/seaweedfs/weed/s3api/http" xhttp "github.com/chrislusf/seaweedfs/weed/s3api/http"
"github.com/chrislusf/seaweedfs/weed/s3api/s3err" "github.com/chrislusf/seaweedfs/weed/s3api/s3err"
@ -309,3 +310,15 @@ func (s3a *S3ApiServer) DeleteBucketLifecycleHandler(w http.ResponseWriter, r *h
s3err.WriteEmptyResponse(w, r, http.StatusNoContent) s3err.WriteEmptyResponse(w, r, http.StatusNoContent)
} }
// GetBucketLocationHandler Get bucket location
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html
func (s3a *S3ApiServer) GetBucketLocationHandler(w http.ResponseWriter, r *http.Request) {
writeSuccessResponseXML(w, r, LocationConstraint{})
}
// GetBucketRequestPaymentHandler Get bucket location
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketRequestPayment.html
func (s3a *S3ApiServer) GetBucketRequestPaymentHandler(w http.ResponseWriter, r *http.Request) {
writeSuccessResponseXML(w, r, RequestPaymentConfiguration{Payer: "BucketOwner"})
}

49
weed/s3api/s3api_bucket_skip_handlers.go

@ -0,0 +1,49 @@
package s3api
import (
"net/http"
"github.com/chrislusf/seaweedfs/weed/s3api/s3err"
)
// GetBucketCorsHandler Get bucket CORS
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketCors.html
func (s3a *S3ApiServer) GetBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
s3err.WriteErrorResponse(w, r, s3err.ErrNoSuchCORSConfiguration)
}
// PutBucketCorsHandler Put bucket CORS
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketCors.html
func (s3a *S3ApiServer) PutBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
s3err.WriteErrorResponse(w, r, s3err.ErrNotImplemented)
}
// DeleteBucketCorsHandler Delete bucket CORS
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketCors.html
func (s3a *S3ApiServer) DeleteBucketCorsHandler(w http.ResponseWriter, r *http.Request) {
s3err.WriteErrorResponse(w, r, http.StatusNoContent)
}
// GetBucketPolicyHandler Get bucket Policy
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicy.html
func (s3a *S3ApiServer) GetBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
s3err.WriteErrorResponse(w, r, s3err.ErrNoSuchBucketPolicy)
}
// PutBucketPolicyHandler Put bucket Policy
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketPolicy.html
func (s3a *S3ApiServer) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
s3err.WriteErrorResponse(w, r, s3err.ErrNotImplemented)
}
// DeleteBucketPolicyHandler Delete bucket Policy
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketPolicy.html
func (s3a *S3ApiServer) DeleteBucketPolicyHandler(w http.ResponseWriter, r *http.Request) {
s3err.WriteErrorResponse(w, r, http.StatusNoContent)
}
// PutBucketAclHandler Put bucket ACL
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAcl.html
func (s3a *S3ApiServer) PutBucketAclHandler(w http.ResponseWriter, r *http.Request) {
s3err.WriteErrorResponse(w, r, s3err.ErrNotImplemented)
}

44
weed/s3api/s3api_server.go

@ -2,16 +2,16 @@ package s3api
import ( import (
"fmt" "fmt"
"github.com/chrislusf/seaweedfs/weed/pb"
"github.com/chrislusf/seaweedfs/weed/security"
"github.com/chrislusf/seaweedfs/weed/util"
"net/http" "net/http"
"strings" "strings"
"time" "time"
"github.com/chrislusf/seaweedfs/weed/filer" "github.com/chrislusf/seaweedfs/weed/filer"
"github.com/chrislusf/seaweedfs/weed/pb"
. "github.com/chrislusf/seaweedfs/weed/s3api/s3_constants" . "github.com/chrislusf/seaweedfs/weed/s3api/s3_constants"
"github.com/chrislusf/seaweedfs/weed/s3api/s3err" "github.com/chrislusf/seaweedfs/weed/s3api/s3err"
"github.com/chrislusf/seaweedfs/weed/security"
"github.com/chrislusf/seaweedfs/weed/util"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
@ -134,6 +134,28 @@ func (s3a *S3ApiServer) registerRouter(router *mux.Router) {
// GetBucketACL // GetBucketACL
bucket.Methods("GET").HandlerFunc(s3a.iam.Auth(s3a.GetBucketAclHandler, ACTION_READ)).Queries("acl", "") bucket.Methods("GET").HandlerFunc(s3a.iam.Auth(s3a.GetBucketAclHandler, ACTION_READ)).Queries("acl", "")
// PutBucketACL
bucket.Methods("PUT").HandlerFunc(s3a.iam.Auth(s3a.PutBucketAclHandler, ACTION_WRITE)).Queries("acl", "")
// GetBucketPolicy
bucket.Methods("GET").HandlerFunc(s3a.iam.Auth(s3a.GetBucketPolicyHandler, ACTION_READ)).Queries("policy", "")
// PutBucketPolicy
bucket.Methods("PUT").HandlerFunc(s3a.iam.Auth(s3a.PutBucketPolicyHandler, ACTION_WRITE)).Queries("policy", "")
// DeleteBucketPolicy
bucket.Methods("DELETE").HandlerFunc(s3a.iam.Auth(s3a.DeleteBucketPolicyHandler, ACTION_WRITE)).Queries("policy", "")
// GetBucketCors
bucket.Methods("GET").HandlerFunc(s3a.iam.Auth(s3a.GetBucketCorsHandler, ACTION_READ)).Queries("cors", "")
// PutBucketCors
bucket.Methods("PUT").HandlerFunc(s3a.iam.Auth(s3a.PutBucketCorsHandler, ACTION_WRITE)).Queries("cors", "")
// DeleteBucketCors
bucket.Methods("DELETE").HandlerFunc(s3a.iam.Auth(s3a.DeleteBucketCorsHandler, ACTION_WRITE)).Queries("cors", "")
// GetBucketLocation
bucket.Methods("GET").HandlerFunc(s3a.iam.Auth(s3a.GetBucketLocationHandler, ACTION_READ)).Queries("location", "")
// GetBucketRequestPayment
bucket.Methods("GET").HandlerFunc(s3a.iam.Auth(s3a.GetBucketRequestPaymentHandler, ACTION_READ)).Queries("requestPayment", "")
// GetObjectACL // GetObjectACL
bucket.Methods("GET").Path("/{object:.+}").HandlerFunc(s3a.iam.Auth(s3a.GetObjectAclHandler, ACTION_READ)).Queries("acl", "") bucket.Methods("GET").Path("/{object:.+}").HandlerFunc(s3a.iam.Auth(s3a.GetObjectAclHandler, ACTION_READ)).Queries("acl", "")
@ -154,22 +176,6 @@ func (s3a *S3ApiServer) registerRouter(router *mux.Router) {
// DeleteBucket // DeleteBucket
bucket.Methods("DELETE").HandlerFunc(track(s3a.iam.Auth(s3a.DeleteBucketHandler, ACTION_WRITE), "DELETE")) bucket.Methods("DELETE").HandlerFunc(track(s3a.iam.Auth(s3a.DeleteBucketHandler, ACTION_WRITE), "DELETE"))
/*
// not implemented
// GetBucketLocation
bucket.Methods("GET").HandlerFunc(s3a.GetBucketLocationHandler).Queries("location", "")
// GetBucketPolicy
bucket.Methods("GET").HandlerFunc(s3a.GetBucketPolicyHandler).Queries("policy", "")
// GetObjectACL
bucket.Methods("GET").Path("/{object:.+}").HandlerFunc(s3a.GetObjectACLHandler).Queries("acl", "")
// PutBucketPolicy
bucket.Methods("PUT").HandlerFunc(s3a.PutBucketPolicyHandler).Queries("policy", "")
// DeleteBucketPolicy
bucket.Methods("DELETE").HandlerFunc(s3a.DeleteBucketPolicyHandler).Queries("policy", "")
*/
} }
// ListBuckets // ListBuckets

4
weed/s3api/s3api_xsd_generated.go

@ -646,6 +646,10 @@ type ListVersionsResult struct {
CommonPrefixes []PrefixEntry `xml:"http://s3.amazonaws.com/doc/2006-03-01/ CommonPrefixes,omitempty"` CommonPrefixes []PrefixEntry `xml:"http://s3.amazonaws.com/doc/2006-03-01/ CommonPrefixes,omitempty"`
} }
type LocationConstraint struct {
LocationConstraint string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ LocationConstraint"`
}
type LoggingSettings struct { type LoggingSettings struct {
TargetBucket string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ TargetBucket"` TargetBucket string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ TargetBucket"`
TargetPrefix string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ TargetPrefix"` TargetPrefix string `xml:"http://s3.amazonaws.com/doc/2006-03-01/ TargetPrefix"`

1
weed/s3api/s3err/s3-error.go

@ -58,4 +58,5 @@ var s3ErrorResponseMap = map[string]string{
"InvalidDuration": "Duration provided in the request is invalid.", "InvalidDuration": "Duration provided in the request is invalid.",
"XAmzContentSHA256Mismatch": "The provided 'x-amz-content-sha256' header does not match what was computed.", "XAmzContentSHA256Mismatch": "The provided 'x-amz-content-sha256' header does not match what was computed.",
// Add new API errors here. // Add new API errors here.
"NoSuchCORSConfiguration": "The CORS configuration does not exist",
} }

12
weed/s3api/s3err/s3api_errors.go

@ -51,6 +51,8 @@ const (
ErrBucketAlreadyExists ErrBucketAlreadyExists
ErrBucketAlreadyOwnedByYou ErrBucketAlreadyOwnedByYou
ErrNoSuchBucket ErrNoSuchBucket
ErrNoSuchBucketPolicy
ErrNoSuchCORSConfiguration
ErrNoSuchLifecycleConfiguration ErrNoSuchLifecycleConfiguration
ErrNoSuchKey ErrNoSuchKey
ErrNoSuchUpload ErrNoSuchUpload
@ -164,6 +166,16 @@ var errorCodeResponse = map[ErrorCode]APIError{
Description: "The specified bucket does not exist", Description: "The specified bucket does not exist",
HTTPStatusCode: http.StatusNotFound, HTTPStatusCode: http.StatusNotFound,
}, },
ErrNoSuchBucketPolicy: {
Code: "NoSuchBucketPolicy",
Description: "The bucket policy does not exist",
HTTPStatusCode: http.StatusNotFound,
},
ErrNoSuchCORSConfiguration: {
Code: "NoSuchCORSConfiguration",
Description: "The CORS configuration does not exist",
HTTPStatusCode: http.StatusNotFound,
},
ErrNoSuchLifecycleConfiguration: { ErrNoSuchLifecycleConfiguration: {
Code: "NoSuchLifecycleConfiguration", Code: "NoSuchLifecycleConfiguration",
Description: "The lifecycle configuration does not exist", Description: "The lifecycle configuration does not exist",

Loading…
Cancel
Save