mirror of
https://github.com/minio/minio.git
synced 2024-12-26 07:05:55 -05:00
0aedb67de0
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.
247 lines
8.4 KiB
Go
247 lines
8.4 KiB
Go
/*
|
|
* Minio Cloud Storage, (C) 2015 Minio, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package main
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/minio/minio/pkg/fs"
|
|
)
|
|
|
|
// Reply date format
|
|
const (
|
|
rfcFormat = "2006-01-02T15:04:05.000Z"
|
|
)
|
|
|
|
// takes an array of Bucketmetadata information for serialization
|
|
// input:
|
|
// array of bucket metadata
|
|
//
|
|
// output:
|
|
// populated struct that can be serialized to match xml and json api spec output
|
|
func generateListBucketsResponse(buckets []fs.BucketMetadata) ListBucketsResponse {
|
|
var listbuckets []*Bucket
|
|
var data = ListBucketsResponse{}
|
|
var owner = Owner{}
|
|
|
|
owner.ID = "minio"
|
|
owner.DisplayName = "minio"
|
|
|
|
for _, bucket := range buckets {
|
|
var listbucket = &Bucket{}
|
|
listbucket.Name = bucket.Name
|
|
listbucket.CreationDate = bucket.Created.Format(rfcFormat)
|
|
listbuckets = append(listbuckets, listbucket)
|
|
}
|
|
|
|
data.Owner = owner
|
|
data.Buckets.Bucket = listbuckets
|
|
|
|
return data
|
|
}
|
|
|
|
// generates an AccessControlPolicy response for the said ACL.
|
|
func generateAccessControlPolicyResponse(acl fs.BucketACL) AccessControlPolicyResponse {
|
|
accessCtrlPolicyResponse := AccessControlPolicyResponse{}
|
|
accessCtrlPolicyResponse.Owner = Owner{
|
|
ID: "minio",
|
|
DisplayName: "minio",
|
|
}
|
|
defaultGrant := Grant{}
|
|
defaultGrant.Grantee.ID = "minio"
|
|
defaultGrant.Grantee.DisplayName = "minio"
|
|
defaultGrant.Permission = "FULL_CONTROL"
|
|
accessCtrlPolicyResponse.AccessControlList.Grant = append(accessCtrlPolicyResponse.AccessControlList.Grant, defaultGrant)
|
|
switch {
|
|
case acl.IsPublicRead():
|
|
publicReadGrant := Grant{}
|
|
publicReadGrant.Grantee.ID = "minio"
|
|
publicReadGrant.Grantee.DisplayName = "minio"
|
|
publicReadGrant.Grantee.URI = "http://acs.amazonaws.com/groups/global/AllUsers"
|
|
publicReadGrant.Permission = "READ"
|
|
accessCtrlPolicyResponse.AccessControlList.Grant = append(accessCtrlPolicyResponse.AccessControlList.Grant, publicReadGrant)
|
|
case acl.IsPublicReadWrite():
|
|
publicReadGrant := Grant{}
|
|
publicReadGrant.Grantee.ID = "minio"
|
|
publicReadGrant.Grantee.DisplayName = "minio"
|
|
publicReadGrant.Grantee.URI = "http://acs.amazonaws.com/groups/global/AllUsers"
|
|
publicReadGrant.Permission = "READ"
|
|
publicReadWriteGrant := Grant{}
|
|
publicReadWriteGrant.Grantee.ID = "minio"
|
|
publicReadWriteGrant.Grantee.DisplayName = "minio"
|
|
publicReadWriteGrant.Grantee.URI = "http://acs.amazonaws.com/groups/global/AllUsers"
|
|
publicReadWriteGrant.Permission = "WRITE"
|
|
accessCtrlPolicyResponse.AccessControlList.Grant = append(accessCtrlPolicyResponse.AccessControlList.Grant, publicReadGrant)
|
|
accessCtrlPolicyResponse.AccessControlList.Grant = append(accessCtrlPolicyResponse.AccessControlList.Grant, publicReadWriteGrant)
|
|
}
|
|
return accessCtrlPolicyResponse
|
|
}
|
|
|
|
// generates an ListObjects response for the said bucket with other enumerated options.
|
|
func generateListObjectsResponse(bucket, prefix, marker, delimiter string, maxKeys int, resp fs.ListObjectsResult) ListObjectsResponse {
|
|
var contents []*Object
|
|
var prefixes []*CommonPrefix
|
|
var owner = Owner{}
|
|
var data = ListObjectsResponse{}
|
|
|
|
owner.ID = "minio"
|
|
owner.DisplayName = "minio"
|
|
|
|
for _, object := range resp.Objects {
|
|
var content = &Object{}
|
|
if object.Object == "" {
|
|
continue
|
|
}
|
|
content.Key = object.Object
|
|
content.LastModified = object.Created.Format(rfcFormat)
|
|
if object.Md5 != "" {
|
|
content.ETag = "\"" + object.Md5 + "\""
|
|
}
|
|
content.Size = object.Size
|
|
content.StorageClass = "STANDARD"
|
|
content.Owner = owner
|
|
contents = append(contents, content)
|
|
}
|
|
// TODO - support EncodingType in xml decoding
|
|
data.Name = bucket
|
|
data.Contents = contents
|
|
|
|
data.Prefix = prefix
|
|
data.Marker = marker
|
|
data.Delimiter = delimiter
|
|
data.MaxKeys = maxKeys
|
|
|
|
data.NextMarker = resp.NextMarker
|
|
data.IsTruncated = resp.IsTruncated
|
|
for _, prefix := range resp.Prefixes {
|
|
var prefixItem = &CommonPrefix{}
|
|
prefixItem.Prefix = prefix
|
|
prefixes = append(prefixes, prefixItem)
|
|
}
|
|
data.CommonPrefixes = prefixes
|
|
return data
|
|
}
|
|
|
|
// generateInitiateMultipartUploadResponse
|
|
func generateInitiateMultipartUploadResponse(bucket, key, uploadID string) InitiateMultipartUploadResponse {
|
|
return InitiateMultipartUploadResponse{
|
|
Bucket: bucket,
|
|
Key: key,
|
|
UploadID: uploadID,
|
|
}
|
|
}
|
|
|
|
// generateCompleteMultipartUploadResponse
|
|
func generateCompleteMultpartUploadResponse(bucket, key, location, etag string) CompleteMultipartUploadResponse {
|
|
return CompleteMultipartUploadResponse{
|
|
Location: location,
|
|
Bucket: bucket,
|
|
Key: key,
|
|
ETag: etag,
|
|
}
|
|
}
|
|
|
|
// generateListPartsResult
|
|
func generateListPartsResponse(objectMetadata fs.ObjectResourcesMetadata) ListPartsResponse {
|
|
// TODO - support EncodingType in xml decoding
|
|
listPartsResponse := ListPartsResponse{}
|
|
listPartsResponse.Bucket = objectMetadata.Bucket
|
|
listPartsResponse.Key = objectMetadata.Object
|
|
listPartsResponse.UploadID = objectMetadata.UploadID
|
|
listPartsResponse.StorageClass = "STANDARD"
|
|
listPartsResponse.Initiator.ID = "minio"
|
|
listPartsResponse.Initiator.DisplayName = "minio"
|
|
listPartsResponse.Owner.ID = "minio"
|
|
listPartsResponse.Owner.DisplayName = "minio"
|
|
|
|
listPartsResponse.MaxParts = objectMetadata.MaxParts
|
|
listPartsResponse.PartNumberMarker = objectMetadata.PartNumberMarker
|
|
listPartsResponse.IsTruncated = objectMetadata.IsTruncated
|
|
listPartsResponse.NextPartNumberMarker = objectMetadata.NextPartNumberMarker
|
|
|
|
listPartsResponse.Part = make([]*Part, len(objectMetadata.Part))
|
|
for _, part := range objectMetadata.Part {
|
|
newPart := &Part{}
|
|
newPart.PartNumber = part.PartNumber
|
|
newPart.ETag = "\"" + part.ETag + "\""
|
|
newPart.Size = part.Size
|
|
newPart.LastModified = part.LastModified.Format(rfcFormat)
|
|
listPartsResponse.Part = append(listPartsResponse.Part, newPart)
|
|
}
|
|
return listPartsResponse
|
|
}
|
|
|
|
// generateListMultipartUploadsResponse
|
|
func generateListMultipartUploadsResponse(bucket string, metadata fs.BucketMultipartResourcesMetadata) ListMultipartUploadsResponse {
|
|
listMultipartUploadsResponse := ListMultipartUploadsResponse{}
|
|
listMultipartUploadsResponse.Bucket = bucket
|
|
listMultipartUploadsResponse.Delimiter = metadata.Delimiter
|
|
listMultipartUploadsResponse.IsTruncated = metadata.IsTruncated
|
|
listMultipartUploadsResponse.EncodingType = metadata.EncodingType
|
|
listMultipartUploadsResponse.Prefix = metadata.Prefix
|
|
listMultipartUploadsResponse.KeyMarker = metadata.KeyMarker
|
|
listMultipartUploadsResponse.NextKeyMarker = metadata.NextKeyMarker
|
|
listMultipartUploadsResponse.MaxUploads = metadata.MaxUploads
|
|
listMultipartUploadsResponse.NextUploadIDMarker = metadata.NextUploadIDMarker
|
|
listMultipartUploadsResponse.UploadIDMarker = metadata.UploadIDMarker
|
|
|
|
listMultipartUploadsResponse.Upload = make([]*Upload, len(metadata.Upload))
|
|
for _, upload := range metadata.Upload {
|
|
newUpload := &Upload{}
|
|
newUpload.UploadID = upload.UploadID
|
|
newUpload.Key = upload.Object
|
|
newUpload.Initiated = upload.Initiated.Format(rfcFormat)
|
|
listMultipartUploadsResponse.Upload = append(listMultipartUploadsResponse.Upload, newUpload)
|
|
}
|
|
return listMultipartUploadsResponse
|
|
}
|
|
|
|
// writeSuccessResponse write success headers and response if any.
|
|
func writeSuccessResponse(w http.ResponseWriter, response []byte) {
|
|
setCommonHeaders(w)
|
|
if response == nil {
|
|
w.WriteHeader(http.StatusOK)
|
|
return
|
|
}
|
|
w.Write(response)
|
|
w.(http.Flusher).Flush()
|
|
}
|
|
|
|
// writeSuccessNoContent write success headers with http status 204
|
|
func writeSuccessNoContent(w http.ResponseWriter) {
|
|
setCommonHeaders(w)
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
// writeErrorRespone write error headers
|
|
func writeErrorResponse(w http.ResponseWriter, req *http.Request, errorType int, resource string) {
|
|
error := getErrorCode(errorType)
|
|
// generate error response
|
|
errorResponse := getErrorResponse(error, resource)
|
|
encodedErrorResponse := encodeErrorResponse(errorResponse)
|
|
// set common headers
|
|
setCommonHeaders(w)
|
|
// write Header
|
|
w.WriteHeader(error.HTTPStatusCode)
|
|
// HEAD should have no body, do not attempt to write to it
|
|
if req.Method != "HEAD" {
|
|
// write error body
|
|
w.Write(encodedErrorResponse)
|
|
w.(http.Flusher).Flush()
|
|
}
|
|
}
|