Use automatic URI encoding (#3352)

This commit is contained in:
Ramon de Klein
2024-06-05 23:48:27 +02:00
committed by GitHub
parent 72939e0cd7
commit 49c5f5a8f0
67 changed files with 398 additions and 875 deletions

View File

@@ -18,8 +18,6 @@ package api
import (
"context"
"encoding/base64"
b64 "encoding/base64"
"errors"
"fmt"
"io"
@@ -79,19 +77,8 @@ func registerObjectsHandlers(api *operations.ConsoleAPI) {
// download object
api.ObjectDownloadObjectHandler = objectApi.DownloadObjectHandlerFunc(func(params objectApi.DownloadObjectParams, session *models.Principal) middleware.Responder {
isFolder := false
ctx := params.HTTPRequest.Context()
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
apiErr := ErrorWithContext(ctx, err)
return objectApi.NewDownloadObjectDefault(400).WithPayload(apiErr.APIError)
}
prefix = string(decodedPrefix)
}
folders := strings.Split(prefix, "/")
folders := strings.Split(params.Prefix, "/")
if folders[len(folders)-1] == "" {
isFolder = true
}
@@ -197,12 +184,7 @@ func getListObjectsResponse(session *models.Principal, params objectApi.ListObje
var withVersions bool
var withMetadata bool
if params.Prefix != nil {
encodedPrefix := SanitizeEncodedPrefix(*params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
prefix = *params.Prefix
}
if params.Recursive != nil {
recursive = *params.Recursive
@@ -417,19 +399,10 @@ func parseRange(s string, size int64) ([]httpRange, error) {
func getDownloadObjectResponse(session *models.Principal, params objectApi.DownloadObjectParams) (middleware.Responder, *CodedAPIError) {
ctx := params.HTTPRequest.Context()
var prefix string
mClient, err := newMinioClient(session, getClientIP(params.HTTPRequest))
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
opts := minio.GetObjectOptions{}
@@ -437,7 +410,7 @@ func getDownloadObjectResponse(session *models.Principal, params objectApi.Downl
opts.VersionID = *params.VersionID
}
resp, err := mClient.GetObject(ctx, params.BucketName, prefix, opts)
resp, err := mClient.GetObject(ctx, params.BucketName, params.Prefix, opts)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -446,19 +419,11 @@ func getDownloadObjectResponse(session *models.Principal, params objectApi.Downl
defer resp.Close()
isPreview := params.Preview != nil && *params.Preview
// override filename is set
decodeOverride, err := base64.StdEncoding.DecodeString(*params.OverrideFileName)
if err != nil {
fmtError := ErrorWithContext(ctx, fmt.Errorf("unable to decode OverrideFileName: %v", err))
http.Error(rw, fmtError.APIError.DetailedMessage, http.StatusBadRequest)
return
}
overrideName := string(decodeOverride)
overrideName := *params.OverrideFileName
// indicate it's a download / inline content to the browser, and the size of the object
var filename string
prefixElements := strings.Split(prefix, "/")
prefixElements := strings.Split(params.Prefix, "/")
if len(prefixElements) > 0 && overrideName == "" {
if prefixElements[len(prefixElements)-1] == "" {
filename = prefixElements[len(prefixElements)-2]
@@ -475,7 +440,7 @@ func getDownloadObjectResponse(session *models.Principal, params objectApi.Downl
stat, err := resp.Stat()
if err != nil {
minErr := minio.ToErrorResponse(err)
fmtError := ErrorWithContext(ctx, fmt.Errorf("failed to get Stat() response from server for %s (version %s): %v", prefix, opts.VersionID, minErr.Error()))
fmtError := ErrorWithContext(ctx, fmt.Errorf("failed to get Stat() response from server for %s (version %s): %v", params.Prefix, opts.VersionID, minErr.Error()))
http.Error(rw, fmtError.APIError.DetailedMessage, http.StatusInternalServerError)
return
}
@@ -537,18 +502,9 @@ func getDownloadObjectResponse(session *models.Principal, params objectApi.Downl
func getDownloadFolderResponse(session *models.Principal, params objectApi.DownloadObjectParams) (middleware.Responder, *CodedAPIError) {
ctx := params.HTTPRequest.Context()
var prefix string
mClient, err := newMinioClient(session, getClientIP(params.HTTPRequest))
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
folders := strings.Split(prefix, "/")
folders := strings.Split(params.Prefix, "/")
if err != nil {
return nil, ErrorWithContext(ctx, err)
@@ -558,7 +514,7 @@ func getDownloadFolderResponse(session *models.Principal, params objectApi.Downl
ctx: ctx,
client: minioClient,
bucketName: params.BucketName,
prefix: prefix,
prefix: params.Prefix,
recursive: true,
withVersions: false,
withMetadata: false,
@@ -579,7 +535,7 @@ func getDownloadFolderResponse(session *models.Principal, params objectApi.Downl
defer zipw.Close()
for i, obj := range objects {
name := folder + objects[i].Name[len(prefix)-1:]
name := folder + objects[i].Name[len(params.Prefix)-1:]
object, err := mClient.GetObject(ctx, params.BucketName, obj.Name, minio.GetObjectOptions{})
if err != nil {
// Ignore errors, move to next
@@ -609,20 +565,8 @@ func getDownloadFolderResponse(session *models.Principal, params objectApi.Downl
defer resp.Close()
// indicate it's a download / inline content to the browser, and the size of the object
var prefixPath string
var filename string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
fmtError := ErrorWithContext(ctx, fmt.Errorf("unable to parse encoded prefix %s: %v", encodedPrefix, err))
http.Error(rw, fmtError.APIError.DetailedMessage, http.StatusInternalServerError)
return
}
prefixPath = string(decodedPrefix)
}
prefixElements := strings.Split(prefixPath, "/")
prefixElements := strings.Split(params.Prefix, "/")
if len(prefixElements) > 0 {
if prefixElements[len(prefixElements)-1] == "" {
filename = prefixElements[len(prefixElements)-2]
@@ -775,16 +719,7 @@ func getMultipleFilesDownloadResponse(session *models.Principal, params objectAp
func getDeleteObjectResponse(session *models.Principal, params objectApi.DeleteObjectParams) *CodedAPIError {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
s3Client, err := newS3BucketClient(session, params.BucketName, prefix, getClientIP(params.HTTPRequest))
s3Client, err := newS3BucketClient(session, params.BucketName, params.Prefix, getClientIP(params.HTTPRequest))
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -817,7 +752,7 @@ func getDeleteObjectResponse(session *models.Principal, params objectApi.DeleteO
return ErrorWithContext(ctx, err)
}
err = deleteObjects(ctx, mcClient, params.BucketName, prefix, version, rec, allVersions, nonCurrentVersions, bypass)
err = deleteObjects(ctx, mcClient, params.BucketName, params.Prefix, version, rec, allVersions, nonCurrentVersions, bypass)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1008,12 +943,7 @@ func getUploadObjectResponse(session *models.Principal, params objectApi.PostBuc
func uploadFiles(ctx context.Context, client MinioClient, params objectApi.PostBucketsBucketNameObjectsUploadParams) error {
var prefix string
if params.Prefix != nil {
encodedPrefix := SanitizeEncodedPrefix(*params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return err
}
prefix = string(decodedPrefix)
prefix = *params.Prefix
// trim any leading '/', since that is not expected
// for any object.
prefix = strings.TrimPrefix(prefix, "/")
@@ -1058,16 +988,7 @@ func uploadFiles(ctx context.Context, client MinioClient, params objectApi.PostB
func getShareObjectResponse(session *models.Principal, params objectApi.ShareObjectParams) (*string, *CodedAPIError) {
ctx := params.HTTPRequest.Context()
clientIP := utils.ClientIPFromContext(ctx)
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
s3Client, err := newS3BucketClient(session, params.BucketName, prefix, clientIP)
s3Client, err := newS3BucketClient(session, params.BucketName, params.Prefix, clientIP)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
@@ -1086,7 +1007,7 @@ func getShareObjectResponse(session *models.Principal, params objectApi.ShareObj
return url, nil
}
func getShareObjectURL(ctx context.Context, client MCClient, r *http.Request, versionID string, duration string) (url *string, err error) {
func getShareObjectURL(ctx context.Context, client MCClient, r *http.Request, versionID string, duration string) (*string, error) {
// default duration 7d if not defined
if strings.TrimSpace(duration) == "" {
duration = "168h"
@@ -1100,9 +1021,8 @@ func getShareObjectURL(ctx context.Context, client MCClient, r *http.Request, ve
return nil, pErr.Cause
}
encodedMinIOURL := b64.URLEncoding.EncodeToString([]byte(minioURL))
requestURL := getRequestURLWithScheme(r)
objURL := fmt.Sprintf("%s/api/v1/download-shared-object/%s", requestURL, encodedMinIOURL)
objURL := fmt.Sprintf("%s/api/v1/download-shared-object/%s", requestURL, url.PathEscape(minioURL))
return &objURL, nil
}
@@ -1129,16 +1049,7 @@ func getSetObjectLegalHoldResponse(session *models.Principal, params objectApi.P
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
err = setObjectLegalHold(ctx, minioClient, params.BucketName, prefix, params.VersionID, *params.Body.Status)
err = setObjectLegalHold(ctx, minioClient, params.BucketName, params.Prefix, params.VersionID, *params.Body.Status)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1164,16 +1075,7 @@ func getSetObjectRetentionResponse(session *models.Principal, params objectApi.P
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
err = setObjectRetention(ctx, minioClient, params.BucketName, params.VersionID, prefix, params.Body)
err = setObjectRetention(ctx, minioClient, params.BucketName, params.VersionID, params.Prefix, params.Body)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1216,16 +1118,7 @@ func deleteObjectRetentionResponse(session *models.Principal, params objectApi.D
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
err = deleteObjectRetention(ctx, minioClient, params.BucketName, prefix, params.VersionID)
err = deleteObjectRetention(ctx, minioClient, params.BucketName, params.Prefix, params.VersionID)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1250,16 +1143,7 @@ func getPutObjectTagsResponse(session *models.Principal, params objectApi.PutObj
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
err = putObjectTags(ctx, minioClient, params.BucketName, prefix, params.VersionID, params.Body.Tags)
err = putObjectTags(ctx, minioClient, params.BucketName, params.Prefix, params.VersionID, params.Body.Tags)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1287,18 +1171,7 @@ func getPutObjectRestoreResponse(session *models.Principal, params objectApi.Put
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
err = restoreObject(ctx, minioClient, params.BucketName, prefix, params.VersionID)
err = restoreObject(ctx, minioClient, params.BucketName, params.Prefix, params.VersionID)
if err != nil {
return ErrorWithContext(ctx, err)
}
@@ -1342,23 +1215,12 @@ func getObjectMetadataResponse(session *models.Principal, params objectApi.GetOb
// create a minioClient interface implementation
// defining the client to be used
minioClient := minioClient{client: mClient}
var prefix string
var versionID string
if params.Prefix != "" {
encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
if params.VersionID != nil {
versionID = *params.VersionID
}
objectInfo, err := getObjectInfo(ctx, minioClient, params.BucketName, prefix, versionID)
objectInfo, err := getObjectInfo(ctx, minioClient, params.BucketName, params.Prefix, versionID)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}