Merge pull request #2324 from mu-adnan/fix/post-object-default-content-type

fix: apply default Content-Type in POSTObject
This commit is contained in:
Ben McClelland
2026-08-31 09:57:09 -07:00
committed by GitHub
4 changed files with 108 additions and 0 deletions
+3
View File
@@ -118,6 +118,9 @@ func (c S3ApiController) POSTObject(ctx fiber.Ctx) (*Response, error) {
parsed := utils.ContextKeyObjectPostResult.Get(ctx).(middlewares.PostObjectResult)
bucket := ctx.Params("bucket")
contentType := parsed.Fields["content-type"]
if contentType == "" {
contentType = defaultContentType
}
contentEncoding := parsed.Fields["content-encoding"]
contentDisposition := parsed.Fields["content-disposition"]
contentLanguage := parsed.Fields["content-language"]
+45
View File
@@ -620,6 +620,47 @@ func TestS3ApiController_POSTObject(t *testing.T) {
},
},
},
{
name: "default content type when field is omitted",
input: testInput{
beRes: s3response.PutObjectOutput{
ETag: "etag-123",
},
locals: postObjectLocalsForTest(middlewares.PostObjectResult{
Fields: baseFields,
FileRdr: newMockFileReader("payload"),
ContentLength: int64(len("payload")),
}),
},
output: testOutput{
response: &Response{
Headers: map[string]*string{
"Etag": utils.GetStringPtr("etag-123"),
"Location": &location,
"x-amz-checksum-crc32": nil,
"x-amz-checksum-crc32c": nil,
"x-amz-checksum-crc64nvme": nil,
"x-amz-checksum-sha1": nil,
"x-amz-checksum-sha256": nil,
"x-amz-checksum-sha512": nil,
"x-amz-checksum-md5": nil,
"x-amz-checksum-xxhash64": nil,
"x-amz-checksum-xxhash3": nil,
"x-amz-checksum-xxhash128": nil,
"x-amz-checksum-type": nil,
"x-amz-version-id": nil,
},
MetaOpts: &MetaOptions{
BucketOwner: "root",
ContentLength: int64(len("payload")),
ObjectETag: utils.GetStringPtr("etag-123"),
ObjectSize: int64(len("payload")),
EventName: s3event.EventObjectCreatedPost,
Status: http.StatusNoContent,
},
},
},
},
{
name: "anonymous upload with policy is evaluated",
input: testInput{
@@ -665,6 +706,10 @@ func TestS3ApiController_POSTObject(t *testing.T) {
assert.Equal(t, "anon-payload", string(body))
}
if tt.name == "default content type when field is omitted" {
assert.Equal(t, defaultContentType, *putObjectInput.ContentType)
}
if tt.name == "successful created response" {
assert.Equal(t, "bucket", *putObjectInput.Bucket)
assert.Equal(t, "uploads/photo.jpg", *putObjectInput.Key)
+58
View File
@@ -976,6 +976,64 @@ func PostObject_success_with_meta_properties(s *S3Conf) error {
})
}
func PostObject_default_content_type(s *S3Conf) error {
testName := "PostObject_default_content_type"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
for _, tt := range []struct {
key string
policyConditions []any
extraFields map[string]string
}{
{
key: "omitted-content-type",
},
{
key: "empty-content-type",
policyConditions: []any{
[]any{"starts-with", "$Content-Type", ""},
},
extraFields: map[string]string{
"Content-Type": "",
},
},
} {
resp, err := sendPostObject(PostRequestConfig{
bucket: bucket,
key: tt.key,
s3Conf: s,
fileContent: []byte("dummy data"),
policyConditions: tt.policyConditions,
extraFields: tt.extraFields,
})
if err != nil {
return err
}
if resp.StatusCode != http.StatusNoContent {
return fmt.Errorf("%s: expected status code to be 204, instead got %d",
tt.key, resp.StatusCode)
}
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
out, err := s3client.HeadObject(ctx, &s3.HeadObjectInput{
Bucket: &bucket,
Key: &tt.key,
})
cancel()
if err != nil {
return err
}
if getString(out.ContentType) != defaultContentType {
return fmt.Errorf("%s: expected default %s Content-Type, instead got %s",
tt.key, defaultContentType, getString(out.ContentType))
}
}
return nil
})
}
func PostObject_invalid_website_redirect_location(s *S3Conf) error {
testName := "PostObject_invalid_website_redirect_location"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
+2
View File
@@ -2033,6 +2033,7 @@ func TestPostObject(ts *TestState) {
ts.Run(PostObject_success_status_201)
ts.Run(PostObject_should_ignore_anything_after_file)
ts.Run(PostObject_success_with_meta_properties)
ts.Run(PostObject_default_content_type)
ts.Run(PostObject_invalid_website_redirect_location)
ts.Run(PostObject_invalid_tagging)
ts.Run(PostObject_success_with_tagging)
@@ -3494,6 +3495,7 @@ func GetIntTests() IntTests {
"PostObject_success_status_201": PostObject_success_status_201,
"PostObject_should_ignore_anything_after_file": PostObject_should_ignore_anything_after_file,
"PostObject_success_with_meta_properties": PostObject_success_with_meta_properties,
"PostObject_default_content_type": PostObject_default_content_type,
"PostObject_invalid_website_redirect_location": PostObject_invalid_website_redirect_location,
"PostObject_invalid_tagging": PostObject_invalid_tagging,
"PostObject_success_with_tagging": PostObject_success_with_tagging,