| 
									
										
										
										
											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/>.
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 07:23:42 +08:00
										 |  |  | package cmd | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-07-03 01:56:22 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2020-07-04 02:53:03 +08:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2019-02-24 14:14:24 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-02 05:59:40 +08:00
										 |  |  | 	"github.com/minio/minio/internal/logger" | 
					
						
							| 
									
										
										
										
											2023-01-23 19:12:47 +08:00
										 |  |  | 	"github.com/minio/mux" | 
					
						
							| 
									
										
										
										
											2018-08-18 03:52:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 03:57:37 +08:00
										 |  |  | 	"github.com/minio/pkg/v2/policy" | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Validate all the ListObjects query arguments, returns an APIErrorCode
 | 
					
						
							|  |  |  | // if one of the args do not meet the required conditions.
 | 
					
						
							| 
									
										
										
										
											2019-04-10 02:39:42 +08:00
										 |  |  | // Special conditions required by MinIO server are as below
 | 
					
						
							| 
									
										
										
										
											2022-08-27 03:52:29 +08:00
										 |  |  | //   - delimiter if set should be equal to '/', otherwise the request is rejected.
 | 
					
						
							|  |  |  | //   - marker if set should have a common prefix with 'prefix' param, otherwise
 | 
					
						
							|  |  |  | //     the request is rejected.
 | 
					
						
							| 
									
										
										
										
											2022-11-09 05:29:05 +08:00
										 |  |  | func validateListObjectsArgs(prefix, marker, delimiter, encodingType string, maxKeys int) APIErrorCode { | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 	// Max keys cannot be negative.
 | 
					
						
							|  |  |  | 	if maxKeys < 0 { | 
					
						
							|  |  |  | 		return ErrInvalidMaxKeys | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-24 14:14:24 +08:00
										 |  |  | 	if encodingType != "" { | 
					
						
							| 
									
										
										
										
											2021-11-17 01:28:29 +08:00
										 |  |  | 		// AWS S3 spec only supports 'url' encoding type
 | 
					
						
							|  |  |  | 		if !strings.EqualFold(encodingType, "url") { | 
					
						
							| 
									
										
										
										
											2019-02-24 14:14:24 +08:00
										 |  |  | 			return ErrInvalidEncodingMethod | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-09 05:29:05 +08:00
										 |  |  | 	if !IsValidObjectPrefix(prefix) { | 
					
						
							|  |  |  | 		return ErrInvalidObjectName | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if marker != "" && !HasPrefix(marker, prefix) { | 
					
						
							|  |  |  | 		return ErrNotImplemented | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 	return ErrNone | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-31 03:20:42 +08:00
										 |  |  | func (api objectAPIHandlers) ListObjectVersionsHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	api.listObjectVersionsHandler(w, r, false) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (api objectAPIHandlers) ListObjectVersionsMHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	api.listObjectVersionsHandler(w, r, true) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ListObjectVersionsHandler - GET Bucket Object versions
 | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | // You can use the versions subresource to list metadata about all
 | 
					
						
							|  |  |  | // of the versions of objects in a bucket.
 | 
					
						
							| 
									
										
										
										
											2023-03-31 03:20:42 +08:00
										 |  |  | func (api objectAPIHandlers) listObjectVersionsHandler(w http.ResponseWriter, r *http.Request, metadata bool) { | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	ctx := newContext(r, w, "ListObjectVersions") | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	bucket := vars["bucket"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	objectAPI := api.ObjectAPI() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 09:25:06 +08:00
										 |  |  | 	if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketVersionsAction, bucket, ""); s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL) | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-04-06 22:52:35 +08:00
										 |  |  | 	var checkObjMeta metaCheckFn | 
					
						
							|  |  |  | 	if metadata { | 
					
						
							|  |  |  | 		checkObjMeta = func(name string, action policy.Action) (s3Err APIErrorCode) { | 
					
						
							|  |  |  | 			return checkRequestAuthType(ctx, r, action, bucket, name) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	urlValues := r.Form | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Extract all the listBucketVersions query params to their native values.
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	prefix, marker, delimiter, maxkeys, encodingType, versionIDMarker, errCode := getListBucketObjectVersionsArgs(urlValues) | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 	if errCode != ErrNone { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(errCode), r.URL) | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate the query params before beginning to serve the request.
 | 
					
						
							| 
									
										
										
										
											2022-11-09 05:29:05 +08:00
										 |  |  | 	if s3Error := validateListObjectsArgs(prefix, marker, delimiter, encodingType, maxkeys); s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL) | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	listObjectVersions := objectAPI.ListObjectVersions | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-18 15:03:17 +08:00
										 |  |  | 	// Initiate a list object versions operation based on the input params.
 | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 	// On success would return back ListObjectsInfo object to be
 | 
					
						
							|  |  |  | 	// marshaled into S3 compatible XML header.
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 	listObjectVersionsInfo, err := listObjectVersions(ctx, bucket, prefix, marker, versionIDMarker, delimiter, maxkeys) | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 02:42:03 +08:00
										 |  |  | 	if err = DecryptETags(ctx, GlobalKMS, listObjectVersionsInfo.Objects); err != nil { | 
					
						
							| 
									
										
										
										
											2022-03-26 06:01:41 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-04-06 22:52:35 +08:00
										 |  |  | 	response := generateListVersionsResponse(bucket, prefix, marker, versionIDMarker, delimiter, encodingType, maxkeys, listObjectVersionsInfo, checkObjMeta) | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Write success response.
 | 
					
						
							| 
									
										
										
										
											2023-01-17 07:38:33 +08:00
										 |  |  | 	writeSuccessResponseXML(w, encodeResponseList(response)) | 
					
						
							| 
									
										
										
										
											2019-08-20 05:02:54 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-21 17:54:49 +08:00
										 |  |  | // ListObjectsV2MHandler - GET Bucket (List Objects) Version 2 with metadata.
 | 
					
						
							|  |  |  | // --------------------------
 | 
					
						
							| 
									
										
										
										
											2021-09-01 08:18:13 +08:00
										 |  |  | // This implementation of the GET operation returns some or all (up to 1000)
 | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | // of the objects in a bucket. You can use the request parameters as selection
 | 
					
						
							| 
									
										
										
										
											2019-11-21 17:54:49 +08:00
										 |  |  | // criteria to return a subset of the objects in a bucket.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: It is recommended that this API to be used for application development.
 | 
					
						
							|  |  |  | // MinIO continues to support ListObjectsV1 and V2 for supporting legacy tools.
 | 
					
						
							|  |  |  | func (api objectAPIHandlers) ListObjectsV2MHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "ListObjectsV2M") | 
					
						
							| 
									
										
										
										
											2023-04-06 22:52:35 +08:00
										 |  |  | 	api.listObjectsV2Handler(ctx, w, r, true) | 
					
						
							| 
									
										
										
										
											2019-11-21 17:54:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | // ListObjectsV2Handler - GET Bucket (List Objects) Version 2.
 | 
					
						
							|  |  |  | // --------------------------
 | 
					
						
							| 
									
										
										
										
											2021-09-01 08:18:13 +08:00
										 |  |  | // This implementation of the GET operation returns some or all (up to 1000)
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | // of the objects in a bucket. You can use the request parameters as selection
 | 
					
						
							|  |  |  | // criteria to return a subset of the objects in a bucket.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: It is recommended that this API to be used for application development.
 | 
					
						
							| 
									
										
										
										
											2019-04-10 02:39:42 +08:00
										 |  |  | // MinIO continues to support ListObjectsV1 for supporting legacy tools.
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2018-07-21 09:46:32 +08:00
										 |  |  | 	ctx := newContext(r, w, "ListObjectsV2") | 
					
						
							| 
									
										
										
										
											2023-04-06 22:52:35 +08:00
										 |  |  | 	api.listObjectsV2Handler(ctx, w, r, false) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-15 03:01:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-06 22:52:35 +08:00
										 |  |  | // listObjectsV2Handler performs listing either with or without extra metadata.
 | 
					
						
							|  |  |  | func (api objectAPIHandlers) listObjectsV2Handler(ctx context.Context, w http.ResponseWriter, r *http.Request, metadata bool) { | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2018-10-13 03:25:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	bucket := vars["bucket"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 	objectAPI := api.ObjectAPI() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL) | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-11-22 05:51:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-06 22:52:35 +08:00
										 |  |  | 	var checkObjMeta metaCheckFn | 
					
						
							|  |  |  | 	if metadata { | 
					
						
							|  |  |  | 		checkObjMeta = func(name string, action policy.Action) (s3Err APIErrorCode) { | 
					
						
							|  |  |  | 			return checkRequestAuthType(ctx, r, action, bucket, name) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	urlValues := r.Form | 
					
						
							| 
									
										
										
										
											2018-06-26 03:35:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 	// Extract all the listObjectsV2 query params to their native values.
 | 
					
						
							| 
									
										
										
										
											2019-02-24 14:14:24 +08:00
										 |  |  | 	prefix, token, startAfter, delimiter, fetchOwner, maxKeys, encodingType, errCode := getListObjectsV2Args(urlValues) | 
					
						
							| 
									
										
										
										
											2018-06-26 03:35:43 +08:00
										 |  |  | 	if errCode != ErrNone { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(errCode), r.URL) | 
					
						
							| 
									
										
										
										
											2018-06-26 03:35:43 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-11 01:44:38 +08:00
										 |  |  | 	// Validate the query params before beginning to serve the request.
 | 
					
						
							| 
									
										
										
										
											2022-11-09 05:29:05 +08:00
										 |  |  | 	if s3Error := validateListObjectsArgs(prefix, token, delimiter, encodingType, maxKeys); s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL) | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-02-12 17:25:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 23:17:03 +08:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		listObjectsV2Info ListObjectsV2Info | 
					
						
							|  |  |  | 		err               error | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if r.Header.Get(xMinIOExtract) == "true" && strings.Contains(prefix, archivePattern) { | 
					
						
							| 
									
										
										
										
											2024-01-18 15:03:17 +08:00
										 |  |  | 		// Initiate a list objects operation inside a zip file based in the input params
 | 
					
						
							| 
									
										
										
										
											2021-06-10 23:17:03 +08:00
										 |  |  | 		listObjectsV2Info, err = listObjectsV2InArchive(ctx, objectAPI, bucket, prefix, token, delimiter, maxKeys, fetchOwner, startAfter) | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2024-01-18 15:03:17 +08:00
										 |  |  | 		// Initiate a list objects operation based on the input params.
 | 
					
						
							| 
									
										
										
										
											2021-06-10 23:17:03 +08:00
										 |  |  | 		// On success would return back ListObjectsInfo object to be
 | 
					
						
							|  |  |  | 		// marshaled into S3 compatible XML header.
 | 
					
						
							|  |  |  | 		listObjectsV2Info, err = objectAPI.ListObjectsV2(ctx, bucket, prefix, token, delimiter, maxKeys, fetchOwner, startAfter) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 02:42:03 +08:00
										 |  |  | 	if err = DecryptETags(ctx, GlobalKMS, listObjectsV2Info.Objects); err != nil { | 
					
						
							| 
									
										
										
										
											2022-03-26 06:01:41 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-02 03:37:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-29 00:18:35 +08:00
										 |  |  | 	response := generateListObjectsV2Response(bucket, prefix, token, listObjectsV2Info.NextContinuationToken, startAfter, | 
					
						
							| 
									
										
										
										
											2019-11-21 17:54:49 +08:00
										 |  |  | 		delimiter, encodingType, fetchOwner, listObjectsV2Info.IsTruncated, | 
					
						
							| 
									
										
										
										
											2023-04-06 22:52:35 +08:00
										 |  |  | 		maxKeys, listObjectsV2Info.Objects, listObjectsV2Info.Prefixes, checkObjMeta) | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 	// Write success response.
 | 
					
						
							| 
									
										
										
										
											2023-01-17 07:38:33 +08:00
										 |  |  | 	writeSuccessResponseXML(w, encodeResponseList(response)) | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-04 10:27:13 +08:00
										 |  |  | func parseRequestToken(token string) (subToken string, nodeIndex int) { | 
					
						
							|  |  |  | 	if token == "" { | 
					
						
							|  |  |  | 		return token, -1 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-08-12 04:12:35 +08:00
										 |  |  | 	i := strings.Index(token, ":") | 
					
						
							| 
									
										
										
										
											2020-07-04 02:53:03 +08:00
										 |  |  | 	if i < 0 { | 
					
						
							| 
									
										
										
										
											2020-07-04 10:27:13 +08:00
										 |  |  | 		return token, -1 | 
					
						
							| 
									
										
										
										
											2020-07-04 02:53:03 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	nodeIndex, err := strconv.Atoi(token[i+1:]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-07-04 10:27:13 +08:00
										 |  |  | 		return token, -1 | 
					
						
							| 
									
										
										
										
											2020-07-03 01:56:22 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-04 02:53:03 +08:00
										 |  |  | 	subToken = token[:i] | 
					
						
							| 
									
										
										
										
											2020-07-04 10:27:13 +08:00
										 |  |  | 	return subToken, nodeIndex | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func proxyRequestByToken(ctx context.Context, w http.ResponseWriter, r *http.Request, token string) (string, bool) { | 
					
						
							|  |  |  | 	subToken, nodeIndex := parseRequestToken(token) | 
					
						
							|  |  |  | 	if nodeIndex > 0 { | 
					
						
							|  |  |  | 		return subToken, proxyRequestByNodeIndex(ctx, w, r, nodeIndex) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return subToken, false | 
					
						
							| 
									
										
										
										
											2020-07-04 02:53:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func proxyRequestByNodeIndex(ctx context.Context, w http.ResponseWriter, r *http.Request, index int) (success bool) { | 
					
						
							|  |  |  | 	if len(globalProxyEndpoints) == 0 { | 
					
						
							| 
									
										
										
										
											2020-07-03 01:56:22 +08:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-04 02:53:03 +08:00
										 |  |  | 	if index < 0 || index >= len(globalProxyEndpoints) { | 
					
						
							| 
									
										
										
										
											2020-07-03 01:56:22 +08:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-04 02:53:03 +08:00
										 |  |  | 	ep := globalProxyEndpoints[index] | 
					
						
							|  |  |  | 	if ep.IsLocal { | 
					
						
							|  |  |  | 		return false | 
					
						
							| 
									
										
										
										
											2020-07-03 01:56:22 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-04 02:53:03 +08:00
										 |  |  | 	return proxyRequest(ctx, w, r, ep) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | // ListObjectsV1Handler - GET Bucket (List Objects) Version 1.
 | 
					
						
							|  |  |  | // --------------------------
 | 
					
						
							| 
									
										
										
										
											2021-09-01 08:18:13 +08:00
										 |  |  | // This implementation of the GET operation returns some or all (up to 1000)
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | // of the objects in a bucket. You can use the request parameters as selection
 | 
					
						
							|  |  |  | // criteria to return a subset of the objects in a bucket.
 | 
					
						
							|  |  |  | func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2018-07-21 09:46:32 +08:00
										 |  |  | 	ctx := newContext(r, w, "ListObjectsV1") | 
					
						
							| 
									
										
										
										
											2018-03-15 03:01:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2018-10-13 03:25:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	bucket := vars["bucket"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 	objectAPI := api.ObjectAPI() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 06:53:30 +08:00
										 |  |  | 	if s3Error := checkRequestAuthType(ctx, r, policy.ListBucketAction, bucket, ""); s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL) | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 14:26:06 +08:00
										 |  |  | 	// Extract all the listObjectsV1 query params to their native values.
 | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	prefix, marker, delimiter, maxKeys, encodingType, s3Error := getListObjectsV1Args(r.Form) | 
					
						
							| 
									
										
										
										
											2018-10-18 22:31:46 +08:00
										 |  |  | 	if s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL) | 
					
						
							| 
									
										
										
										
											2018-10-18 22:31:46 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-12 17:25:52 +08:00
										 |  |  | 	// Validate all the query params before beginning to serve the request.
 | 
					
						
							| 
									
										
										
										
											2022-11-09 05:29:05 +08:00
										 |  |  | 	if s3Error := validateListObjectsArgs(prefix, marker, delimiter, encodingType, maxKeys); s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL) | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-02-12 17:25:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 05:14:06 +08:00
										 |  |  | 	listObjects := objectAPI.ListObjects | 
					
						
							| 
									
										
										
										
											2019-02-12 17:25:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-18 15:03:17 +08:00
										 |  |  | 	// Initiate a list objects operation based on the input params.
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 	// On success would return back ListObjectsInfo object to be
 | 
					
						
							| 
									
										
										
										
											2018-06-29 07:02:02 +08:00
										 |  |  | 	// marshaled into S3 compatible XML header.
 | 
					
						
							| 
									
										
										
										
											2018-03-29 05:14:06 +08:00
										 |  |  | 	listObjectsInfo, err := listObjects(ctx, bucket, prefix, marker, delimiter, maxKeys) | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-06-18 11:27:04 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-02 03:37:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 02:42:03 +08:00
										 |  |  | 	if err = DecryptETags(ctx, GlobalKMS, listObjectsInfo.Objects); err != nil { | 
					
						
							| 
									
										
										
										
											2022-03-26 06:01:41 +08:00
										 |  |  | 		writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-25 02:19:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-24 14:14:24 +08:00
										 |  |  | 	response := generateListObjectsV1Response(bucket, prefix, marker, delimiter, encodingType, maxKeys, listObjectsInfo) | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | 	// Write success response.
 | 
					
						
							| 
									
										
										
										
											2023-01-17 07:38:33 +08:00
										 |  |  | 	writeSuccessResponseXML(w, encodeResponseList(response)) | 
					
						
							| 
									
										
										
										
											2016-07-18 03:32:05 +08:00
										 |  |  | } |