diff --git a/weed/s3api/s3api_bucket_handlers.go b/weed/s3api/s3api_bucket_handlers.go index f1197c60e0..9991d0ba99 100644 --- a/weed/s3api/s3api_bucket_handlers.go +++ b/weed/s3api/s3api_bucket_handlers.go @@ -224,6 +224,15 @@ func (s3a *S3ApiServer) PutBucketHandler(w http.ResponseWriter, r *http.Request) // collect parameters bucket, _ := s3_constants.GetBucketAndObject(r) + // Only bucket-level PUTs with a registered sub-resource route land in a + // dedicated handler; anything else that reaches here is an operation we do + // not implement, not a bare CreateBucket. + if subresource, found := unroutedSubresource(r, nil); found { + glog.V(1).Infof("unimplemented bucket PUT subresource ?%s", subresource) + s3err.WriteErrorResponse(w, r, s3err.ErrNotImplemented) + return + } + // validate the bucket name err := s3bucket.VerifyS3BucketName(bucket) if err != nil { diff --git a/weed/s3api/s3api_bucket_handlers_misc.go b/weed/s3api/s3api_bucket_handlers_misc.go index e608527648..798257a8e1 100644 --- a/weed/s3api/s3api_bucket_handlers_misc.go +++ b/weed/s3api/s3api_bucket_handlers_misc.go @@ -185,11 +185,20 @@ var listObjectsQueryParams = map[string]bool{ // catch-all, so anything left is a subresource it does not implement - and answering // it with a bucket listing is worse than saying so. func unroutedBucketSubresource(r *http.Request) (string, bool) { + return unroutedSubresource(r, listObjectsQueryParams) +} + +// unroutedSubresource names a query key that no route claimed, outside the +// request's own parameters, SigV2 presign keys, and SigV4 presign keys +// (all "X-Amz-" prefixed). +func unroutedSubresource(r *http.Request, allowed map[string]bool) (string, bool) { for key := range r.URL.Query() { - if listObjectsQueryParams[key] || strings.HasPrefix(key, "X-Amz-") { - continue + switch { + case allowed[key], strings.HasPrefix(key, "X-Amz-"): + case key == "x-id", key == "AWSAccessKeyId", key == "Signature", key == "Expires": + default: + return key, true } - return key, true } return "", false }