diff --git a/api-router.go b/api-router.go index ec19fd504..81a59567d 100644 --- a/api-router.go +++ b/api-router.go @@ -48,7 +48,7 @@ func registerAPIRouter(mux *router.Router, api objectAPIHandlers) { // GetObject bucket.Methods("GET").Path("/{object:.+}").HandlerFunc(api.GetObjectHandler) // CopyObject - bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/).*?").HandlerFunc(api.CopyObjectHandler) + bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(api.CopyObjectHandler) // PutObject bucket.Methods("PUT").Path("/{object:.+}").HandlerFunc(api.PutObjectHandler) // DeleteObject diff --git a/object-handlers.go b/object-handlers.go index 97b2399b6..5c84b0137 100644 --- a/object-handlers.go +++ b/object-handlers.go @@ -337,11 +337,14 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re } } - // TODO: Reject requests where body/payload is present, for now we - // don't even read it. + // TODO: Reject requests where body/payload is present, for now we don't even read it. // objectSource - objectSource := r.Header.Get("X-Amz-Copy-Source") + objectSource, err := url.QueryUnescape(r.Header.Get("X-Amz-Copy-Source")) + if err != nil { + // Save unescaped string as is. + objectSource = r.Header.Get("X-Amz-Copy-Source") + } // Skip the first element if it is '/', split the rest. if strings.HasPrefix(objectSource, "/") { diff --git a/server_test.go b/server_test.go index ff6f64d6d..82ac6e3f3 100644 --- a/server_test.go +++ b/server_test.go @@ -27,6 +27,7 @@ import ( "io/ioutil" "math/rand" "net/http" + "net/url" "sync" "time" @@ -689,7 +690,7 @@ func (s *TestSuiteCommon) TestCopyObject(c *C) { request, err = newTestRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName2), 0, nil, s.accessKey, s.secretKey) // setting the "X-Amz-Copy-Source" to allow copying the content of previously uploaded object. - request.Header.Set("X-Amz-Copy-Source", "/"+bucketName+"/"+objectName) + request.Header.Set("X-Amz-Copy-Source", url.QueryEscape("/"+bucketName+"/"+objectName)) c.Assert(err, IsNil) // execute the HTTP request. // the content is expected to have the content of previous disk.