mirror of https://github.com/minio/minio.git
				
				
				
			
		
			
	
	
		
			326 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Go
		
	
	
	
		
		
			
		
	
	
			326 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Go
		
	
	
	
|  | /* | ||
|  |  * Minio Cloud Storage, (C) 2017 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 cmd | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"net/http" | ||
|  | 
 | ||
|  | 	"github.com/minio/minio/pkg/errors" | ||
|  | 	"github.com/minio/minio/pkg/hash" | ||
|  | 
 | ||
|  | 	minio "github.com/minio/minio-go" | ||
|  | ) | ||
|  | 
 | ||
|  | var ( | ||
|  | 	// CanonicalizeETag provides canonicalizeETag function alias.
 | ||
|  | 	CanonicalizeETag = canonicalizeETag | ||
|  | 
 | ||
|  | 	// MustGetUUID function alias.
 | ||
|  | 	MustGetUUID = mustGetUUID | ||
|  | 
 | ||
|  | 	// ErrorIf provides errorIf function alias.
 | ||
|  | 	ErrorIf = errorIf | ||
|  | 
 | ||
|  | 	// FatalIf provides fatalIf function alias.
 | ||
|  | 	FatalIf = fatalIf | ||
|  | ) | ||
|  | 
 | ||
|  | // AnonErrToObjectErr - converts standard http codes into meaningful object layer errors.
 | ||
|  | func AnonErrToObjectErr(statusCode int, params ...string) error { | ||
|  | 	bucket := "" | ||
|  | 	object := "" | ||
|  | 	if len(params) >= 1 { | ||
|  | 		bucket = params[0] | ||
|  | 	} | ||
|  | 	if len(params) == 2 { | ||
|  | 		object = params[1] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	switch statusCode { | ||
|  | 	case http.StatusNotFound: | ||
|  | 		if object != "" { | ||
|  | 			return ObjectNotFound{bucket, object} | ||
|  | 		} | ||
|  | 		return BucketNotFound{Bucket: bucket} | ||
|  | 	case http.StatusBadRequest: | ||
|  | 		if object != "" { | ||
|  | 			return ObjectNameInvalid{bucket, object} | ||
|  | 		} | ||
|  | 		return BucketNameInvalid{Bucket: bucket} | ||
|  | 	case http.StatusForbidden: | ||
|  | 		fallthrough | ||
|  | 	case http.StatusUnauthorized: | ||
|  | 		return AllAccessDisabled{bucket, object} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return errUnexpected | ||
|  | } | ||
|  | 
 | ||
|  | // FromMinioClientMetadata converts minio metadata to map[string]string
 | ||
|  | func FromMinioClientMetadata(metadata map[string][]string) map[string]string { | ||
|  | 	mm := map[string]string{} | ||
|  | 	for k, v := range metadata { | ||
|  | 		mm[http.CanonicalHeaderKey(k)] = v[0] | ||
|  | 	} | ||
|  | 	return mm | ||
|  | } | ||
|  | 
 | ||
|  | // FromMinioClientObjectPart converts minio ObjectPart to PartInfo
 | ||
|  | func FromMinioClientObjectPart(op minio.ObjectPart) PartInfo { | ||
|  | 	return PartInfo{ | ||
|  | 		Size:         op.Size, | ||
|  | 		ETag:         canonicalizeETag(op.ETag), | ||
|  | 		LastModified: op.LastModified, | ||
|  | 		PartNumber:   op.PartNumber, | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // FromMinioClientListPartsInfo converts minio ListObjectPartsResult to ListPartsInfo
 | ||
|  | func FromMinioClientListPartsInfo(lopr minio.ListObjectPartsResult) ListPartsInfo { | ||
|  | 	// Convert minio ObjectPart to PartInfo
 | ||
|  | 	fromMinioClientObjectParts := func(parts []minio.ObjectPart) []PartInfo { | ||
|  | 		toParts := make([]PartInfo, len(parts)) | ||
|  | 		for i, part := range parts { | ||
|  | 			toParts[i] = FromMinioClientObjectPart(part) | ||
|  | 		} | ||
|  | 		return toParts | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return ListPartsInfo{ | ||
|  | 		UploadID:             lopr.UploadID, | ||
|  | 		Bucket:               lopr.Bucket, | ||
|  | 		Object:               lopr.Key, | ||
|  | 		StorageClass:         "", | ||
|  | 		PartNumberMarker:     lopr.PartNumberMarker, | ||
|  | 		NextPartNumberMarker: lopr.NextPartNumberMarker, | ||
|  | 		MaxParts:             lopr.MaxParts, | ||
|  | 		IsTruncated:          lopr.IsTruncated, | ||
|  | 		EncodingType:         lopr.EncodingType, | ||
|  | 		Parts:                fromMinioClientObjectParts(lopr.ObjectParts), | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // FromMinioClientListMultipartsInfo converts minio ListMultipartUploadsResult to ListMultipartsInfo
 | ||
|  | func FromMinioClientListMultipartsInfo(lmur minio.ListMultipartUploadsResult) ListMultipartsInfo { | ||
|  | 	uploads := make([]MultipartInfo, len(lmur.Uploads)) | ||
|  | 
 | ||
|  | 	for i, um := range lmur.Uploads { | ||
|  | 		uploads[i] = MultipartInfo{ | ||
|  | 			Object:    um.Key, | ||
|  | 			UploadID:  um.UploadID, | ||
|  | 			Initiated: um.Initiated, | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	commonPrefixes := make([]string, len(lmur.CommonPrefixes)) | ||
|  | 	for i, cp := range lmur.CommonPrefixes { | ||
|  | 		commonPrefixes[i] = cp.Prefix | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return ListMultipartsInfo{ | ||
|  | 		KeyMarker:          lmur.KeyMarker, | ||
|  | 		UploadIDMarker:     lmur.UploadIDMarker, | ||
|  | 		NextKeyMarker:      lmur.NextKeyMarker, | ||
|  | 		NextUploadIDMarker: lmur.NextUploadIDMarker, | ||
|  | 		MaxUploads:         int(lmur.MaxUploads), | ||
|  | 		IsTruncated:        lmur.IsTruncated, | ||
|  | 		Uploads:            uploads, | ||
|  | 		Prefix:             lmur.Prefix, | ||
|  | 		Delimiter:          lmur.Delimiter, | ||
|  | 		CommonPrefixes:     commonPrefixes, | ||
|  | 		EncodingType:       lmur.EncodingType, | ||
|  | 	} | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | // FromMinioClientObjectInfo converts minio ObjectInfo to gateway ObjectInfo
 | ||
|  | func FromMinioClientObjectInfo(bucket string, oi minio.ObjectInfo) ObjectInfo { | ||
|  | 	userDefined := FromMinioClientMetadata(oi.Metadata) | ||
|  | 	userDefined["Content-Type"] = oi.ContentType | ||
|  | 
 | ||
|  | 	return ObjectInfo{ | ||
|  | 		Bucket:          bucket, | ||
|  | 		Name:            oi.Key, | ||
|  | 		ModTime:         oi.LastModified, | ||
|  | 		Size:            oi.Size, | ||
|  | 		ETag:            canonicalizeETag(oi.ETag), | ||
|  | 		UserDefined:     userDefined, | ||
|  | 		ContentType:     oi.ContentType, | ||
|  | 		ContentEncoding: oi.Metadata.Get("Content-Encoding"), | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // FromMinioClientListBucketV2Result converts minio ListBucketResult to ListObjectsInfo
 | ||
|  | func FromMinioClientListBucketV2Result(bucket string, result minio.ListBucketV2Result) ListObjectsV2Info { | ||
|  | 	objects := make([]ObjectInfo, len(result.Contents)) | ||
|  | 
 | ||
|  | 	for i, oi := range result.Contents { | ||
|  | 		objects[i] = FromMinioClientObjectInfo(bucket, oi) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	prefixes := make([]string, len(result.CommonPrefixes)) | ||
|  | 	for i, p := range result.CommonPrefixes { | ||
|  | 		prefixes[i] = p.Prefix | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return ListObjectsV2Info{ | ||
|  | 		IsTruncated: result.IsTruncated, | ||
|  | 		Prefixes:    prefixes, | ||
|  | 		Objects:     objects, | ||
|  | 
 | ||
|  | 		ContinuationToken:     result.ContinuationToken, | ||
|  | 		NextContinuationToken: result.NextContinuationToken, | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // FromMinioClientListBucketResult converts minio ListBucketResult to ListObjectsInfo
 | ||
|  | func FromMinioClientListBucketResult(bucket string, result minio.ListBucketResult) ListObjectsInfo { | ||
|  | 	objects := make([]ObjectInfo, len(result.Contents)) | ||
|  | 
 | ||
|  | 	for i, oi := range result.Contents { | ||
|  | 		objects[i] = FromMinioClientObjectInfo(bucket, oi) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	prefixes := make([]string, len(result.CommonPrefixes)) | ||
|  | 	for i, p := range result.CommonPrefixes { | ||
|  | 		prefixes[i] = p.Prefix | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return ListObjectsInfo{ | ||
|  | 		IsTruncated: result.IsTruncated, | ||
|  | 		NextMarker:  result.NextMarker, | ||
|  | 		Prefixes:    prefixes, | ||
|  | 		Objects:     objects, | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // FromMinioClientListBucketResultToV2Info converts minio ListBucketResult to ListObjectsV2Info
 | ||
|  | func FromMinioClientListBucketResultToV2Info(bucket string, result minio.ListBucketResult) ListObjectsV2Info { | ||
|  | 	objects := make([]ObjectInfo, len(result.Contents)) | ||
|  | 
 | ||
|  | 	for i, oi := range result.Contents { | ||
|  | 		objects[i] = FromMinioClientObjectInfo(bucket, oi) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	prefixes := make([]string, len(result.CommonPrefixes)) | ||
|  | 	for i, p := range result.CommonPrefixes { | ||
|  | 		prefixes[i] = p.Prefix | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return ListObjectsV2Info{ | ||
|  | 		IsTruncated:           result.IsTruncated, | ||
|  | 		Prefixes:              prefixes, | ||
|  | 		Objects:               objects, | ||
|  | 		ContinuationToken:     result.Marker, | ||
|  | 		NextContinuationToken: result.NextMarker, | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // ToMinioClientMetadata converts metadata to map[string][]string
 | ||
|  | func ToMinioClientMetadata(metadata map[string]string) map[string]string { | ||
|  | 	mm := make(map[string]string) | ||
|  | 	for k, v := range metadata { | ||
|  | 		mm[http.CanonicalHeaderKey(k)] = v | ||
|  | 	} | ||
|  | 	return mm | ||
|  | } | ||
|  | 
 | ||
|  | // ToMinioClientCompletePart converts CompletePart to minio CompletePart
 | ||
|  | func ToMinioClientCompletePart(part CompletePart) minio.CompletePart { | ||
|  | 	return minio.CompletePart{ | ||
|  | 		ETag:       part.ETag, | ||
|  | 		PartNumber: part.PartNumber, | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // ToMinioClientCompleteParts converts []CompletePart to minio []CompletePart
 | ||
|  | func ToMinioClientCompleteParts(parts []CompletePart) []minio.CompletePart { | ||
|  | 	mparts := make([]minio.CompletePart, len(parts)) | ||
|  | 	for i, part := range parts { | ||
|  | 		mparts[i] = ToMinioClientCompletePart(part) | ||
|  | 	} | ||
|  | 	return mparts | ||
|  | } | ||
|  | 
 | ||
|  | // ErrorRespToObjectError converts Minio errors to minio object layer errors.
 | ||
|  | func ErrorRespToObjectError(err error, params ...string) error { | ||
|  | 	if err == nil { | ||
|  | 		return nil | ||
|  | 	} | ||
|  | 
 | ||
|  | 	e, ok := err.(*errors.Error) | ||
|  | 	if !ok { | ||
|  | 		// Code should be fixed if this function is called without doing traceError()
 | ||
|  | 		// Else handling different situations in this function makes this function complicated.
 | ||
|  | 		errorIf(err, "Expected type *Error") | ||
|  | 		return err | ||
|  | 	} | ||
|  | 
 | ||
|  | 	err = e.Cause | ||
|  | 
 | ||
|  | 	bucket := "" | ||
|  | 	object := "" | ||
|  | 	if len(params) >= 1 { | ||
|  | 		bucket = params[0] | ||
|  | 	} | ||
|  | 	if len(params) == 2 { | ||
|  | 		object = params[1] | ||
|  | 	} | ||
|  | 
 | ||
|  | 	minioErr, ok := err.(minio.ErrorResponse) | ||
|  | 	if !ok { | ||
|  | 		// We don't interpret non Minio errors. As minio errors will
 | ||
|  | 		// have StatusCode to help to convert to object errors.
 | ||
|  | 		return e | ||
|  | 	} | ||
|  | 
 | ||
|  | 	switch minioErr.Code { | ||
|  | 	case "BucketAlreadyOwnedByYou": | ||
|  | 		err = BucketAlreadyOwnedByYou{} | ||
|  | 	case "BucketNotEmpty": | ||
|  | 		err = BucketNotEmpty{} | ||
|  | 	case "NoSuchBucketPolicy": | ||
|  | 		err = PolicyNotFound{} | ||
|  | 	case "InvalidBucketName": | ||
|  | 		err = BucketNameInvalid{Bucket: bucket} | ||
|  | 	case "NoSuchBucket": | ||
|  | 		err = BucketNotFound{Bucket: bucket} | ||
|  | 	case "NoSuchKey": | ||
|  | 		if object != "" { | ||
|  | 			err = ObjectNotFound{Bucket: bucket, Object: object} | ||
|  | 		} else { | ||
|  | 			err = BucketNotFound{Bucket: bucket} | ||
|  | 		} | ||
|  | 	case "XMinioInvalidObjectName": | ||
|  | 		err = ObjectNameInvalid{} | ||
|  | 	case "AccessDenied": | ||
|  | 		err = PrefixAccessDenied{ | ||
|  | 			Bucket: bucket, | ||
|  | 			Object: object, | ||
|  | 		} | ||
|  | 	case "XAmzContentSHA256Mismatch": | ||
|  | 		err = hash.SHA256Mismatch{} | ||
|  | 	case "NoSuchUpload": | ||
|  | 		err = InvalidUploadID{} | ||
|  | 	case "EntityTooSmall": | ||
|  | 		err = PartTooSmall{} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	e.Cause = err | ||
|  | 	return e | ||
|  | } |