diff --git a/fakestorage/object.go b/fakestorage/object.go index 58c9639829..b229a45233 100644 --- a/fakestorage/object.go +++ b/fakestorage/object.go @@ -35,6 +35,7 @@ type ObjectAttrs struct { ContentType string ContentEncoding string ContentDisposition string + CacheControl string // Crc32c checksum of Content. calculated by server when it's upload methods are used. Crc32c string Md5Hash string @@ -396,6 +397,7 @@ func toBackendObjects(objects []StreamingObject) []backend.StreamingObject { ContentType: o.ContentType, ContentEncoding: o.ContentEncoding, ContentDisposition: o.ContentDisposition, + CacheControl: o.CacheControl, ACL: o.ACL, Created: getCurrentIfZero(o.Created).Format(timestampFormat), Deleted: o.Deleted.Format(timestampFormat), @@ -450,6 +452,7 @@ func fromBackendObjects(objects []backend.StreamingObject) []StreamingObject { ContentType: o.ContentType, ContentEncoding: o.ContentEncoding, ContentDisposition: o.ContentDisposition, + CacheControl: o.CacheControl, Crc32c: o.Crc32c, Md5Hash: o.Md5Hash, Etag: o.Etag, @@ -477,6 +480,7 @@ func fromBackendObjectsAttrs(objectAttrs []backend.ObjectAttrs) []ObjectAttrs { ContentType: o.ContentType, ContentEncoding: o.ContentEncoding, ContentDisposition: o.ContentDisposition, + CacheControl: o.CacheControl, Crc32c: o.Crc32c, Md5Hash: o.Md5Hash, Etag: o.Etag, @@ -898,6 +902,9 @@ func (s *Server) downloadObject(w http.ResponseWriter, r *http.Request) { if obj.ContentType != "" { w.Header().Set(contentTypeHeader, obj.ContentType) } + if obj.CacheControl != "" { + w.Header().Set(cacheControlHeader, obj.CacheControl) + } // If content was transcoded, the underlying encoding was removed so we shouldn't report it. if obj.ContentEncoding != "" && !transcoded { w.Header().Set("Content-Encoding", obj.ContentEncoding) diff --git a/fakestorage/upload.go b/fakestorage/upload.go index 939ed29260..e9181df46f 100644 --- a/fakestorage/upload.go +++ b/fakestorage/upload.go @@ -26,7 +26,10 @@ import ( "github.com/gorilla/mux" ) -const contentTypeHeader = "Content-Type" +const ( + contentTypeHeader = "Content-Type" + cacheControlHeader = "Cache-Control" +) const ( uploadTypeMedia = "media" @@ -51,6 +54,7 @@ type multipartMetadata struct { ContentType string `json:"contentType"` ContentEncoding string `json:"contentEncoding"` ContentDisposition string `json:"contentDisposition"` + CacheControl string `json:"cacheControl"` CustomTime time.Time `json:"customTime,omitempty"` Name string `json:"name"` Metadata map[string]string `json:"metadata"` @@ -239,6 +243,7 @@ func (s *Server) simpleUpload(bucketName string, r *http.Request) jsonResponse { BucketName: bucketName, Name: name, ContentType: r.Header.Get(contentTypeHeader), + CacheControl: r.Header.Get(cacheControlHeader), ContentEncoding: contentEncoding, CustomTime: convertTimeWithoutError(customTime), ACL: getObjectACL(predefinedACL), @@ -374,6 +379,7 @@ func (s *Server) multipartUpload(bucketName string, r *http.Request) jsonRespons BucketName: bucketName, Name: objName, ContentType: contentType, + CacheControl: metadata.CacheControl, ContentEncoding: metadata.ContentEncoding, ContentDisposition: metadata.ContentDisposition, CustomTime: metadata.CustomTime, @@ -423,6 +429,7 @@ func (s *Server) resumableUpload(bucketName string, r *http.Request) jsonRespons BucketName: bucketName, Name: objName, ContentType: metadata.ContentType, + CacheControl: metadata.CacheControl, ContentEncoding: contentEncoding, CustomTime: metadata.CustomTime, ACL: getObjectACL(predefinedACL), diff --git a/fakestorage/upload_test.go b/fakestorage/upload_test.go index 582c913e35..6e2e2d8dd6 100644 --- a/fakestorage/upload_test.go +++ b/fakestorage/upload_test.go @@ -70,6 +70,7 @@ func TestServerClientObjectWriter(t *testing.T) { test := test t.Run(test.testCase, func(t *testing.T) { const contentType = "text/plain; charset=utf-8" + cacheControl := "public, max-age=3600" server.CreateBucketWithOpts(CreateBucketOpts{Name: test.bucketName}) client := server.Client() @@ -82,6 +83,7 @@ func TestServerClientObjectWriter(t *testing.T) { w.Metadata = map[string]string{ "foo": "bar", } + w.CacheControl = cacheControl w.Write([]byte(content)) err := w.Close() if err != nil { @@ -123,6 +125,9 @@ func TestServerClientObjectWriter(t *testing.T) { if !customTime.Equal(obj.CustomTime) { t.Errorf("wrong custom time\nwant %q\ngot %q", customTime.String(), obj.CustomTime.String()) } + if obj.CacheControl != cacheControl { + t.Errorf("wrong cache control\nwant %q\ngot %q", cacheControl, obj.CacheControl) + } reader, err := client.Bucket(test.bucketName).Object(test.objectName).NewReader(context.Background()) if err != nil { @@ -154,6 +159,7 @@ func TestServerClientObjectWriterOverwrite(t *testing.T) { runServersTest(t, runServersOptions{}, func(t *testing.T, server *Server) { const content = "other content" const contentType = "text/plain" + const cacheControl = "no-cache" server.CreateObject(Object{ ObjectAttrs: ObjectAttrs{ BucketName: "some-bucket", @@ -165,6 +171,7 @@ func TestServerClientObjectWriterOverwrite(t *testing.T) { objHandle := server.Client().Bucket("some-bucket").Object("some-object.txt") w := objHandle.NewWriter(context.Background()) w.ContentType = contentType + w.CacheControl = cacheControl w.Write([]byte(content)) err := w.Close() if err != nil { @@ -181,6 +188,9 @@ func TestServerClientObjectWriterOverwrite(t *testing.T) { if obj.ContentType != contentType { t.Errorf("wrong content-type\nwsant %q\ngot %q", contentType, obj.ContentType) } + if obj.CacheControl != cacheControl { + t.Errorf("wrong cache control\nwant %q\ngot %q", cacheControl, obj.CacheControl) + } }) } diff --git a/internal/backend/object.go b/internal/backend/object.go index eb7956d7fe..63bf8d6d14 100644 --- a/internal/backend/object.go +++ b/internal/backend/object.go @@ -21,6 +21,7 @@ type ObjectAttrs struct { ContentType string ContentEncoding string ContentDisposition string + CacheControl string Crc32c string Md5Hash string Etag string