diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index f8f6baacc..ede9c9643 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -429,9 +429,8 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h } } - // Save metadata. - metadata := make(map[string]string) - // Nothing to store right now. + // Extract metadata to be saved from received Form. + metadata := extractMetadataFromForm(formValues) sha256sum := "" diff --git a/cmd/handler-utils.go b/cmd/handler-utils.go index a087e1b40..4fc0083f9 100644 --- a/cmd/handler-utils.go +++ b/cmd/handler-utils.go @@ -92,6 +92,32 @@ func extractMetadataFromHeader(header http.Header) map[string]string { return metadata } +// extractMetadataFromForm extracts metadata from Post Form. +func extractMetadataFromForm(formValues map[string]string) map[string]string { + metadata := make(map[string]string) + // Save standard supported headers. + for _, supportedHeader := range supportedHeaders { + canonicalHeader := http.CanonicalHeaderKey(supportedHeader) + // Form field names are case insensitive, look for both canonical + // and non canonical entries. + if _, ok := formValues[canonicalHeader]; ok { + metadata[supportedHeader] = formValues[canonicalHeader] + } else if _, ok := formValues[supportedHeader]; ok { + metadata[supportedHeader] = formValues[canonicalHeader] + } + } + // Go through all other form values for any additional headers that needs to be saved. + for key := range formValues { + cKey := http.CanonicalHeaderKey(key) + if strings.HasPrefix(cKey, "X-Amz-Meta-") { + metadata[cKey] = formValues[key] + } else if strings.HasPrefix(cKey, "X-Minio-Meta-") { + metadata[cKey] = formValues[key] + } + } + return metadata +} + // Extract form fields and file data from a HTTP POST Policy func extractPostPolicyFormValues(reader *multipart.Reader) (filePart io.Reader, fileName string, formValues map[string]string, err error) { /// HTML Form values diff --git a/cmd/post-policy_test.go b/cmd/post-policy_test.go index 456302b62..2453d224c 100644 --- a/cmd/post-policy_test.go +++ b/cmd/post-policy_test.go @@ -178,6 +178,7 @@ func testPostPolicyBucketHandler(obj ObjectLayer, instanceType string, t TestErr testCasesV4 := []struct { objectName string data []byte + expectedHeaders map[string]string expectedRespStatus int accessKey string secretKey string @@ -188,6 +189,7 @@ func testPostPolicyBucketHandler(obj ObjectLayer, instanceType string, t TestErr objectName: "test", data: []byte("Hello, World"), expectedRespStatus: http.StatusNoContent, + expectedHeaders: map[string]string{"X-Amz-Meta-Uuid": "1234"}, accessKey: credentials.AccessKeyID, secretKey: credentials.SecretAccessKey, malformedBody: false, @@ -229,6 +231,18 @@ func testPostPolicyBucketHandler(obj ObjectLayer, instanceType string, t TestErr if rec.Code != testCase.expectedRespStatus { t.Errorf("Test %d: %s: Expected the response status to be `%d`, but instead found `%d`", i+1, instanceType, testCase.expectedRespStatus, rec.Code) } + // When the operation is successful, check if sending metadata is successful too + if rec.Code == http.StatusNoContent { + objInfo, err := obj.GetObjectInfo(bucketName, testCase.objectName+"/upload.txt") + if err != nil { + t.Error("Unexpected error: ", err) + } + for k, v := range testCase.expectedHeaders { + if objInfo.UserDefined[k] != v { + t.Errorf("Expected to have header %s with value %s, but found value `%s` instead", k, v, objInfo.UserDefined[k]) + } + } + } } // Test cases for signature-V4. @@ -475,6 +489,8 @@ func newPostRequestV4Generic(endPoint, bucketName, objectName string, objData [] "x-amz-signature": signature, "x-amz-date": t.Format(iso8601DateFormat), "x-amz-algorithm": "AWS4-HMAC-SHA256", + "x-amz-meta-uuid": "1234", + "Content-Encoding": "gzip", } // Create the multipart form.