From 0aedb67de056bcbb1e3c68192918eadf00f68535 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 1 Feb 2016 12:19:54 -0800 Subject: [PATCH] contentType: Reply back proper contentTypes based on the file extension. Currently the server would set 'application/octet-stream' for all objects, set this value based on the file extension transparently. This is useful in case of minio browser to facilitate displaying proper icons for the different mime data types. --- api-headers.go | 2 +- api-response.go | 4 +++- bucket-handlers.go | 4 +++- object-handlers.go | 8 ++++++-- pkg/fs/fs-multipart.go | 7 ++++++- pkg/fs/fs-object.go | 10 +++++++++- pkg/fs/fs.go | 4 ++++ web-definitions.go | 2 ++ web-handlers.go | 14 +++++++++++--- 9 files changed, 45 insertions(+), 10 deletions(-) diff --git a/api-headers.go b/api-headers.go index f1181512e..ba9ecaecd 100644 --- a/api-headers.go +++ b/api-headers.go @@ -78,7 +78,7 @@ func setObjectHeaders(w http.ResponseWriter, metadata fs.ObjectMetadata, content // set object headers lastModified := metadata.Created.Format(http.TimeFormat) // object related headers - w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Type", metadata.ContentType) if metadata.Md5 != "" { w.Header().Set("ETag", "\""+metadata.Md5+"\"") } diff --git a/api-response.go b/api-response.go index f29013754..e294e7ffe 100644 --- a/api-response.go +++ b/api-response.go @@ -108,7 +108,9 @@ func generateListObjectsResponse(bucket, prefix, marker, delimiter string, maxKe } content.Key = object.Object content.LastModified = object.Created.Format(rfcFormat) - content.ETag = "\"" + object.Md5 + "\"" + if object.Md5 != "" { + content.ETag = "\"" + object.Md5 + "\"" + } content.Size = object.Size content.StorageClass = "STANDARD" content.Owner = owner diff --git a/bucket-handlers.go b/bucket-handlers.go index d413f7851..0956b44f1 100644 --- a/bucket-handlers.go +++ b/bucket-handlers.go @@ -361,7 +361,9 @@ func (api CloudStorageAPI) PostPolicyBucketHandler(w http.ResponseWriter, req *h } return } - w.Header().Set("ETag", "\""+metadata.Md5+"\"") + if metadata.Md5 != "" { + w.Header().Set("ETag", "\""+metadata.Md5+"\"") + } writeSuccessResponse(w, nil) } diff --git a/object-handlers.go b/object-handlers.go index 04a911f4e..686029d18 100644 --- a/object-handlers.go +++ b/object-handlers.go @@ -204,7 +204,9 @@ func (api CloudStorageAPI) PutObjectHandler(w http.ResponseWriter, req *http.Req } return } - w.Header().Set("ETag", "\""+metadata.Md5+"\"") + if metadata.Md5 != "" { + w.Header().Set("ETag", "\""+metadata.Md5+"\"") + } writeSuccessResponse(w, nil) } @@ -347,7 +349,9 @@ func (api CloudStorageAPI) PutObjectPartHandler(w http.ResponseWriter, req *http } return } - w.Header().Set("ETag", "\""+calculatedMD5+"\"") + if calculatedMD5 != "" { + w.Header().Set("ETag", "\""+calculatedMD5+"\"") + } writeSuccessResponse(w, nil) } diff --git a/pkg/fs/fs-multipart.go b/pkg/fs/fs-multipart.go index 2c2372414..1ee6c4754 100644 --- a/pkg/fs/fs-multipart.go +++ b/pkg/fs/fs-multipart.go @@ -38,6 +38,7 @@ import ( "github.com/minio/minio-xl/pkg/crypto/sha256" "github.com/minio/minio-xl/pkg/crypto/sha512" "github.com/minio/minio-xl/pkg/probe" + "github.com/minio/minio/pkg/contentdb" "github.com/minio/minio/pkg/disk" ) @@ -432,12 +433,16 @@ func (fs Filesystem) CompleteMultipartUpload(bucket, object, uploadID string, da if err != nil { return ObjectMetadata{}, probe.NewError(err) } + contentType := "application/octet-stream" + if objectExt := filepath.Ext(objectPath); objectExt != "" { + contentType = contentdb.MustLookup(strings.TrimPrefix(objectExt, ".")) + } newObject := ObjectMetadata{ Bucket: bucket, Object: object, Created: st.ModTime(), Size: st.Size(), - ContentType: "application/octet-stream", + ContentType: contentType, Md5: hex.EncodeToString(h.Sum(nil)), } return newObject, nil diff --git a/pkg/fs/fs-object.go b/pkg/fs/fs-object.go index cd28bb054..b4b14bf44 100644 --- a/pkg/fs/fs-object.go +++ b/pkg/fs/fs-object.go @@ -32,6 +32,7 @@ import ( "github.com/minio/minio-xl/pkg/atomic" "github.com/minio/minio-xl/pkg/crypto/sha256" "github.com/minio/minio-xl/pkg/probe" + "github.com/minio/minio/pkg/contentdb" "github.com/minio/minio/pkg/disk" ) @@ -153,6 +154,9 @@ func getMetadata(rootPath, bucket, object string) (ObjectMetadata, *probe.Error) if runtime.GOOS == "windows" { object = sanitizeWindowsPath(object) } + if objectExt := filepath.Ext(object); objectExt != "" { + contentType = contentdb.MustLookup(strings.TrimPrefix(objectExt, ".")) + } metadata := ObjectMetadata{ Bucket: bucket, Object: object, @@ -279,12 +283,16 @@ func (fs Filesystem) CreateObject(bucket, object, expectedMD5Sum string, size in if err != nil { return ObjectMetadata{}, probe.NewError(err) } + contentType := "application/octet-stream" + if objectExt := filepath.Ext(objectPath); objectExt != "" { + contentType = contentdb.MustLookup(strings.TrimPrefix(objectExt, ".")) + } newObject := ObjectMetadata{ Bucket: bucket, Object: object, Created: st.ModTime(), Size: st.Size(), - ContentType: "application/octet-stream", + ContentType: contentType, Md5: md5Sum, } return newObject, nil diff --git a/pkg/fs/fs.go b/pkg/fs/fs.go index ed88cf747..ae229e56a 100644 --- a/pkg/fs/fs.go +++ b/pkg/fs/fs.go @@ -23,6 +23,7 @@ import ( "time" "github.com/minio/minio-xl/pkg/probe" + "github.com/minio/minio/pkg/contentdb" ) // Filesystem - local variables @@ -79,6 +80,9 @@ func New(rootPath string) (Filesystem, *probe.Error) { return Filesystem{}, err.Trace() } } + // Initialize content db. + contentdb.Init() + var buckets *Buckets buckets, err = loadBucketsMetadata() if err != nil { diff --git a/web-definitions.go b/web-definitions.go index 0a413e3dd..ddcbd82f7 100644 --- a/web-definitions.go +++ b/web-definitions.go @@ -51,6 +51,8 @@ type ObjectInfo struct { LastModified time.Time `json:"lastModified"` // Size in bytes of the object. Size int64 `json:"size"` + // ContentType is mime type of the object. + ContentType string `json:"contentType"` } // PutObjectURLArgs - args to generate url for upload access. diff --git a/web-handlers.go b/web-handlers.go index d09068d9a..55afc7f04 100644 --- a/web-handlers.go +++ b/web-handlers.go @@ -95,10 +95,18 @@ func (web *WebAPI) ListObjects(r *http.Request, args *ListObjectsArgs, reply *[] if object.Err != nil { return object.Err } + // TODO - This can get slower for large directories, we can + // perhaps extend the ListObjects XML to reply back + // ContentType as well. + objectInfo, e := web.Client.StatObject(args.BucketName, object.Key) + if e != nil { + return e + } *reply = append(*reply, ObjectInfo{ - Key: object.Key, - LastModified: object.LastModified, - Size: object.Size, + Key: objectInfo.Key, + LastModified: objectInfo.LastModified, + Size: objectInfo.Size, + ContentType: objectInfo.ContentType, }) } return nil