diff --git a/weed/s3api/s3api_object_copy_handlers.go b/weed/s3api/s3api_object_copy_handlers.go index 99a852c0c..7c6d36f20 100644 --- a/weed/s3api/s3api_object_copy_handlers.go +++ b/weed/s3api/s3api_object_copy_handlers.go @@ -1,6 +1,7 @@ package s3api import ( + "crypto/md5" "fmt" "github.com/chrislusf/seaweedfs/weed/s3api/s3err" "net/http" @@ -82,7 +83,7 @@ type CopyPartResult struct { func (s3a *S3ApiServer) CopyObjectPartHandler(w http.ResponseWriter, r *http.Request) { // https://docs.aws.amazon.com/AmazonS3/latest/dev/CopyingObjctsUsingRESTMPUapi.html // https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html - dstBucket, _ := getBucketAndObject(r) + dstBucket, dstObject := getBucketAndObject(r) // Copy source path. cpSrcPath, err := url.QueryUnescape(r.Header.Get("X-Amz-Copy-Source")) @@ -127,11 +128,20 @@ func (s3a *S3ApiServer) CopyObjectPartHandler(w http.ResponseWriter, r *http.Req } defer dataReader.Close() - etag, errCode := s3a.putToFiler(r, dstUrl, dataReader) - - if errCode != s3err.ErrNone { - writeErrorResponse(w, errCode, r.URL) - return + var etag string + if strings.HasSuffix(srcObject, "/") { + if err := s3a.mkdir(s3a.option.BucketsPath, dstBucket+dstObject, nil); err != nil { + writeErrorResponse(w, s3err.ErrInternalError, r.URL) + return + } + etag = fmt.Sprintf("%x", md5.New().Sum(nil)) + } else { + _etag, errCode := s3a.putToFiler(r, dstUrl, dataReader) + etag = _etag + if errCode != s3err.ErrNone { + writeErrorResponse(w, errCode, r.URL) + return + } } setEtag(w, etag) diff --git a/weed/s3api/s3api_object_handlers.go b/weed/s3api/s3api_object_handlers.go index bb03048c8..cb85aa9fe 100644 --- a/weed/s3api/s3api_object_handlers.go +++ b/weed/s3api/s3api_object_handlers.go @@ -112,6 +112,12 @@ func (s3a *S3ApiServer) DeleteObjectHandler(w http.ResponseWriter, r *http.Reque bucket, object := getBucketAndObject(r) + response, _ := s3a.listFilerEntries(bucket, object, 1, "", "/") + if len(response.Contents) != 0 && strings.HasSuffix(r.URL.Path, "/") { + w.WriteHeader(http.StatusNoContent) + return + } + destUrl := fmt.Sprintf("http://%s%s/%s%s?recursive=true", s3a.option.Filer, s3a.option.BucketsPath, bucket, object) @@ -121,7 +127,6 @@ func (s3a *S3ApiServer) DeleteObjectHandler(w http.ResponseWriter, r *http.Reque } w.WriteHeader(http.StatusNoContent) }) - } // / ObjectIdentifier carries key name for the object to delete.