| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // Copyright (c) 2015-2021 MinIO, Inc.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2019-11-02 07:58:11 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2020-11-20 02:38:02 +08:00
										 |  |  | 	"net" | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2019-01-06 06:16:43 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2019-11-02 07:58:11 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-02 05:59:40 +08:00
										 |  |  | 	"github.com/minio/minio/internal/config" | 
					
						
							|  |  |  | 	"github.com/minio/minio/internal/hash" | 
					
						
							|  |  |  | 	xhttp "github.com/minio/minio/internal/http" | 
					
						
							|  |  |  | 	"github.com/minio/minio/internal/logger" | 
					
						
							| 
									
										
										
										
											2021-05-29 06:17:01 +08:00
										 |  |  | 	"github.com/minio/pkg/env" | 
					
						
							| 
									
										
										
										
											2021-06-15 05:54:37 +08:00
										 |  |  | 	xnet "github.com/minio/pkg/net" | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-15 00:38:05 +08:00
										 |  |  | 	minio "github.com/minio/minio-go/v7" | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	// CanonicalizeETag provides canonicalizeETag function alias.
 | 
					
						
							|  |  |  | 	CanonicalizeETag = canonicalizeETag | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// MustGetUUID function alias.
 | 
					
						
							|  |  |  | 	MustGetUUID = mustGetUUID | 
					
						
							| 
									
										
										
										
											2019-01-06 06:16:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// CleanMetadataKeys provides cleanMetadataKeys function alias.
 | 
					
						
							|  |  |  | 	CleanMetadataKeys = cleanMetadataKeys | 
					
						
							| 
									
										
										
										
											2019-04-18 00:52:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// PathJoin function alias.
 | 
					
						
							|  |  |  | 	PathJoin = pathJoin | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// ListObjects function alias.
 | 
					
						
							|  |  |  | 	ListObjects = listObjects | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-26 03:26:48 +08:00
										 |  |  | 	// FilterListEntries function alias.
 | 
					
						
							|  |  |  | 	FilterListEntries = filterListEntries | 
					
						
							| 
									
										
										
										
											2019-04-18 00:52:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// IsStringEqual is string equal.
 | 
					
						
							|  |  |  | 	IsStringEqual = isStringEqual | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // FromMinioClientMetadata converts minio metadata to map[string]string
 | 
					
						
							|  |  |  | func FromMinioClientMetadata(metadata map[string][]string) map[string]string { | 
					
						
							| 
									
										
										
										
											2020-09-11 02:37:22 +08:00
										 |  |  | 	mm := make(map[string]string, len(metadata)) | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 	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, | 
					
						
							|  |  |  | 		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) | 
					
						
							| 
									
										
										
										
											2019-07-03 13:34:32 +08:00
										 |  |  | 	userDefined[xhttp.ContentType] = oi.ContentType | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ObjectInfo{ | 
					
						
							|  |  |  | 		Bucket:          bucket, | 
					
						
							|  |  |  | 		Name:            oi.Key, | 
					
						
							|  |  |  | 		ModTime:         oi.LastModified, | 
					
						
							|  |  |  | 		Size:            oi.Size, | 
					
						
							|  |  |  | 		ETag:            canonicalizeETag(oi.ETag), | 
					
						
							|  |  |  | 		UserDefined:     userDefined, | 
					
						
							|  |  |  | 		ContentType:     oi.ContentType, | 
					
						
							| 
									
										
										
										
											2019-07-03 13:34:32 +08:00
										 |  |  | 		ContentEncoding: oi.Metadata.Get(xhttp.ContentEncoding), | 
					
						
							| 
									
										
										
										
											2018-06-20 02:22:08 +08:00
										 |  |  | 		StorageClass:    oi.StorageClass, | 
					
						
							| 
									
										
										
										
											2019-03-01 03:01:25 +08:00
										 |  |  | 		Expires:         oi.Expires, | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 03:25:59 +08:00
										 |  |  | // ToMinioClientObjectInfoMetadata convertes metadata to map[string][]string
 | 
					
						
							|  |  |  | func ToMinioClientObjectInfoMetadata(metadata map[string]string) map[string][]string { | 
					
						
							|  |  |  | 	mm := make(map[string][]string, len(metadata)) | 
					
						
							|  |  |  | 	for k, v := range metadata { | 
					
						
							|  |  |  | 		mm[http.CanonicalHeaderKey(k)] = []string{v} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return mm | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ToMinioClientMetadata converts metadata to map[string]string
 | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | func ToMinioClientMetadata(metadata map[string]string) map[string]string { | 
					
						
							| 
									
										
										
										
											2020-09-11 02:37:22 +08:00
										 |  |  | 	mm := make(map[string]string, len(metadata)) | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 	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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-02 07:58:11 +08:00
										 |  |  | // IsBackendOnline - verifies if the backend is reachable
 | 
					
						
							|  |  |  | // by performing a GET request on the URL. returns 'true'
 | 
					
						
							|  |  |  | // if backend is reachable.
 | 
					
						
							| 
									
										
										
										
											2020-11-20 02:38:02 +08:00
										 |  |  | func IsBackendOnline(ctx context.Context, host string) bool { | 
					
						
							|  |  |  | 	var d net.Dialer | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-02 07:58:11 +08:00
										 |  |  | 	ctx, cancel := context.WithTimeout(ctx, 1*time.Second) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 02:38:02 +08:00
										 |  |  | 	conn, err := d.DialContext(ctx, "tcp", host) | 
					
						
							| 
									
										
										
										
											2019-11-02 07:58:11 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-20 02:38:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	conn.Close() | 
					
						
							| 
									
										
										
										
											2019-11-02 07:58:11 +08:00
										 |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 02:39:42 +08:00
										 |  |  | // ErrorRespToObjectError converts MinIO errors to minio object layer errors.
 | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | func ErrorRespToObjectError(err error, params ...string) error { | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := "" | 
					
						
							|  |  |  | 	object := "" | 
					
						
							|  |  |  | 	if len(params) >= 1 { | 
					
						
							|  |  |  | 		bucket = params[0] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if len(params) == 2 { | 
					
						
							|  |  |  | 		object = params[1] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 00:52:11 +08:00
										 |  |  | 	if xnet.IsNetworkOrHostDown(err, false) { | 
					
						
							| 
									
										
										
										
											2021-11-11 14:33:17 +08:00
										 |  |  | 		return BackendDown{Err: err.Error()} | 
					
						
							| 
									
										
										
										
											2018-03-29 05:14:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 	minioErr, ok := err.(minio.ErrorResponse) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2019-04-10 02:39:42 +08:00
										 |  |  | 		// We don't interpret non MinIO errors. As minio errors will
 | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 		// have StatusCode to help to convert to object errors.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch minioErr.Code { | 
					
						
							| 
									
										
										
										
											2022-06-28 05:03:44 +08:00
										 |  |  | 	case "PreconditionFailed": | 
					
						
							|  |  |  | 		err = PreConditionFailed{} | 
					
						
							|  |  |  | 	case "InvalidRange": | 
					
						
							|  |  |  | 		err = InvalidRange{} | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 	case "BucketAlreadyOwnedByYou": | 
					
						
							|  |  |  | 		err = BucketAlreadyOwnedByYou{} | 
					
						
							|  |  |  | 	case "BucketNotEmpty": | 
					
						
							|  |  |  | 		err = BucketNotEmpty{} | 
					
						
							|  |  |  | 	case "NoSuchBucketPolicy": | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 		err = BucketPolicyNotFound{} | 
					
						
							| 
									
										
										
										
											2020-02-08 19:16:59 +08:00
										 |  |  | 	case "NoSuchLifecycleConfiguration": | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | 		err = BucketLifecycleNotFound{} | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 	case "InvalidBucketName": | 
					
						
							|  |  |  | 		err = BucketNameInvalid{Bucket: bucket} | 
					
						
							| 
									
										
										
										
											2018-10-18 00:20:58 +08:00
										 |  |  | 	case "InvalidPart": | 
					
						
							|  |  |  | 		err = InvalidPart{} | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | 	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{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-24 05:48:22 +08:00
										 |  |  | 	switch minioErr.StatusCode { | 
					
						
							|  |  |  | 	case http.StatusMethodNotAllowed: | 
					
						
							|  |  |  | 		err = toObjectErr(errMethodNotAllowed, bucket, object) | 
					
						
							| 
									
										
										
										
											2022-02-24 05:34:25 +08:00
										 |  |  | 	case http.StatusBadGateway: | 
					
						
							|  |  |  | 		return BackendDown{Err: err.Error()} | 
					
						
							| 
									
										
										
										
											2021-08-24 05:48:22 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 	return err | 
					
						
							| 
									
										
										
										
											2017-12-06 09:58:09 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-01-06 06:16:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:50:25 +08:00
										 |  |  | // ComputeCompleteMultipartMD5 calculates MD5 ETag for complete multipart responses
 | 
					
						
							| 
									
										
										
										
											2019-05-09 09:35:40 +08:00
										 |  |  | func ComputeCompleteMultipartMD5(parts []CompletePart) string { | 
					
						
							|  |  |  | 	return getCompleteMultipartMD5(parts) | 
					
						
							| 
									
										
										
										
											2019-04-18 14:50:25 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-06 06:16:43 +08:00
										 |  |  | // parse gateway sse env variable
 | 
					
						
							|  |  |  | func parseGatewaySSE(s string) (gatewaySSE, error) { | 
					
						
							|  |  |  | 	l := strings.Split(s, ";") | 
					
						
							| 
									
										
										
										
											2020-09-16 04:57:15 +08:00
										 |  |  | 	var gwSlice gatewaySSE | 
					
						
							| 
									
										
										
										
											2019-01-06 06:16:43 +08:00
										 |  |  | 	for _, val := range l { | 
					
						
							|  |  |  | 		v := strings.ToUpper(val) | 
					
						
							| 
									
										
										
										
											2020-09-16 04:57:15 +08:00
										 |  |  | 		switch v { | 
					
						
							|  |  |  | 		case "": | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		case gatewaySSES3: | 
					
						
							|  |  |  | 			fallthrough | 
					
						
							|  |  |  | 		case gatewaySSEC: | 
					
						
							| 
									
										
										
										
											2019-01-06 06:16:43 +08:00
										 |  |  | 			gwSlice = append(gwSlice, v) | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2020-09-16 04:57:15 +08:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 			return nil, config.ErrInvalidGWSSEValue(nil).Msg("gateway SSE cannot be (%s) ", v) | 
					
						
							| 
									
										
										
										
											2019-01-06 06:16:43 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-09-16 04:57:15 +08:00
										 |  |  | 	return gwSlice, nil | 
					
						
							| 
									
										
										
										
											2019-01-06 06:16:43 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // handle gateway env vars
 | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | func gatewayHandleEnvVars() { | 
					
						
							|  |  |  | 	// Handle common env vars.
 | 
					
						
							|  |  |  | 	handleCommonEnvVars() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !globalActiveCred.IsValid() { | 
					
						
							|  |  |  | 		logger.Fatal(config.ErrInvalidCredentials(nil), | 
					
						
							| 
									
										
										
										
											2019-10-23 13:59:13 +08:00
										 |  |  | 			"Unable to validate credentials inherited from the shell environment") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-31 14:39:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	gwsseVal := env.Get("MINIO_GATEWAY_SSE", "") | 
					
						
							| 
									
										
										
										
											2020-09-16 04:57:15 +08:00
										 |  |  | 	if gwsseVal != "" { | 
					
						
							| 
									
										
										
										
											2019-10-31 14:39:09 +08:00
										 |  |  | 		var err error | 
					
						
							|  |  |  | 		GlobalGatewaySSE, err = parseGatewaySSE(gwsseVal) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			logger.Fatal(err, "Unable to parse MINIO_GATEWAY_SSE value (`%s`)", gwsseVal) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-06 06:16:43 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-02-11 23:38:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // shouldMeterRequest checks whether incoming request should be added to prometheus gateway metrics
 | 
					
						
							|  |  |  | func shouldMeterRequest(req *http.Request) bool { | 
					
						
							| 
									
										
										
										
											2021-09-05 00:07:24 +08:00
										 |  |  | 	return req.URL != nil && !strings.HasPrefix(req.URL.Path, minioReservedBucketPath+slashSeparator) | 
					
						
							| 
									
										
										
										
											2020-02-11 23:38:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MetricsTransport is a custom wrapper around Transport to track metrics
 | 
					
						
							|  |  |  | type MetricsTransport struct { | 
					
						
							|  |  |  | 	Transport *http.Transport | 
					
						
							| 
									
										
										
										
											2021-01-19 12:35:38 +08:00
										 |  |  | 	Metrics   *BackendMetrics | 
					
						
							| 
									
										
										
										
											2020-02-11 23:38:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RoundTrip implements the RoundTrip method for MetricsTransport
 | 
					
						
							|  |  |  | func (m MetricsTransport) RoundTrip(r *http.Request) (*http.Response, error) { | 
					
						
							|  |  |  | 	metered := shouldMeterRequest(r) | 
					
						
							| 
									
										
										
										
											2020-04-02 03:52:31 +08:00
										 |  |  | 	if metered && (r.Method == http.MethodPost || r.Method == http.MethodPut) { | 
					
						
							| 
									
										
										
										
											2020-02-11 23:38:01 +08:00
										 |  |  | 		m.Metrics.IncRequests(r.Method) | 
					
						
							| 
									
										
										
										
											2020-02-12 12:45:00 +08:00
										 |  |  | 		if r.ContentLength > 0 { | 
					
						
							|  |  |  | 			m.Metrics.IncBytesSent(uint64(r.ContentLength)) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-02-11 23:38:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// Make the request to the server.
 | 
					
						
							|  |  |  | 	resp, err := m.Transport.RoundTrip(r) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if metered && (r.Method == http.MethodGet || r.Method == http.MethodHead) { | 
					
						
							| 
									
										
										
										
											2020-04-02 03:52:31 +08:00
										 |  |  | 		m.Metrics.IncRequests(r.Method) | 
					
						
							|  |  |  | 		if resp.ContentLength > 0 { | 
					
						
							| 
									
										
										
										
											2020-02-12 12:45:00 +08:00
										 |  |  | 			m.Metrics.IncBytesReceived(uint64(resp.ContentLength)) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-02-11 23:38:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return resp, nil | 
					
						
							|  |  |  | } |