diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 25c00d99b..46cba6872 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -1594,7 +1594,7 @@ func mustTrace(entry interface{}, trcAll, errOnly bool) bool { if !ok { return false } - trace := trcAll || !hasPrefix(trcInfo.ReqInfo.Path, minioReservedBucketPath+slashSeparator) + trace := trcAll || !hasPrefix(trcInfo.ReqInfo.Path, minioReservedBucketPath+SlashSeparator) if errOnly { return trace && trcInfo.RespInfo.StatusCode >= http.StatusBadRequest } diff --git a/cmd/admin-heal-ops.go b/cmd/admin-heal-ops.go index 4935ea0e3..8617d2ffc 100644 --- a/cmd/admin-heal-ops.go +++ b/cmd/admin-heal-ops.go @@ -587,9 +587,9 @@ func (h *healSequence) healItemsFromSourceCh() error { var itemType madmin.HealItemType switch { - case path == "/": + case path == SlashSeparator: itemType = madmin.HealItemMetadata - case !strings.Contains(path, "/"): + case !strings.Contains(path, SlashSeparator): itemType = madmin.HealItemBucket default: itemType = madmin.HealItemObject @@ -693,7 +693,7 @@ func (h *healSequence) healDiskFormat() error { return errServerNotInitialized } - return h.queueHealTask("/", madmin.HealItemMetadata) + return h.queueHealTask(SlashSeparator, madmin.HealItemMetadata) } // healBuckets - check for all buckets heal or just particular bucket. diff --git a/cmd/api-resources_test.go b/cmd/api-resources_test.go index 10140c2df..9b0c98799 100644 --- a/cmd/api-resources_test.go +++ b/cmd/api-resources_test.go @@ -36,7 +36,7 @@ func TestListObjectsV2Resources(t *testing.T) { "prefix": []string{"photos/"}, "continuation-token": []string{"token"}, "start-after": []string{"start-after"}, - "delimiter": []string{"/"}, + "delimiter": []string{SlashSeparator}, "fetch-owner": []string{"true"}, "max-keys": []string{"100"}, "encoding-type": []string{"gzip"}, @@ -44,7 +44,7 @@ func TestListObjectsV2Resources(t *testing.T) { prefix: "photos/", token: "token", startAfter: "start-after", - delimiter: "/", + delimiter: SlashSeparator, fetchOwner: true, maxKeys: 100, encodingType: "gzip", @@ -55,14 +55,14 @@ func TestListObjectsV2Resources(t *testing.T) { "prefix": []string{"photos/"}, "continuation-token": []string{"token"}, "start-after": []string{"start-after"}, - "delimiter": []string{"/"}, + "delimiter": []string{SlashSeparator}, "fetch-owner": []string{"true"}, "encoding-type": []string{"gzip"}, }, prefix: "photos/", token: "token", startAfter: "start-after", - delimiter: "/", + delimiter: SlashSeparator, fetchOwner: true, maxKeys: 1000, encodingType: "gzip", @@ -73,7 +73,7 @@ func TestListObjectsV2Resources(t *testing.T) { "prefix": []string{"photos/"}, "continuation-token": []string{""}, "start-after": []string{"start-after"}, - "delimiter": []string{"/"}, + "delimiter": []string{SlashSeparator}, "fetch-owner": []string{"true"}, "encoding-type": []string{"gzip"}, }, @@ -130,13 +130,13 @@ func TestListObjectsV1Resources(t *testing.T) { values: url.Values{ "prefix": []string{"photos/"}, "marker": []string{"test"}, - "delimiter": []string{"/"}, + "delimiter": []string{SlashSeparator}, "max-keys": []string{"100"}, "encoding-type": []string{"gzip"}, }, prefix: "photos/", marker: "test", - delimiter: "/", + delimiter: SlashSeparator, maxKeys: 100, encodingType: "gzip", }, @@ -144,12 +144,12 @@ func TestListObjectsV1Resources(t *testing.T) { values: url.Values{ "prefix": []string{"photos/"}, "marker": []string{"test"}, - "delimiter": []string{"/"}, + "delimiter": []string{SlashSeparator}, "encoding-type": []string{"gzip"}, }, prefix: "photos/", marker: "test", - delimiter: "/", + delimiter: SlashSeparator, maxKeys: 1000, encodingType: "gzip", }, diff --git a/cmd/api-response.go b/cmd/api-response.go index d0964ff70..72fc01719 100644 --- a/cmd/api-response.go +++ b/cmd/api-response.go @@ -293,14 +293,14 @@ func getObjectLocation(r *http.Request, domains []string, bucket, object string) } u := &url.URL{ Host: r.Host, - Path: path.Join(slashSeparator, bucket, object), + Path: path.Join(SlashSeparator, bucket, object), Scheme: proto, } // If domain is set then we need to use bucket DNS style. for _, domain := range domains { if strings.Contains(r.Host, domain) { u.Host = bucket + "." + r.Host - u.Path = path.Join(slashSeparator, object) + u.Path = path.Join(SlashSeparator, object) break } } diff --git a/cmd/api-router.go b/cmd/api-router.go index 328baa905..18ead4f37 100644 --- a/cmd/api-router.go +++ b/cmd/api-router.go @@ -48,7 +48,7 @@ func registerAPIRouter(router *mux.Router, encryptionEnabled, allowSSEKMS bool) } // API Router - apiRouter := router.PathPrefix("/").Subrouter() + apiRouter := router.PathPrefix(SlashSeparator).Subrouter() var routers []*mux.Router for _, domainName := range globalDomainNames { routers = append(routers, apiRouter.Host("{bucket:.+}."+domainName).Subrouter()) @@ -157,7 +157,7 @@ func registerAPIRouter(router *mux.Router, encryptionEnabled, allowSSEKMS bool) /// Root operation // ListBuckets - apiRouter.Methods(http.MethodGet).Path("/").HandlerFunc(httpTraceAll(api.ListBucketsHandler)) + apiRouter.Methods(http.MethodGet).Path(SlashSeparator).HandlerFunc(httpTraceAll(api.ListBucketsHandler)) // If none of the routes match. apiRouter.NotFoundHandler = http.HandlerFunc(httpTraceAll(notFoundHandler)) diff --git a/cmd/auth-handler_test.go b/cmd/auth-handler_test.go index 75712295e..858f12b1c 100644 --- a/cmd/auth-handler_test.go +++ b/cmd/auth-handler_test.go @@ -44,7 +44,7 @@ func TestGetRequestAuthType(t *testing.T) { URL: &url.URL{ Host: "127.0.0.1:9000", Scheme: httpScheme, - Path: "/", + Path: SlashSeparator, }, Header: http.Header{ "Authorization": []string{"AWS4-HMAC-SHA256 "}, @@ -62,7 +62,7 @@ func TestGetRequestAuthType(t *testing.T) { URL: &url.URL{ Host: "127.0.0.1:9000", Scheme: httpScheme, - Path: "/", + Path: SlashSeparator, }, Header: http.Header{ "Authorization": []string{"Bearer 12313123"}, @@ -77,7 +77,7 @@ func TestGetRequestAuthType(t *testing.T) { URL: &url.URL{ Host: "127.0.0.1:9000", Scheme: httpScheme, - Path: "/", + Path: SlashSeparator, }, Header: http.Header{ "Authorization": []string{""}, @@ -92,7 +92,7 @@ func TestGetRequestAuthType(t *testing.T) { URL: &url.URL{ Host: "127.0.0.1:9000", Scheme: httpScheme, - Path: "/", + Path: SlashSeparator, RawQuery: "X-Amz-Credential=EXAMPLEINVALIDEXAMPL%2Fs3%2F20160314%2Fus-east-1", }, }, @@ -105,7 +105,7 @@ func TestGetRequestAuthType(t *testing.T) { URL: &url.URL{ Host: "127.0.0.1:9000", Scheme: httpScheme, - Path: "/", + Path: SlashSeparator, }, Header: http.Header{ "Content-Type": []string{"multipart/form-data"}, diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index ea3892245..62517756a 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -650,7 +650,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h return } if objectAPI.IsEncryptionSupported() { - if hasServerSideEncryptionHeader(formValues) && !hasSuffix(object, slashSeparator) { // handle SSE-C and SSE-S3 requests + if hasServerSideEncryptionHeader(formValues) && !hasSuffix(object, SlashSeparator) { // handle SSE-C and SSE-S3 requests var reader io.Reader var key []byte if crypto.SSEC.IsRequested(formValues) { diff --git a/cmd/bucket-handlers_test.go b/cmd/bucket-handlers_test.go index 78ae30dee..6971d9f17 100644 --- a/cmd/bucket-handlers_test.go +++ b/cmd/bucket-handlers_test.go @@ -69,7 +69,7 @@ func testGetBucketLocationHandler(obj ObjectLayer, instanceType, bucketName stri expectedRespStatus: http.StatusForbidden, locationResponse: []byte(""), errorResponse: APIErrorResponse{ - Resource: "/" + bucketName + "/", + Resource: SlashSeparator + bucketName + SlashSeparator, Code: "InvalidAccessKeyId", Message: "The access key ID you provided does not exist in our records.", }, @@ -394,7 +394,7 @@ func testListMultipartUploadsHandler(obj ObjectLayer, instanceType, bucketName s prefix: "", keyMarker: "", uploadIDMarker: "", - delimiter: "/", + delimiter: SlashSeparator, maxUploads: "100", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, diff --git a/cmd/certs.go b/cmd/certs.go index ef263e83b..c886d72b7 100644 --- a/cmd/certs.go +++ b/cmd/certs.go @@ -87,7 +87,7 @@ func getRootCAs(certsCAsDir string) (*x509.CertPool, error) { // Load all custom CA files. for _, fi := range fis { // Skip all directories. - if hasSuffix(fi, slashSeparator) { + if hasSuffix(fi, SlashSeparator) { continue } caCert, err := ioutil.ReadFile(pathJoin(certsCAsDir, fi)) diff --git a/cmd/config-migrate_test.go b/cmd/config-migrate_test.go index 46083322d..53c53b2d3 100644 --- a/cmd/config-migrate_test.go +++ b/cmd/config-migrate_test.go @@ -175,7 +175,7 @@ func TestServerConfigMigrateV2toV33(t *testing.T) { } defer os.RemoveAll(fsDir) - configPath := rootPath + "/" + minioConfigFile + configPath := rootPath + SlashSeparator + minioConfigFile // Create a corrupted config file if err := ioutil.WriteFile(configPath, []byte("{ \"version\":\"2\","), 0644); err != nil { @@ -238,7 +238,7 @@ func TestServerConfigMigrateFaultyConfig(t *testing.T) { defer os.RemoveAll(rootPath) globalConfigDir = &ConfigDir{path: rootPath} - configPath := rootPath + "/" + minioConfigFile + configPath := rootPath + SlashSeparator + minioConfigFile // Create a corrupted config file if err := ioutil.WriteFile(configPath, []byte("{ \"version\":\"2\", \"test\":"), 0644); err != nil { @@ -335,7 +335,7 @@ func TestServerConfigMigrateCorruptedConfig(t *testing.T) { defer os.RemoveAll(rootPath) globalConfigDir = &ConfigDir{path: rootPath} - configPath := rootPath + "/" + minioConfigFile + configPath := rootPath + SlashSeparator + minioConfigFile for i := 3; i <= 17; i++ { // Create a corrupted config file diff --git a/cmd/disk-cache-config.go b/cmd/disk-cache-config.go index 16d8292b3..429752603 100644 --- a/cmd/disk-cache-config.go +++ b/cmd/disk-cache-config.go @@ -109,7 +109,7 @@ func parseCacheExcludes(excludes []string) ([]string, error) { if len(e) == 0 { return nil, uiErrInvalidCacheExcludesValue(nil).Msg("cache exclude path (%s) cannot be empty", e) } - if hasPrefix(e, slashSeparator) { + if hasPrefix(e, SlashSeparator) { return nil, uiErrInvalidCacheExcludesValue(nil).Msg("cache exclude pattern (%s) cannot start with / as prefix", e) } } diff --git a/cmd/disk-cache-fs.go b/cmd/disk-cache-fs.go index 18aa2d1c8..36ed85245 100644 --- a/cmd/disk-cache-fs.go +++ b/cmd/disk-cache-fs.go @@ -182,7 +182,7 @@ func (cfs *cacheFSObjects) purgeTrash() { // Purge cache entries that were not accessed. func (cfs *cacheFSObjects) purge() { - delimiter := slashSeparator + delimiter := SlashSeparator maxKeys := 1000 ctx := context.Background() for { diff --git a/cmd/disk-cache.go b/cmd/disk-cache.go index c1ab3b398..679f87b01 100644 --- a/cmd/disk-cache.go +++ b/cmd/disk-cache.go @@ -395,7 +395,7 @@ func listDirCacheFactory(isLeaf func(string, string) bool, disks []*cacheFSObjec for i := range entries { if isLeaf(bucket, entries[i]) { - entries[i] = strings.TrimSuffix(entries[i], slashSeparator) + entries[i] = strings.TrimSuffix(entries[i], SlashSeparator) } } @@ -432,7 +432,7 @@ func (c cacheObjects) listCacheObjects(ctx context.Context, bucket, prefix, mark var nextMarker string recursive := true - if delimiter == slashSeparator { + if delimiter == SlashSeparator { recursive = false } walkResultCh, endWalkCh := c.listPool.Release(listParams{bucket, recursive, marker, prefix, false}) @@ -460,7 +460,7 @@ func (c cacheObjects) listCacheObjects(ctx context.Context, bucket, prefix, mark entry := walkResult.entry var objInfo ObjectInfo - if hasSuffix(entry, slashSeparator) { + if hasSuffix(entry, SlashSeparator) { // Object name needs to be full path. objInfo.Bucket = bucket objInfo.Name = entry @@ -502,7 +502,7 @@ func (c cacheObjects) listCacheObjects(ctx context.Context, bucket, prefix, mark result = ListObjectsInfo{IsTruncated: !eof} for _, objInfo := range objInfos { result.NextMarker = objInfo.Name - if objInfo.IsDir && delimiter == slashSeparator { + if objInfo.IsDir && delimiter == SlashSeparator { result.Prefixes = append(result.Prefixes, objInfo.Name) continue } diff --git a/cmd/disk-usage.go b/cmd/disk-usage.go index b14e19510..c4522cabc 100644 --- a/cmd/disk-usage.go +++ b/cmd/disk-usage.go @@ -23,7 +23,7 @@ import ( // getDiskUsage walks the file tree rooted at root, calling usageFn // for each file or directory in the tree, including root. func getDiskUsage(ctx context.Context, root string, usageFn usageFunc) error { - return walk(ctx, root+slashSeparator, usageFn) + return walk(ctx, root+SlashSeparator, usageFn) } type usageFunc func(ctx context.Context, entry string) error @@ -34,7 +34,7 @@ func walk(ctx context.Context, path string, usageFn usageFunc) error { return err } - if !hasSuffix(path, slashSeparator) { + if !hasSuffix(path, SlashSeparator) { return nil } diff --git a/cmd/endpoint.go b/cmd/endpoint.go index e5f0b3e02..c5f79d9d9 100644 --- a/cmd/endpoint.go +++ b/cmd/endpoint.go @@ -100,7 +100,7 @@ func (endpoint *Endpoint) UpdateIsLocal() error { func NewEndpoint(arg string) (ep Endpoint, e error) { // isEmptyPath - check whether given path is not empty. isEmptyPath := func(path string) bool { - return path == "" || path == "/" || path == `\` + return path == "" || path == SlashSeparator || path == `\` } if isEmptyPath(arg) { @@ -152,7 +152,7 @@ func NewEndpoint(arg string) (ep Endpoint, e error) { return ep, fmt.Errorf("empty or root path is not supported in URL endpoint") } - // On windows having a preceding "/" will cause problems, if the + // On windows having a preceding SlashSeparator will cause problems, if the // command line already has C:/= 0; i-- { p := pfxSlice[i] @@ -401,10 +400,10 @@ func (l *s3EncObjects) ListMultipartUploads(ctx context.Context, bucket string, if e != nil { return } - lmi.KeyMarker = strings.TrimSuffix(lmi.KeyMarker, getGWContentPath("/")) - lmi.NextKeyMarker = strings.TrimSuffix(lmi.NextKeyMarker, getGWContentPath("/")) + lmi.KeyMarker = strings.TrimSuffix(lmi.KeyMarker, getGWContentPath(minio.SlashSeparator)) + lmi.NextKeyMarker = strings.TrimSuffix(lmi.NextKeyMarker, getGWContentPath(minio.SlashSeparator)) for i := range lmi.Uploads { - lmi.Uploads[i].Object = strings.TrimSuffix(lmi.Uploads[i].Object, getGWContentPath("/")) + lmi.Uploads[i].Object = strings.TrimSuffix(lmi.Uploads[i].Object, getGWContentPath(minio.SlashSeparator)) } return } diff --git a/cmd/generic-handlers.go b/cmd/generic-handlers.go index d326fcc1f..f8766ed4c 100644 --- a/cmd/generic-handlers.go +++ b/cmd/generic-handlers.go @@ -153,7 +153,7 @@ func containsReservedMetadata(header http.Header) bool { // Reserved bucket. const ( minioReservedBucket = "minio" - minioReservedBucketPath = "/" + minioReservedBucket + minioReservedBucketPath = SlashSeparator + minioReservedBucket ) // Adds redirect rules for incoming requests. @@ -172,10 +172,10 @@ func setBrowserRedirectHandler(h http.Handler) http.Handler { // browser requests. func getRedirectLocation(urlPath string) (rLocation string) { if urlPath == minioReservedBucketPath { - rLocation = minioReservedBucketPath + "/" + rLocation = minioReservedBucketPath + SlashSeparator } if contains([]string{ - "/", + SlashSeparator, "/webrpc", "/login", "/favicon.ico", @@ -229,7 +229,7 @@ func guessIsRPCReq(req *http.Request) bool { return false } return req.Method == http.MethodPost && - strings.HasPrefix(req.URL.Path, minioReservedBucketPath+"/") + strings.HasPrefix(req.URL.Path, minioReservedBucketPath+SlashSeparator) } func (h redirectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -258,7 +258,7 @@ func setBrowserCacheControlHandler(h http.Handler) http.Handler { func (h cacheControlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet && guessIsBrowserReq(r) { // For all browser requests set appropriate Cache-Control policies - if hasPrefix(r.URL.Path, minioReservedBucketPath+"/") { + if hasPrefix(r.URL.Path, minioReservedBucketPath+SlashSeparator) { if hasSuffix(r.URL.Path, ".js") || r.URL.Path == minioReservedBucketPath+"/favicon.ico" { // For assets set cache expiry of one year. For each release, the name // of the asset name will change and hence it can not be served from cache. @@ -276,7 +276,7 @@ func (h cacheControlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Check to allow access to the reserved "bucket" `/minio` for Admin // API requests. func isAdminReq(r *http.Request) bool { - return strings.HasPrefix(r.URL.Path, adminAPIPathPrefix+"/") + return strings.HasPrefix(r.URL.Path, adminAPIPathPrefix+SlashSeparator) } // Adds verification for incoming paths. @@ -596,7 +596,7 @@ const ( // such as ".." and "." func hasBadPathComponent(path string) bool { path = strings.TrimSpace(path) - for _, p := range strings.Split(path, slashSeparator) { + for _, p := range strings.Split(path, SlashSeparator) { switch strings.TrimSpace(p) { case dotdotComponent: return true diff --git a/cmd/generic-handlers_test.go b/cmd/generic-handlers_test.go index 24f81334b..a7f98d78f 100644 --- a/cmd/generic-handlers_test.go +++ b/cmd/generic-handlers_test.go @@ -35,12 +35,12 @@ func TestRedirectLocation(t *testing.T) { { // 1. When urlPath is '/minio' urlPath: minioReservedBucketPath, - location: minioReservedBucketPath + "/", + location: minioReservedBucketPath + SlashSeparator, }, { // 2. When urlPath is '/' - urlPath: "/", - location: minioReservedBucketPath + "/", + urlPath: SlashSeparator, + location: minioReservedBucketPath + SlashSeparator, }, { // 3. When urlPath is '/webrpc' diff --git a/cmd/handler-utils.go b/cmd/handler-utils.go index 69f2905fa..981c739c4 100644 --- a/cmd/handler-utils.go +++ b/cmd/handler-utils.go @@ -95,8 +95,8 @@ func isMetadataReplace(h http.Header) bool { // Splits an incoming path into bucket and object components. func path2BucketAndObject(path string) (bucket, object string) { // Skip the first element if it is '/', split the rest. - path = strings.TrimPrefix(path, "/") - pathComponents := strings.SplitN(path, "/", 2) + path = strings.TrimPrefix(path, SlashSeparator) + pathComponents := strings.SplitN(path, SlashSeparator, 2) // Save the bucket and object extracted from path. switch len(pathComponents) { @@ -370,7 +370,7 @@ func getResource(path string, host string, domains []string) (string, error) { continue } bucket := strings.TrimSuffix(host, "."+domain) - return slashSeparator + pathJoin(bucket, path), nil + return SlashSeparator + pathJoin(bucket, path), nil } return path, nil } diff --git a/cmd/iam.go b/cmd/iam.go index 70332e4a9..40462bcb0 100644 --- a/cmd/iam.go +++ b/cmd/iam.go @@ -86,7 +86,7 @@ func getCurrentIAMFormat() iamFormat { } func getIAMFormatFilePath() string { - return iamConfigPrefix + "/" + iamFormatFile + return iamConfigPrefix + SlashSeparator + iamFormatFile } func getUserIdentityPath(user string, isSTS bool) string { @@ -191,7 +191,7 @@ func listIAMConfigItems(objectAPI ObjectLayer, pathPrefix string, dirs bool, marker := "" for { lo, err := objectAPI.ListObjects(context.Background(), - minioMetaBucket, pathPrefix, marker, "/", 1000) + minioMetaBucket, pathPrefix, marker, SlashSeparator, 1000) if err != nil { select { case ch <- itemOrErr{Err: err}: @@ -207,7 +207,7 @@ func listIAMConfigItems(objectAPI ObjectLayer, pathPrefix string, dirs bool, } for _, itemPrefix := range lister { item := strings.TrimPrefix(itemPrefix, pathPrefix) - item = strings.TrimSuffix(item, "/") + item = strings.TrimSuffix(item, SlashSeparator) select { case ch <- itemOrErr{Item: item}: case <-doneCh: diff --git a/cmd/lock-rest-server.go b/cmd/lock-rest-server.go index 261f1ea0a..b1b2b6b4f 100644 --- a/cmd/lock-rest-server.go +++ b/cmd/lock-rest-server.go @@ -232,12 +232,12 @@ func startLockMaintenance(lkSrv *lockRESTServer) { func registerLockRESTHandlers(router *mux.Router) { subrouter := router.PathPrefix(lockRESTPath).Subrouter() queries := restQueries(lockRESTUID, lockRESTSource, lockRESTResource, lockRESTServerAddr, lockRESTServerEndpoint) - subrouter.Methods(http.MethodPost).Path("/" + lockRESTMethodLock).HandlerFunc(httpTraceHdrs(globalLockServer.LockHandler)).Queries(queries...) - subrouter.Methods(http.MethodPost).Path("/" + lockRESTMethodRLock).HandlerFunc(httpTraceHdrs(globalLockServer.RLockHandler)).Queries(queries...) - subrouter.Methods(http.MethodPost).Path("/" + lockRESTMethodUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.UnlockHandler)).Queries(queries...) - subrouter.Methods(http.MethodPost).Path("/" + lockRESTMethodRUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.RUnlockHandler)).Queries(queries...) - subrouter.Methods(http.MethodPost).Path("/" + lockRESTMethodForceUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.ForceUnlockHandler)).Queries(queries...) - subrouter.Methods(http.MethodPost).Path("/" + lockRESTMethodExpired).HandlerFunc(httpTraceAll(globalLockServer.ExpiredHandler)).Queries(queries...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodLock).HandlerFunc(httpTraceHdrs(globalLockServer.LockHandler)).Queries(queries...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodRLock).HandlerFunc(httpTraceHdrs(globalLockServer.RLockHandler)).Queries(queries...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.UnlockHandler)).Queries(queries...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodRUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.RUnlockHandler)).Queries(queries...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodForceUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.ForceUnlockHandler)).Queries(queries...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodExpired).HandlerFunc(httpTraceAll(globalLockServer.ExpiredHandler)).Queries(queries...) router.NotFoundHandler = http.HandlerFunc(httpTraceAll(notFoundHandler)) diff --git a/cmd/object-api-common.go b/cmd/object-api-common.go index bfbf8e000..4ba3603d0 100644 --- a/cmd/object-api-common.go +++ b/cmd/object-api-common.go @@ -56,10 +56,10 @@ func init() { } // Checks if the object is a directory, this logic uses -// if size == 0 and object ends with slashSeparator then +// if size == 0 and object ends with SlashSeparator then // returns true. func isObjectDir(object string, size int64) bool { - return hasSuffix(object, slashSeparator) && size == 0 + return hasSuffix(object, SlashSeparator) && size == 0 } // Converts just bucket, object metadata into ObjectInfo datatype. @@ -110,7 +110,7 @@ func cleanupDir(ctx context.Context, storage StorageAPI, volume, dirPath string) var delFunc func(string) error // Function to delete entries recursively. delFunc = func(entryPath string) error { - if !hasSuffix(entryPath, slashSeparator) { + if !hasSuffix(entryPath, SlashSeparator) { // Delete the file entry. err := storage.DeleteFile(volume, entryPath) logger.LogIf(ctx, err) @@ -157,7 +157,7 @@ func cleanupObjectsBulk(ctx context.Context, storage StorageAPI, volume string, var traverse func(string) ([]string, error) traverse = func(entryPath string) ([]string, error) { var output = make([]string, 0) - if !hasSuffix(entryPath, slashSeparator) { + if !hasSuffix(entryPath, SlashSeparator) { output = append(output, entryPath) return output, nil } @@ -320,7 +320,7 @@ func listObjectsNonSlash(ctx context.Context, obj ObjectLayer, bucket, prefix, m } func listObjects(ctx context.Context, obj ObjectLayer, bucket, prefix, marker, delimiter string, maxKeys int, tpool *TreeWalkPool, listDir ListDirFunc, getObjInfo func(context.Context, string, string) (ObjectInfo, error), getObjectInfoDirs ...func(context.Context, string, string) (ObjectInfo, error)) (loi ListObjectsInfo, err error) { - if delimiter != slashSeparator && delimiter != "" { + if delimiter != SlashSeparator && delimiter != "" { return listObjectsNonSlash(ctx, obj, bucket, prefix, marker, delimiter, maxKeys, tpool, listDir, getObjInfo, getObjectInfoDirs...) } @@ -346,7 +346,7 @@ func listObjects(ctx context.Context, obj ObjectLayer, bucket, prefix, marker, d // along // with the prefix. On a flat namespace with 'prefix' // as '/' we don't have any entries, since all the keys are // of form 'keyName/...' - if delimiter == slashSeparator && prefix == slashSeparator { + if delimiter == SlashSeparator && prefix == SlashSeparator { return loi, nil } @@ -357,7 +357,7 @@ func listObjects(ctx context.Context, obj ObjectLayer, bucket, prefix, marker, d // Default is recursive, if delimiter is set then list non recursive. recursive := true - if delimiter == slashSeparator { + if delimiter == SlashSeparator { recursive = false } @@ -382,7 +382,7 @@ func listObjects(ctx context.Context, obj ObjectLayer, bucket, prefix, marker, d var objInfo ObjectInfo var err error - if hasSuffix(walkResult.entry, slashSeparator) { + if hasSuffix(walkResult.entry, SlashSeparator) { for _, getObjectInfoDir := range getObjectInfoDirs { objInfo, err = getObjectInfoDir(ctx, bucket, walkResult.entry) if err == nil { @@ -429,7 +429,7 @@ func listObjects(ctx context.Context, obj ObjectLayer, bucket, prefix, marker, d result := ListObjectsInfo{} for _, objInfo := range objInfos { - if objInfo.IsDir && delimiter == slashSeparator { + if objInfo.IsDir && delimiter == SlashSeparator { result.Prefixes = append(result.Prefixes, objInfo.Name) continue } diff --git a/cmd/object-api-errors.go b/cmd/object-api-errors.go index 461e5df46..35695a0db 100644 --- a/cmd/object-api-errors.go +++ b/cmd/object-api-errors.go @@ -203,14 +203,14 @@ func (e ObjectExistsAsDirectory) Error() string { type PrefixAccessDenied GenericError func (e PrefixAccessDenied) Error() string { - return "Prefix access is denied: " + e.Bucket + "/" + e.Object + return "Prefix access is denied: " + e.Bucket + SlashSeparator + e.Object } // ParentIsObject object access is denied. type ParentIsObject GenericError func (e ParentIsObject) Error() string { - return "Parent is object " + e.Bucket + "/" + path.Dir(e.Object) + return "Parent is object " + e.Bucket + SlashSeparator + path.Dir(e.Object) } // BucketExists bucket exists. diff --git a/cmd/object-api-getobject_test.go b/cmd/object-api-getobject_test.go index d4d878819..17ae84178 100644 --- a/cmd/object-api-getobject_test.go +++ b/cmd/object-api-getobject_test.go @@ -259,7 +259,7 @@ func testGetObjectPermissionDenied(obj ObjectLayer, instanceType string, disks [ for i, testCase := range testCases { for _, d := range disks { - err = os.Chmod(d+"/"+testCase.bucketName+"/"+testCase.chmodPath, 0) + err = os.Chmod(d+SlashSeparator+testCase.bucketName+SlashSeparator+testCase.chmodPath, 0) if err != nil { t.Fatalf("Test %d, Unable to chmod: %v", i+1, err) } diff --git a/cmd/object-api-input-checks.go b/cmd/object-api-input-checks.go index 09bb7afc4..da5294521 100644 --- a/cmd/object-api-input-checks.go +++ b/cmd/object-api-input-checks.go @@ -74,7 +74,7 @@ func checkListObjsArgs(ctx context.Context, bucket, prefix, marker, delimiter st } } // Verify if delimiter is anything other than '/', which we do not support. - if delimiter != "" && delimiter != slashSeparator { + if delimiter != "" && delimiter != SlashSeparator { logger.LogIf(ctx, UnsupportedDelimiter{ Delimiter: delimiter, }) @@ -102,7 +102,7 @@ func checkListMultipartArgs(ctx context.Context, bucket, prefix, keyMarker, uplo return err } if uploadIDMarker != "" { - if hasSuffix(keyMarker, slashSeparator) { + if hasSuffix(keyMarker, SlashSeparator) { logger.LogIf(ctx, InvalidUploadIDKeyCombination{ UploadIDMarker: uploadIDMarker, @@ -196,7 +196,7 @@ func checkPutObjectArgs(ctx context.Context, bucket, object string, obj ObjectLa return err } if len(object) == 0 || - (hasSuffix(object, slashSeparator) && size != 0) || + (hasSuffix(object, SlashSeparator) && size != 0) || !IsValidObjectPrefix(object) { return ObjectNameInvalid{ Bucket: bucket, diff --git a/cmd/object-api-listobjects_test.go b/cmd/object-api-listobjects_test.go index 31ae30460..de6e28248 100644 --- a/cmd/object-api-listobjects_test.go +++ b/cmd/object-api-listobjects_test.go @@ -543,20 +543,20 @@ func testListObjects(obj ObjectLayer, instanceType string, t1 TestErrHandler) { {"test-bucket-list-object", "Asia", "", "", 10, resultCases[24], nil, true}, // Tests with prefix and delimiter (55-57). // With delimeter the code should not recurse into the sub-directories of prefix Dir. - {"test-bucket-list-object", "Asia", "", "/", 10, resultCases[25], nil, true}, - {"test-bucket-list-object", "new", "", "/", 10, resultCases[26], nil, true}, - {"test-bucket-list-object", "Asia/India/", "", "/", 10, resultCases[27], nil, true}, + {"test-bucket-list-object", "Asia", "", SlashSeparator, 10, resultCases[25], nil, true}, + {"test-bucket-list-object", "new", "", SlashSeparator, 10, resultCases[26], nil, true}, + {"test-bucket-list-object", "Asia/India/", "", SlashSeparator, 10, resultCases[27], nil, true}, // Test with marker set as hierarhical value and with delimiter. (58-59) - {"test-bucket-list-object", "", "Asia/India/India-summer-photos-1", "/", 10, resultCases[28], nil, true}, - {"test-bucket-list-object", "", "Asia/India/Karnataka/Bangalore/Koramangala/pics", "/", 10, resultCases[29], nil, true}, + {"test-bucket-list-object", "", "Asia/India/India-summer-photos-1", SlashSeparator, 10, resultCases[28], nil, true}, + {"test-bucket-list-object", "", "Asia/India/Karnataka/Bangalore/Koramangala/pics", SlashSeparator, 10, resultCases[29], nil, true}, // Test with prefix and delimiter set to '/'. (60) - {"test-bucket-list-object", "/", "", "/", 10, resultCases[30], nil, true}, + {"test-bucket-list-object", SlashSeparator, "", SlashSeparator, 10, resultCases[30], nil, true}, // Test with invalid prefix (61) - {"test-bucket-list-object", "\\", "", "/", 10, ListObjectsInfo{}, ObjectNameInvalid{Bucket: "test-bucket-list-object", Object: "\\"}, false}, + {"test-bucket-list-object", "\\", "", SlashSeparator, 10, ListObjectsInfo{}, ObjectNameInvalid{Bucket: "test-bucket-list-object", Object: "\\"}, false}, // Test listing an empty directory in recursive mode (62) {"test-bucket-empty-dir", "", "", "", 10, resultCases[31], nil, true}, // Test listing an empty directory in a non recursive mode (63) - {"test-bucket-empty-dir", "", "", "/", 10, resultCases[32], nil, true}, + {"test-bucket-empty-dir", "", "", SlashSeparator, 10, resultCases[32], nil, true}, // Test listing a directory which contains an empty directory (64) {"test-bucket-empty-dir", "", "temporary/", "", 10, resultCases[33], nil, true}, } @@ -595,7 +595,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t1 TestErrHandler) { t.Errorf("Test %d: %s: Expected object name to be \"%s\", but found \"%s\" instead", i+1, instanceType, testCase.result.Objects[j].Name, result.Objects[j].Name) } // FIXME: we should always check for ETag - if result.Objects[j].ETag == "" && !strings.HasSuffix(result.Objects[j].Name, slashSeparator) { + if result.Objects[j].ETag == "" && !strings.HasSuffix(result.Objects[j].Name, SlashSeparator) { t.Errorf("Test %d: %s: Expected ETag to be not empty, but found empty instead (%v)", i+1, instanceType, result.Objects[j].Name) } diff --git a/cmd/object-api-multipart_test.go b/cmd/object-api-multipart_test.go index aa346e099..1386da39d 100644 --- a/cmd/object-api-multipart_test.go +++ b/cmd/object-api-multipart_test.go @@ -680,7 +680,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan // Expecting the result to contain one MultipartInfo entry and IsTruncated to be false. { MaxUploads: 2, - Delimiter: "/", + Delimiter: SlashSeparator, Prefix: "", IsTruncated: false, Uploads: []MultipartInfo{ @@ -1170,7 +1170,7 @@ func testListMultipartUploads(obj ObjectLayer, instanceType string, t TestErrHan {bucketNames[0], "orange", "", "", "", 2, listMultipartResults[12], nil, true}, {bucketNames[0], "Asia", "", "", "", 2, listMultipartResults[13], nil, true}, // setting delimiter (Test number 27). - {bucketNames[0], "", "", "", "/", 2, listMultipartResults[14], nil, true}, + {bucketNames[0], "", "", "", SlashSeparator, 2, listMultipartResults[14], nil, true}, //Test case with multiple uploadID listing for given object (Test number 28). {bucketNames[1], "", "", "", "", 100, listMultipartResults[15], nil, true}, // Test case with multiple uploadID listing for given object, but uploadID marker set. diff --git a/cmd/object-api-utils.go b/cmd/object-api-utils.go index 1525241fb..dcbb77952 100644 --- a/cmd/object-api-utils.go +++ b/cmd/object-api-utils.go @@ -51,7 +51,7 @@ const ( // Multipart meta prefix. mpartMetaPrefix = "multipart" // MinIO Multipart meta prefix. - minioMetaMultipartBucket = minioMetaBucket + "/" + mpartMetaPrefix + minioMetaMultipartBucket = minioMetaBucket + SlashSeparator + mpartMetaPrefix // MinIO Tmp meta prefix. minioMetaTmpBucket = minioMetaBucket + "/tmp" // DNS separator (period), used for bucket name validation. @@ -131,12 +131,12 @@ func IsValidBucketName(bucket string) bool { // // - Backslash ("\") // -// additionally minio does not support object names with trailing "/". +// additionally minio does not support object names with trailing SlashSeparator. func IsValidObjectName(object string) bool { if len(object) == 0 { return false } - if hasSuffix(object, slashSeparator) { + if hasSuffix(object, SlashSeparator) { return false } return IsValidObjectPrefix(object) @@ -168,7 +168,7 @@ func checkObjectNameForLengthAndSlash(bucket, object string) error { } } // Check for slash as prefix in object name - if hasPrefix(object, slashSeparator) { + if hasPrefix(object, SlashSeparator) { return ObjectNamePrefixAsSlash{ Bucket: bucket, Object: object, @@ -177,20 +177,20 @@ func checkObjectNameForLengthAndSlash(bucket, object string) error { return nil } -// Slash separator. -const slashSeparator = "/" +// SlashSeparator - slash separator. +const SlashSeparator = "/" // retainSlash - retains slash from a path. func retainSlash(s string) string { - return strings.TrimSuffix(s, slashSeparator) + slashSeparator + return strings.TrimSuffix(s, SlashSeparator) + SlashSeparator } -// pathJoin - like path.Join() but retains trailing "/" of the last element +// pathJoin - like path.Join() but retains trailing SlashSeparator of the last element func pathJoin(elem ...string) string { trailingSlash := "" if len(elem) > 0 { - if hasSuffix(elem[len(elem)-1], slashSeparator) { - trailingSlash = "/" + if hasSuffix(elem[len(elem)-1], SlashSeparator) { + trailingSlash = SlashSeparator } } return path.Join(elem...) + trailingSlash @@ -292,7 +292,7 @@ func isStringEqual(s1 string, s2 string) bool { // Ignores all reserved bucket names or invalid bucket names. func isReservedOrInvalidBucket(bucketEntry string, strict bool) bool { - bucketEntry = strings.TrimSuffix(bucketEntry, slashSeparator) + bucketEntry = strings.TrimSuffix(bucketEntry, SlashSeparator) if strict { if err := s3utils.CheckValidBucketNameStrict(bucketEntry); err != nil { return true diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index c63661cf5..43059da22 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -1233,7 +1233,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req var objectEncryptionKey []byte if objectAPI.IsEncryptionSupported() { - if hasServerSideEncryptionHeader(r.Header) && !hasSuffix(object, slashSeparator) { // handle SSE requests + if hasServerSideEncryptionHeader(r.Header) && !hasSuffix(object, SlashSeparator) { // handle SSE requests reader, objectEncryptionKey, err = EncryptRequest(hashReader, r, bucket, object, metadata) if err != nil { writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) diff --git a/cmd/object-handlers_test.go b/cmd/object-handlers_test.go index 9e83789eb..39bdb7993 100644 --- a/cmd/object-handlers_test.go +++ b/cmd/object-handlers_test.go @@ -482,7 +482,7 @@ func testAPIGetObjectHandler(obj ObjectLayer, instanceType, bucketName string, a expectedContent: encodeResponse(getAPIErrorResponse(ctx, getAPIError(ErrNoSuchKey), - "/"+bucketName+"/"+". ./. ./etc", "", "")), + SlashSeparator+bucketName+SlashSeparator+". ./. ./etc", "", "")), expectedRespStatus: http.StatusNotFound, }, // Test case - 9. @@ -496,7 +496,7 @@ func testAPIGetObjectHandler(obj ObjectLayer, instanceType, bucketName string, a expectedContent: encodeResponse(getAPIErrorResponse(ctx, getAPIError(ErrInvalidObjectName), - "/"+bucketName+"/"+". ./../etc", "", "")), + SlashSeparator+bucketName+SlashSeparator+". ./../etc", "", "")), expectedRespStatus: http.StatusBadRequest, }, // Test case - 10. @@ -1593,7 +1593,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, expectedRespStatus: http.StatusOK, @@ -1604,7 +1604,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/"), + copySourceHeader: url.QueryEscape(SlashSeparator), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1617,7 +1617,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + testObject), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + testObject), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1629,7 +1629,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copySourceRange: "bytes=500-4096", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1642,7 +1642,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copySourceRange: "bytes=6145-", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1655,7 +1655,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copySourceRange: "bytes=0-6144", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1683,7 +1683,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + "non-existent-object"), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + "non-existent-object"), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1697,7 +1697,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: "non-existent-destination-bucket", uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1709,7 +1709,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), accessKey: "Invalid-AccessID", secretKey: credentials.SecretKey, @@ -1721,7 +1721,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: "-1", - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1732,7 +1732,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), invalidPartNumber: true, accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1743,7 +1743,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), maximumPartNumber: true, accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1753,7 +1753,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/"+bucketName+"/"+objectName) + "?versionId=null", + copySourceHeader: url.QueryEscape(SlashSeparator+bucketName+SlashSeparator+objectName) + "?versionId=null", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, expectedRespStatus: http.StatusOK, @@ -1762,7 +1762,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/"+bucketName+"/"+objectName) + "?versionId=17", + copySourceHeader: url.QueryEscape(SlashSeparator+bucketName+SlashSeparator+objectName) + "?versionId=17", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, expectedRespStatus: http.StatusNotFound, @@ -1771,7 +1771,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copySourceVersionID: "null", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1781,7 +1781,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri { bucketName: bucketName, uploadID: uploadID, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copySourceVersionID: "17", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1852,7 +1852,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri // Below is how CopyObjectPartHandler is registered. // bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(api.CopyObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") // Its necessary to set the "X-Amz-Copy-Source" header for the request to be accepted by the handler. - nilReq.Header.Set("X-Amz-Copy-Source", url.QueryEscape("/"+nilBucket+"/"+nilObject)) + nilReq.Header.Set("X-Amz-Copy-Source", url.QueryEscape(SlashSeparator+nilBucket+SlashSeparator+nilObject)) // execute the object layer set to `nil` test. // `ExecObjectLayerAPINilTest` manages the operation. @@ -1947,7 +1947,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, metadata: map[string]string{ @@ -1961,7 +1961,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/"), + copySourceHeader: url.QueryEscape(SlashSeparator), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1973,7 +1973,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: objectName, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1986,7 +1986,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: objectName, - copySourceHeader: url.QueryEscape(bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(bucketName + SlashSeparator + objectName), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -1999,7 +1999,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: objectName, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), metadata: map[string]string{ "Content-Type": "application/json", }, @@ -2015,7 +2015,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), metadata: map[string]string{ "Content-Type": "application/json", }, @@ -2032,7 +2032,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: objectName, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), metadata: map[string]string{ "Content-Type": "application/json", }, @@ -2050,7 +2050,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: objectName, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + "non-existent-object"), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + "non-existent-object"), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -2064,7 +2064,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: "non-existent-destination-bucket", newObjectName: objectName, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -2076,7 +2076,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: objectName, - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), accessKey: "Invalid-AccessID", secretKey: credentials.SecretKey, @@ -2086,7 +2086,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copyModifiedHeader: "Mon, 02 Jan 2006 15:04:05 GMT", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -2096,7 +2096,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copyModifiedHeader: "Mon, 02 Jan 2217 15:04:05 GMT", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -2106,7 +2106,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copyModifiedHeader: "Mon, 02 Jan 2217 15:04:05 +00:00", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -2116,7 +2116,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copyUnmodifiedHeader: "Mon, 02 Jan 2217 15:04:05 GMT", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -2126,7 +2126,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copyUnmodifiedHeader: "Mon, 02 Jan 2007 15:04:05 GMT", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -2136,7 +2136,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copyUnmodifiedHeader: "Mon, 02 Jan 2007 15:04:05 +00:00", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -2146,7 +2146,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/"+bucketName+"/"+objectName) + "?versionId=null", + copySourceHeader: url.QueryEscape(SlashSeparator+bucketName+SlashSeparator+objectName) + "?versionId=null", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, expectedRespStatus: http.StatusOK, @@ -2155,7 +2155,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/"+bucketName+"/"+objectName) + "?versionId=17", + copySourceHeader: url.QueryEscape(SlashSeparator+bucketName+SlashSeparator+objectName) + "?versionId=17", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, expectedRespStatus: http.StatusNotFound, @@ -2164,7 +2164,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copySourceVersionID: "null", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -2174,7 +2174,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, { bucketName: bucketName, newObjectName: "newObject1", - copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceHeader: url.QueryEscape(SlashSeparator + bucketName + SlashSeparator + objectName), copySourceVersionID: "17", accessKey: credentials.AccessKey, secretKey: credentials.SecretKey, @@ -2307,7 +2307,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, // Below is how CopyObjectHandler is registered. // bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?") // Its necessary to set the "X-Amz-Copy-Source" header for the request to be accepted by the handler. - nilReq.Header.Set("X-Amz-Copy-Source", url.QueryEscape("/"+nilBucket+"/"+nilObject)) + nilReq.Header.Set("X-Amz-Copy-Source", url.QueryEscape(SlashSeparator+nilBucket+SlashSeparator+nilObject)) if err != nil { t.Errorf("MinIO %s: Failed to create HTTP request for testing the response when object Layer is set to `nil`.", instanceType) } diff --git a/cmd/object_api_suite_test.go b/cmd/object_api_suite_test.go index b4e83fe4f..36a30670b 100644 --- a/cmd/object_api_suite_test.go +++ b/cmd/object_api_suite_test.go @@ -340,7 +340,7 @@ func testPaging(obj ObjectLayer, instanceType string, t TestErrHandler) { if err != nil { t.Fatalf("%s: %s", instanceType, err) } - result, err = obj.ListObjects(context.Background(), "bucket", "this/is/", "", "/", 10) + result, err = obj.ListObjects(context.Background(), "bucket", "this/is/", "", SlashSeparator, 10) if err != nil { t.Fatalf("%s: %s", instanceType, err) } @@ -354,7 +354,7 @@ func testPaging(obj ObjectLayer, instanceType string, t TestErrHandler) { // check delimited results with delimiter without prefix. { - result, err = obj.ListObjects(context.Background(), "bucket", "", "", "/", 1000) + result, err = obj.ListObjects(context.Background(), "bucket", "", "", SlashSeparator, 1000) if err != nil { t.Fatalf("%s: %s", instanceType, err) } diff --git a/cmd/peer-rest-server.go b/cmd/peer-rest-server.go index 73fbca90b..ee4c63d45 100644 --- a/cmd/peer-rest-server.go +++ b/cmd/peer-rest-server.go @@ -808,38 +808,38 @@ func (s *peerRESTServer) IsValid(w http.ResponseWriter, r *http.Request) bool { func registerPeerRESTHandlers(router *mux.Router) { server := &peerRESTServer{} subrouter := router.PathPrefix(peerRESTPath).Subrouter() - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodGetLocks).HandlerFunc(httpTraceHdrs(server.GetLocksHandler)) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodServerInfo).HandlerFunc(httpTraceHdrs(server.ServerInfoHandler)) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodCPULoadInfo).HandlerFunc(httpTraceHdrs(server.CPULoadInfoHandler)) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodMemUsageInfo).HandlerFunc(httpTraceHdrs(server.MemUsageInfoHandler)) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodDrivePerfInfo).HandlerFunc(httpTraceHdrs(server.DrivePerfInfoHandler)) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodDeleteBucket).HandlerFunc(httpTraceHdrs(server.DeleteBucketHandler)).Queries(restQueries(peerRESTBucket)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodSignalService).HandlerFunc(httpTraceHdrs(server.SignalServiceHandler)).Queries(restQueries(peerRESTSignal)...) - - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodBucketPolicyRemove).HandlerFunc(httpTraceAll(server.RemoveBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodBucketPolicySet).HandlerFunc(httpTraceHdrs(server.SetBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...) - - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodDeletePolicy).HandlerFunc(httpTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodLoadPolicy).HandlerFunc(httpTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodDeleteUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodLoadUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser, peerRESTUserTemp)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodLoadUsers).HandlerFunc(httpTraceAll(server.LoadUsersHandler)) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodLoadGroup).HandlerFunc(httpTraceAll(server.LoadGroupHandler)).Queries(restQueries(peerRESTGroup)...) - - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodStartProfiling).HandlerFunc(httpTraceAll(server.StartProfilingHandler)).Queries(restQueries(peerRESTProfiler)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodDownloadProfilingData).HandlerFunc(httpTraceHdrs(server.DownloadProflingDataHandler)) - - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodTargetExists).HandlerFunc(httpTraceHdrs(server.TargetExistsHandler)).Queries(restQueries(peerRESTBucket)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodSendEvent).HandlerFunc(httpTraceHdrs(server.SendEventHandler)).Queries(restQueries(peerRESTBucket)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodBucketNotificationPut).HandlerFunc(httpTraceHdrs(server.PutBucketNotificationHandler)).Queries(restQueries(peerRESTBucket)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodBucketNotificationListen).HandlerFunc(httpTraceHdrs(server.ListenBucketNotificationHandler)).Queries(restQueries(peerRESTBucket)...) - - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodReloadFormat).HandlerFunc(httpTraceHdrs(server.ReloadFormatHandler)).Queries(restQueries(peerRESTDryRun)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodBucketLifecycleSet).HandlerFunc(httpTraceHdrs(server.SetBucketLifecycleHandler)).Queries(restQueries(peerRESTBucket)...) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodBucketLifecycleRemove).HandlerFunc(httpTraceHdrs(server.RemoveBucketLifecycleHandler)).Queries(restQueries(peerRESTBucket)...) - - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodTrace).HandlerFunc(server.TraceHandler) - subrouter.Methods(http.MethodPost).Path("/" + peerRESTMethodBackgroundHealStatus).HandlerFunc(server.BackgroundHealStatusHandler) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodGetLocks).HandlerFunc(httpTraceHdrs(server.GetLocksHandler)) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodServerInfo).HandlerFunc(httpTraceHdrs(server.ServerInfoHandler)) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodCPULoadInfo).HandlerFunc(httpTraceHdrs(server.CPULoadInfoHandler)) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodMemUsageInfo).HandlerFunc(httpTraceHdrs(server.MemUsageInfoHandler)) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDrivePerfInfo).HandlerFunc(httpTraceHdrs(server.DrivePerfInfoHandler)) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDeleteBucket).HandlerFunc(httpTraceHdrs(server.DeleteBucketHandler)).Queries(restQueries(peerRESTBucket)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodSignalService).HandlerFunc(httpTraceHdrs(server.SignalServiceHandler)).Queries(restQueries(peerRESTSignal)...) + + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketPolicyRemove).HandlerFunc(httpTraceAll(server.RemoveBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketPolicySet).HandlerFunc(httpTraceHdrs(server.SetBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...) + + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDeletePolicy).HandlerFunc(httpTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadPolicy).HandlerFunc(httpTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDeleteUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser, peerRESTUserTemp)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadUsers).HandlerFunc(httpTraceAll(server.LoadUsersHandler)) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadGroup).HandlerFunc(httpTraceAll(server.LoadGroupHandler)).Queries(restQueries(peerRESTGroup)...) + + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodStartProfiling).HandlerFunc(httpTraceAll(server.StartProfilingHandler)).Queries(restQueries(peerRESTProfiler)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDownloadProfilingData).HandlerFunc(httpTraceHdrs(server.DownloadProflingDataHandler)) + + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodTargetExists).HandlerFunc(httpTraceHdrs(server.TargetExistsHandler)).Queries(restQueries(peerRESTBucket)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodSendEvent).HandlerFunc(httpTraceHdrs(server.SendEventHandler)).Queries(restQueries(peerRESTBucket)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketNotificationPut).HandlerFunc(httpTraceHdrs(server.PutBucketNotificationHandler)).Queries(restQueries(peerRESTBucket)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketNotificationListen).HandlerFunc(httpTraceHdrs(server.ListenBucketNotificationHandler)).Queries(restQueries(peerRESTBucket)...) + + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodReloadFormat).HandlerFunc(httpTraceHdrs(server.ReloadFormatHandler)).Queries(restQueries(peerRESTDryRun)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketLifecycleSet).HandlerFunc(httpTraceHdrs(server.SetBucketLifecycleHandler)).Queries(restQueries(peerRESTBucket)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketLifecycleRemove).HandlerFunc(httpTraceHdrs(server.RemoveBucketLifecycleHandler)).Queries(restQueries(peerRESTBucket)...) + + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodTrace).HandlerFunc(server.TraceHandler) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBackgroundHealStatus).HandlerFunc(server.BackgroundHealStatusHandler) router.NotFoundHandler = http.HandlerFunc(httpTraceAll(notFoundHandler)) } diff --git a/cmd/posix-list-dir_other.go b/cmd/posix-list-dir_other.go index ae2e04bae..97a1f7ad1 100644 --- a/cmd/posix-list-dir_other.go +++ b/cmd/posix-list-dir_other.go @@ -86,7 +86,7 @@ func readDirN(dirPath string, count int) (entries []string, err error) { } // Append to entries if symbolic link exists and is valid. if st.IsDir() { - entries = append(entries, fi.Name()+slashSeparator) + entries = append(entries, fi.Name()+SlashSeparator) } else if st.Mode().IsRegular() { entries = append(entries, fi.Name()) } @@ -96,8 +96,8 @@ func readDirN(dirPath string, count int) (entries []string, err error) { continue } if fi.Mode().IsDir() { - // Append "/" instead of "\" so that sorting is achieved as expected. - entries = append(entries, fi.Name()+slashSeparator) + // Append SlashSeparator instead of "\" so that sorting is achieved as expected. + entries = append(entries, fi.Name()+SlashSeparator) } else if fi.Mode().IsRegular() { entries = append(entries, fi.Name()) } diff --git a/cmd/posix-list-dir_unix.go b/cmd/posix-list-dir_unix.go index a247fafd2..8433191ba 100644 --- a/cmd/posix-list-dir_unix.go +++ b/cmd/posix-list-dir_unix.go @@ -69,7 +69,7 @@ func parseDirents(dirPath string, buf []byte) (entries []string, err error) { switch dirent.Type { case syscall.DT_DIR: - entries = append(entries, name+slashSeparator) + entries = append(entries, name+SlashSeparator) case syscall.DT_REG: entries = append(entries, name) case syscall.DT_LNK, syscall.DT_UNKNOWN: @@ -89,7 +89,7 @@ func parseDirents(dirPath string, buf []byte) (entries []string, err error) { return nil, err } if fi.IsDir() { - entries = append(entries, name+slashSeparator) + entries = append(entries, name+SlashSeparator) } else if fi.Mode().IsRegular() { entries = append(entries, name) } diff --git a/cmd/posix-list-dir_windows.go b/cmd/posix-list-dir_windows.go index 5676c2790..b6b98434b 100644 --- a/cmd/posix-list-dir_windows.go +++ b/cmd/posix-list-dir_windows.go @@ -92,12 +92,12 @@ func readDirN(dirPath string, count int) (entries []string, err error) { return nil, err } if fi.IsDir() { - entries = append(entries, name+slashSeparator) + entries = append(entries, name+SlashSeparator) } else if fi.Mode().IsRegular() { entries = append(entries, name) } case data.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0: - entries = append(entries, name+slashSeparator) + entries = append(entries, name+SlashSeparator) default: entries = append(entries, name) } diff --git a/cmd/posix.go b/cmd/posix.go index 704738aac..027384666 100644 --- a/cmd/posix.go +++ b/cmd/posix.go @@ -95,7 +95,7 @@ func checkPathLength(pathName string) error { } // Check each path segment length is > 255 - for len(pathName) > 0 && pathName != "." && pathName != "/" { + for len(pathName) > 0 && pathName != "." && pathName != SlashSeparator { dir, file := slashpath.Dir(pathName), slashpath.Base(pathName) if len(file) > 255 { @@ -558,7 +558,7 @@ func listVols(dirPath string) ([]VolInfo, error) { } var volsInfo []VolInfo for _, entry := range entries { - if !hasSuffix(entry, slashSeparator) || !isValidVolname(slashpath.Clean(entry)) { + if !hasSuffix(entry, SlashSeparator) || !isValidVolname(slashpath.Clean(entry)) { // Skip if entry is neither a directory not a valid volume name. continue } @@ -718,7 +718,7 @@ func (s *posix) Walk(volume, dirPath, marker string, recursive bool, leafFile st return } var fi FileInfo - if hasSuffix(walkResult.entry, slashSeparator) { + if hasSuffix(walkResult.entry, SlashSeparator) { fi = FileInfo{ Volume: volume, Name: walkResult.entry, @@ -743,7 +743,7 @@ func (s *posix) Walk(volume, dirPath, marker string, recursive bool, leafFile st } // ListDir - return all the entries at the given directory path. -// If an entry is a directory it will be returned with a trailing "/". +// If an entry is a directory it will be returned with a trailing SlashSeparator. func (s *posix) ListDir(volume, dirPath string, count int, leafFile string) (entries []string, err error) { defer func() { if err == errFaultyDisk { @@ -786,7 +786,7 @@ func (s *posix) ListDir(volume, dirPath string, count int, leafFile string) (ent if leafFile != "" { for i, entry := range entries { if _, serr := os.Stat(pathJoin(dirPath, entry, leafFile)); serr == nil { - entries[i] = strings.TrimSuffix(entry, slashSeparator) + entries[i] = strings.TrimSuffix(entry, SlashSeparator) } } } @@ -1390,7 +1390,7 @@ func deleteFile(basePath, deletePath string) error { // Trailing slash is removed when found to ensure // slashpath.Dir() to work as intended. - deletePath = strings.TrimSuffix(deletePath, slashSeparator) + deletePath = strings.TrimSuffix(deletePath, SlashSeparator) deletePath = slashpath.Dir(deletePath) // Delete parent directory. Errors for parent directories shouldn't trickle down. @@ -1430,7 +1430,7 @@ func (s *posix) DeleteFile(volume, path string) (err error) { return err } - // Following code is needed so that we retain "/" suffix if any in + // Following code is needed so that we retain SlashSeparator suffix if any in // path argument. filePath := pathJoin(volumeDir, path) if err = checkPathLength((filePath)); err != nil { @@ -1492,8 +1492,8 @@ func (s *posix) RenameFile(srcVolume, srcPath, dstVolume, dstPath string) (err e } } - srcIsDir := hasSuffix(srcPath, slashSeparator) - dstIsDir := hasSuffix(dstPath, slashSeparator) + srcIsDir := hasSuffix(srcPath, SlashSeparator) + dstIsDir := hasSuffix(dstPath, SlashSeparator) // Either src and dst have to be directories or files, else return error. if !(srcIsDir && dstIsDir || !srcIsDir && !dstIsDir) { return errFileAccessDenied diff --git a/cmd/posix_test.go b/cmd/posix_test.go index c5d23c107..b27e85dca 100644 --- a/cmd/posix_test.go +++ b/cmd/posix_test.go @@ -69,7 +69,7 @@ func TestIsValidVolname(t *testing.T) { // cases for which test should fail. // passing invalid bucket names. {"", false}, - {"/", false}, + {SlashSeparator, false}, {"a", false}, {"ab", false}, {"ab/", true}, @@ -319,9 +319,9 @@ func TestPosixReadAll(t *testing.T) { // TestPosixNewPosix all the cases handled in posix storage layer initialization. func TestPosixNewPosix(t *testing.T) { // Temporary dir name. - tmpDirName := globalTestTmpDir + "/" + "minio-" + nextSuffix() + tmpDirName := globalTestTmpDir + SlashSeparator + "minio-" + nextSuffix() // Temporary file name. - tmpFileName := globalTestTmpDir + "/" + "minio-" + nextSuffix() + tmpFileName := globalTestTmpDir + SlashSeparator + "minio-" + nextSuffix() f, _ := os.Create(tmpFileName) f.Close() defer os.Remove(tmpFileName) diff --git a/cmd/rest/client.go b/cmd/rest/client.go index fe435e0fe..e6cbccbe2 100644 --- a/cmd/rest/client.go +++ b/cmd/rest/client.go @@ -52,9 +52,15 @@ type Client struct { newAuthToken func() string } +// URL query separator constants +const ( + resourceSep = "/" + querySep = "?" +) + // CallWithContext - make a REST call with context. func (c *Client) CallWithContext(ctx context.Context, method string, values url.Values, body io.Reader, length int64) (reply io.ReadCloser, err error) { - req, err := http.NewRequest(http.MethodPost, c.url.String()+"/"+method+"?"+values.Encode(), body) + req, err := http.NewRequest(http.MethodPost, c.url.String()+resourceSep+method+querySep+values.Encode(), body) if err != nil { return nil, &NetworkError{err} } diff --git a/cmd/server_test.go b/cmd/server_test.go index 9d59c25da..bb57d9d65 100644 --- a/cmd/server_test.go +++ b/cmd/server_test.go @@ -1000,7 +1000,7 @@ func (s *TestSuiteCommon) TestMultipleObjects(c *check) { func (s *TestSuiteCommon) TestNotImplemented(c *check) { // Generate a random bucket name. bucketName := getRandomBucketName() - request, err := newTestSignedRequest("GET", s.endPoint+"/"+bucketName+"/object?policy", + request, err := newTestSignedRequest("GET", s.endPoint+SlashSeparator+bucketName+"/object?policy", 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1111,7 +1111,7 @@ func (s *TestSuiteCommon) TestCopyObject(c *check) { request, err = newTestRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName2), 0, nil) c.Assert(err, nil) // setting the "X-Amz-Copy-Source" to allow copying the content of previously uploaded object. - request.Header.Set("X-Amz-Copy-Source", url.QueryEscape("/"+bucketName+"/"+objectName)) + request.Header.Set("X-Amz-Copy-Source", url.QueryEscape(SlashSeparator+bucketName+SlashSeparator+objectName)) if s.signer == signerV4 { err = signRequestV4(request, s.accessKey, s.secretKey) } else { @@ -1821,7 +1821,7 @@ func (s *TestSuiteCommon) TestPutBucketErrors(c *check) { // request for ACL. // Since MinIO server doesn't support ACL's the request is expected to fail with "NotImplemented" error message. - request, err = newTestSignedRequest("PUT", s.endPoint+"/"+bucketName+"?acl", + request, err = newTestSignedRequest("PUT", s.endPoint+SlashSeparator+bucketName+"?acl", 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) diff --git a/cmd/signature-v2.go b/cmd/signature-v2.go index e1c861056..56be06a9b 100644 --- a/cmd/signature-v2.go +++ b/cmd/signature-v2.go @@ -209,7 +209,7 @@ func getReqAccessKeyV2(r *http.Request) (auth.Credentials, bool, APIErrorCode) { // CanonicalizedProtocolHeaders + // CanonicalizedResource; // -// CanonicalizedResource = [ "/" + Bucket ] + +// CanonicalizedResource = [ SlashSeparator + Bucket ] + // + // [ subresource, if present. For example "?acl", "?location", "?logging", or "?torrent"]; // diff --git a/cmd/signature-v4-parser.go b/cmd/signature-v4-parser.go index e9a683622..7655bcb96 100644 --- a/cmd/signature-v4-parser.go +++ b/cmd/signature-v4-parser.go @@ -44,7 +44,7 @@ func (c credentialHeader) getScope() string { c.scope.region, c.scope.service, c.scope.request, - }, "/") + }, SlashSeparator) } func getReqAccessKeyV4(r *http.Request, region string, stype serviceType) (auth.Credentials, bool, APIErrorCode) { @@ -73,11 +73,11 @@ func parseCredentialHeader(credElement string, region string, stype serviceType) if creds[0] != "Credential" { return ch, ErrMissingCredTag } - credElements := strings.Split(strings.TrimSpace(creds[1]), "/") + credElements := strings.Split(strings.TrimSpace(creds[1]), SlashSeparator) if len(credElements) < 5 { return ch, ErrCredMalformed } - accessKey := strings.Join(credElements[:len(credElements)-4], "/") // The access key may contain one or more `/` + accessKey := strings.Join(credElements[:len(credElements)-4], SlashSeparator) // The access key may contain one or more `/` if !auth.IsAccessKeyValid(accessKey) { return ch, ErrInvalidAccessKeyID } diff --git a/cmd/signature-v4-parser_test.go b/cmd/signature-v4-parser_test.go index bd0a7d654..b64c51707 100644 --- a/cmd/signature-v4-parser_test.go +++ b/cmd/signature-v4-parser_test.go @@ -36,7 +36,7 @@ func joinWithSlash(accessKey, date, region, service, requestVersion string) stri date, region, service, - requestVersion}, "/") + requestVersion}, SlashSeparator) } // generate CredentialHeader from its fields. @@ -79,12 +79,12 @@ func validateCredentialfields(t *testing.T, testNum int, expectedCredentials cre // TestParseCredentialHeader - validates the format validator and extractor for the Credential header in an aws v4 request. // A valid format of creadential should be of the following format. -// Credential = accessKey + "/"+ scope +// Credential = accessKey + SlashSeparator+ scope // where scope = string.Join([]string{ currTime.Format(yyyymmdd), // globalMinioDefaultRegion, // "s3", // "aws4_request", -// },"/") +// },SlashSeparator) func TestParseCredentialHeader(t *testing.T) { sampleTimeStr := UTCNow().Format(yyyymmdd) diff --git a/cmd/signature-v4.go b/cmd/signature-v4.go index 06689517e..97be5db95 100644 --- a/cmd/signature-v4.go +++ b/cmd/signature-v4.go @@ -120,7 +120,7 @@ func getScope(t time.Time, region string) string { region, string(serviceS3), "aws4_request", - }, "/") + }, SlashSeparator) return scope } @@ -248,7 +248,7 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s query.Set(xhttp.AmzDate, t.Format(iso8601Format)) query.Set(xhttp.AmzExpires, strconv.Itoa(expireSeconds)) query.Set(xhttp.AmzSignedHeaders, getSignedHeaders(extractedSignedHeaders)) - query.Set(xhttp.AmzCredential, cred.AccessKey+"/"+pSignValues.Credential.getScope()) + query.Set(xhttp.AmzCredential, cred.AccessKey+SlashSeparator+pSignValues.Credential.getScope()) // Save other headers available in the request parameters. for k, v := range req.URL.Query() { diff --git a/cmd/storage-rest-common.go b/cmd/storage-rest-common.go index 488b2b937..281744b36 100644 --- a/cmd/storage-rest-common.go +++ b/cmd/storage-rest-common.go @@ -17,7 +17,7 @@ package cmd const storageRESTVersion = "v8" -const storageRESTPath = minioReservedBucketPath + "/storage/" + storageRESTVersion + "/" +const storageRESTPath = minioReservedBucketPath + "/storage/" + storageRESTVersion + SlashSeparator const ( storageRESTMethodDiskInfo = "diskinfo" diff --git a/cmd/storage-rest-server.go b/cmd/storage-rest-server.go index 35e182777..5ac06658f 100644 --- a/cmd/storage-rest-server.go +++ b/cmd/storage-rest-server.go @@ -567,41 +567,41 @@ func registerStorageRESTHandlers(router *mux.Router, endpoints EndpointList) { subrouter := router.PathPrefix(path.Join(storageRESTPath, endpoint.Path)).Subrouter() - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodDiskInfo).HandlerFunc(httpTraceHdrs(server.DiskInfoHandler)) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodMakeVol).HandlerFunc(httpTraceHdrs(server.MakeVolHandler)).Queries(restQueries(storageRESTVolume)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodStatVol).HandlerFunc(httpTraceHdrs(server.StatVolHandler)).Queries(restQueries(storageRESTVolume)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodDeleteVol).HandlerFunc(httpTraceHdrs(server.DeleteVolHandler)).Queries(restQueries(storageRESTVolume)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodListVols).HandlerFunc(httpTraceHdrs(server.ListVolsHandler)) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodDiskInfo).HandlerFunc(httpTraceHdrs(server.DiskInfoHandler)) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodMakeVol).HandlerFunc(httpTraceHdrs(server.MakeVolHandler)).Queries(restQueries(storageRESTVolume)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodStatVol).HandlerFunc(httpTraceHdrs(server.StatVolHandler)).Queries(restQueries(storageRESTVolume)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodDeleteVol).HandlerFunc(httpTraceHdrs(server.DeleteVolHandler)).Queries(restQueries(storageRESTVolume)...) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodListVols).HandlerFunc(httpTraceHdrs(server.ListVolsHandler)) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodAppendFile).HandlerFunc(httpTraceHdrs(server.AppendFileHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodAppendFile).HandlerFunc(httpTraceHdrs(server.AppendFileHandler)). Queries(restQueries(storageRESTVolume, storageRESTFilePath)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodWriteAll).HandlerFunc(httpTraceHdrs(server.WriteAllHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodWriteAll).HandlerFunc(httpTraceHdrs(server.WriteAllHandler)). Queries(restQueries(storageRESTVolume, storageRESTFilePath)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodCreateFile).HandlerFunc(httpTraceHdrs(server.CreateFileHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodCreateFile).HandlerFunc(httpTraceHdrs(server.CreateFileHandler)). Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTLength)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodStatFile).HandlerFunc(httpTraceHdrs(server.StatFileHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodStatFile).HandlerFunc(httpTraceHdrs(server.StatFileHandler)). Queries(restQueries(storageRESTVolume, storageRESTFilePath)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodReadAll).HandlerFunc(httpTraceHdrs(server.ReadAllHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodReadAll).HandlerFunc(httpTraceHdrs(server.ReadAllHandler)). Queries(restQueries(storageRESTVolume, storageRESTFilePath)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodReadFile).HandlerFunc(httpTraceHdrs(server.ReadFileHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodReadFile).HandlerFunc(httpTraceHdrs(server.ReadFileHandler)). Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTOffset, storageRESTLength, storageRESTBitrotAlgo, storageRESTBitrotHash)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodReadFileStream).HandlerFunc(httpTraceHdrs(server.ReadFileStreamHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodReadFileStream).HandlerFunc(httpTraceHdrs(server.ReadFileStreamHandler)). Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTOffset, storageRESTLength)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodListDir).HandlerFunc(httpTraceHdrs(server.ListDirHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodListDir).HandlerFunc(httpTraceHdrs(server.ListDirHandler)). Queries(restQueries(storageRESTVolume, storageRESTDirPath, storageRESTCount, storageRESTLeafFile)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodWalk).HandlerFunc(httpTraceHdrs(server.WalkHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodWalk).HandlerFunc(httpTraceHdrs(server.WalkHandler)). Queries(restQueries(storageRESTVolume, storageRESTDirPath, storageRESTMarkerPath, storageRESTRecursive, storageRESTLeafFile)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodDeleteFile).HandlerFunc(httpTraceHdrs(server.DeleteFileHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodDeleteFile).HandlerFunc(httpTraceHdrs(server.DeleteFileHandler)). Queries(restQueries(storageRESTVolume, storageRESTFilePath)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodDeleteFileBulk).HandlerFunc(httpTraceHdrs(server.DeleteFileBulkHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodDeleteFileBulk).HandlerFunc(httpTraceHdrs(server.DeleteFileBulkHandler)). Queries(restQueries(storageRESTVolume, storageRESTFilePath)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodRenameFile).HandlerFunc(httpTraceHdrs(server.RenameFileHandler)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodRenameFile).HandlerFunc(httpTraceHdrs(server.RenameFileHandler)). Queries(restQueries(storageRESTSrcVolume, storageRESTSrcPath, storageRESTDstVolume, storageRESTDstPath)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodVerifyFile).HandlerFunc(httpTraceHdrs(server.VerifyFile)). + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodVerifyFile).HandlerFunc(httpTraceHdrs(server.VerifyFile)). Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTBitrotAlgo, storageRESTLength)...) - subrouter.Methods(http.MethodPost).Path("/" + storageRESTMethodGetInstanceID).HandlerFunc(httpTraceAll(server.GetInstanceID)) + subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodGetInstanceID).HandlerFunc(httpTraceAll(server.GetInstanceID)) } router.NotFoundHandler = http.HandlerFunc(httpTraceAll(notFoundHandler)) diff --git a/cmd/sts-handlers.go b/cmd/sts-handlers.go index 2a7fc5261..aa56b06ed 100644 --- a/cmd/sts-handlers.go +++ b/cmd/sts-handlers.go @@ -53,7 +53,7 @@ func registerSTSRouter(router *mux.Router) { sts := &stsAPIHandlers{} // STS Router - stsRouter := router.NewRoute().PathPrefix("/").Subrouter() + stsRouter := router.NewRoute().PathPrefix(SlashSeparator).Subrouter() // Assume roles with no JWT, handles AssumeRole. stsRouter.Methods(http.MethodPost).MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool { diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index e5125e443..b9c8d6056 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -707,7 +707,7 @@ func signStreamingRequest(req *http.Request, accessKey, secretKey string, currTi globalMinioDefaultRegion, string(serviceS3), "aws4_request", - }, "/") + }, SlashSeparator) stringToSign := "AWS4-HMAC-SHA256" + "\n" + currTime.Format(iso8601Format) + "\n" stringToSign = stringToSign + scope + "\n" @@ -722,7 +722,7 @@ func signStreamingRequest(req *http.Request, accessKey, secretKey string, currTi // final Authorization header parts := []string{ - "AWS4-HMAC-SHA256" + " Credential=" + accessKey + "/" + scope, + "AWS4-HMAC-SHA256" + " Credential=" + accessKey + SlashSeparator + scope, "SignedHeaders=" + signedHeaders, "Signature=" + signature, } @@ -787,7 +787,7 @@ func assembleStreamingChunks(req *http.Request, body io.ReadSeeker, chunkSize in regionStr, string(serviceS3), "aws4_request", - }, "/") + }, SlashSeparator) stringToSign := "AWS4-HMAC-SHA256-PAYLOAD" + "\n" stringToSign = stringToSign + currTime.Format(iso8601Format) + "\n" @@ -1062,7 +1062,7 @@ func signRequestV4(req *http.Request, accessKey, secretKey string) error { region, string(serviceS3), "aws4_request", - }, "/") + }, SlashSeparator) stringToSign := "AWS4-HMAC-SHA256" + "\n" + currTime.Format(iso8601Format) + "\n" stringToSign = stringToSign + scope + "\n" @@ -1077,7 +1077,7 @@ func signRequestV4(req *http.Request, accessKey, secretKey string) error { // final Authorization header parts := []string{ - "AWS4-HMAC-SHA256" + " Credential=" + accessKey + "/" + scope, + "AWS4-HMAC-SHA256" + " Credential=" + accessKey + SlashSeparator + scope, "SignedHeaders=" + signedHeaders, "Signature=" + signature, } @@ -1089,7 +1089,7 @@ func signRequestV4(req *http.Request, accessKey, secretKey string) error { // getCredentialString generate a credential string. func getCredentialString(accessKeyID, location string, t time.Time) string { - return accessKeyID + "/" + getScope(t, location) + return accessKeyID + SlashSeparator + getScope(t, location) } // getMD5HashBase64 returns MD5 hash in base64 encoding of given data. @@ -1360,9 +1360,9 @@ func (t *EOFWriter) Write(p []byte) (n int, err error) { // construct URL for http requests for bucket operations. func makeTestTargetURL(endPoint, bucketName, objectName string, queryValues url.Values) string { - urlStr := endPoint + "/" + urlStr := endPoint + SlashSeparator if bucketName != "" { - urlStr = urlStr + bucketName + "/" + urlStr = urlStr + bucketName + SlashSeparator } if objectName != "" { urlStr = urlStr + s3utils.EncodePath(objectName) @@ -2142,7 +2142,7 @@ func registerAPIFunctions(muxRouter *mux.Router, objLayer ObjectLayer, apiFuncti return } // API Router. - apiRouter := muxRouter.PathPrefix("/").Subrouter() + apiRouter := muxRouter.PathPrefix(SlashSeparator).Subrouter() // Bucket router. bucketRouter := apiRouter.PathPrefix("/{bucket}").Subrouter() diff --git a/cmd/tree-walk.go b/cmd/tree-walk.go index f396ca131..ad062eb81 100644 --- a/cmd/tree-walk.go +++ b/cmd/tree-walk.go @@ -67,10 +67,10 @@ func doTreeWalk(ctx context.Context, bucket, prefixDir, entryPrefixMatch, marker var markerBase, markerDir string if marker != "" { // Ex: if marker="four/five.txt", markerDir="four/" markerBase="five.txt" - markerSplit := strings.SplitN(marker, slashSeparator, 2) + markerSplit := strings.SplitN(marker, SlashSeparator, 2) markerDir = markerSplit[0] if len(markerSplit) == 2 { - markerDir += slashSeparator + markerDir += SlashSeparator markerBase = markerSplit[1] } } @@ -95,7 +95,7 @@ func doTreeWalk(ctx context.Context, bucket, prefixDir, entryPrefixMatch, marker for i, entry := range entries { pentry := pathJoin(prefixDir, entry) - isDir := hasSuffix(pentry, slashSeparator) + isDir := hasSuffix(pentry, SlashSeparator) if i == 0 && markerDir == entry { if !recursive { @@ -165,7 +165,7 @@ func startTreeWalk(ctx context.Context, bucket, prefix, marker string, recursive resultCh := make(chan TreeWalkResult, maxObjectList) entryPrefixMatch := prefix prefixDir := "" - lastIndex := strings.LastIndex(prefix, slashSeparator) + lastIndex := strings.LastIndex(prefix, SlashSeparator) if lastIndex != -1 { entryPrefixMatch = prefix[lastIndex+1:] prefixDir = prefix[:lastIndex+1] diff --git a/cmd/update-main.go b/cmd/update-main.go index 43b149b6a..2ba1b0fca 100644 --- a/cmd/update-main.go +++ b/cmd/update-main.go @@ -72,7 +72,7 @@ EXAMPLES: const ( minioReleaseTagTimeLayout = "2006-01-02T15-04-05Z" minioOSARCH = runtime.GOOS + "-" + runtime.GOARCH - minioReleaseURL = "https://dl.min.io/server/minio/release/" + minioOSARCH + "/" + minioReleaseURL = "https://dl.min.io/server/minio/release/" + minioOSARCH + SlashSeparator ) var ( diff --git a/cmd/utils.go b/cmd/utils.go index b9cc12247..0d72472b2 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -81,16 +81,16 @@ func request2BucketObjectName(r *http.Request) (bucketName, objectName string) { // Convert url path into bucket and object name. func urlPath2BucketObjectName(path string) (bucketName, objectName string) { - if path == "" || path == slashSeparator { + if path == "" || path == SlashSeparator { return "", "" } // Trim any preceding slash separator. - urlPath := strings.TrimPrefix(path, slashSeparator) + urlPath := strings.TrimPrefix(path, SlashSeparator) // Split urlpath using slash separator into a given number of // expected tokens. - tokens := strings.SplitN(urlPath, slashSeparator, 2) + tokens := strings.SplitN(urlPath, SlashSeparator, 2) bucketName = tokens[0] if len(tokens) == 2 { objectName = tokens[1] diff --git a/cmd/utils_test.go b/cmd/utils_test.go index 1cd8bbe1d..ac9ebd168 100644 --- a/cmd/utils_test.go +++ b/cmd/utils_test.go @@ -148,7 +148,7 @@ func TestURL2BucketObjectName(t *testing.T) { // Test case 2 where url only has separator. { u: &url.URL{ - Path: "/", + Path: SlashSeparator, }, bucket: "", object: "", diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index d7c59fc9a..7032325fe 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -315,7 +315,7 @@ func (web *webAPIHandlers) ListBuckets(r *http.Request, args *WebGenericArgs, re r.Header.Set("prefix", "") // Set delimiter value for "s3:delimiter" policy conditionals. - r.Header.Set("delimiter", slashSeparator) + r.Header.Set("delimiter", SlashSeparator) // If etcd, dns federation configured list buckets from etcd. if globalDNSConfig != nil { @@ -429,7 +429,7 @@ func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, r nextMarker := "" // Fetch all the objects for { - result, err := core.ListObjects(args.BucketName, args.Prefix, nextMarker, slashSeparator, 1000) + result, err := core.ListObjects(args.BucketName, args.Prefix, nextMarker, SlashSeparator, 1000) if err != nil { return toJSONError(ctx, err, args.BucketName) } @@ -464,7 +464,7 @@ func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, r r.Header.Set("prefix", args.Prefix) // Set delimiter value for "s3:delimiter" policy conditionals. - r.Header.Set("delimiter", slashSeparator) + r.Header.Set("delimiter", SlashSeparator) // Check if anonymous (non-owner) has access to download objects. readable := globalPolicySys.IsAllowed(policy.Args{ @@ -480,7 +480,7 @@ func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, r BucketName: args.BucketName, ConditionValues: getConditionValues(r, "", ""), IsOwner: false, - ObjectName: args.Prefix + "/", + ObjectName: args.Prefix + SlashSeparator, }) reply.Writable = writable @@ -503,7 +503,7 @@ func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, r r.Header.Set("prefix", args.Prefix) // Set delimiter value for "s3:delimiter" policy conditionals. - r.Header.Set("delimiter", slashSeparator) + r.Header.Set("delimiter", SlashSeparator) readable := globalIAMSys.IsAllowed(iampolicy.Args{ AccountName: claims.Subject, @@ -519,7 +519,7 @@ func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, r BucketName: args.BucketName, ConditionValues: getConditionValues(r, "", claims.Subject), IsOwner: owner, - ObjectName: args.Prefix + "/", + ObjectName: args.Prefix + SlashSeparator, }) reply.Writable = writable @@ -541,7 +541,7 @@ func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, r nextMarker := "" // Fetch all the objects for { - lo, err := listObjects(ctx, args.BucketName, args.Prefix, nextMarker, slashSeparator, 1000) + lo, err := listObjects(ctx, args.BucketName, args.Prefix, nextMarker, SlashSeparator, 1000) if err != nil { return &json2.Error{Message: err.Error()} } @@ -671,7 +671,7 @@ func (web *webAPIHandlers) RemoveObject(r *http.Request, args *RemoveObjectArgs, next: for _, objectName := range args.Objects { // If not a directory, remove the object. - if !hasSuffix(objectName, slashSeparator) && objectName != "" { + if !hasSuffix(objectName, SlashSeparator) && objectName != "" { // Deny if WORM is enabled if globalWORMEnabled { if _, err = objectAPI.GetObjectInfo(ctx, args.BucketName, objectName, ObjectOptions{}); err == nil { @@ -1034,7 +1034,7 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) { return } if objectAPI.IsEncryptionSupported() { - if hasServerSideEncryptionHeader(r.Header) && !hasSuffix(object, slashSeparator) { // handle SSE requests + if hasServerSideEncryptionHeader(r.Header) && !hasSuffix(object, SlashSeparator) { // handle SSE requests rawReader := hashReader var objectEncryptionKey []byte reader, objectEncryptionKey, err = EncryptRequest(hashReader, r, bucket, object, metadata) @@ -1436,7 +1436,7 @@ func (web *webAPIHandlers) DownloadZip(w http.ResponseWriter, r *http.Request) { return nil } - if !hasSuffix(object, slashSeparator) { + if !hasSuffix(object, SlashSeparator) { // If not a directory, compress the file and write it to response. err := zipit(pathJoin(args.Prefix, object)) if err != nil { @@ -1873,7 +1873,7 @@ func presignedGet(host, bucket, object string, expiry int64, creds auth.Credenti query.Set(xhttp.AmzSignedHeaders, "host") queryStr := s3utils.QueryEncode(query) - path := "/" + path.Join(bucket, object) + path := SlashSeparator + path.Join(bucket, object) // "host" is the only header required to be signed for Presigned URLs. extractedSignedHeaders := make(http.Header) diff --git a/cmd/web-handlers_test.go b/cmd/web-handlers_test.go index 4eb94d4ff..aeecf18fb 100644 --- a/cmd/web-handlers_test.go +++ b/cmd/web-handlers_test.go @@ -824,7 +824,7 @@ func testUploadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler test := func(token string, sendContentLength bool) int { rec := httptest.NewRecorder() - req, rErr := http.NewRequest("PUT", "/minio/upload/"+bucketName+"/"+objectName, nil) + req, rErr := http.NewRequest("PUT", "/minio/upload/"+bucketName+SlashSeparator+objectName, nil) if rErr != nil { t.Fatalf("Cannot create upload request, %v", rErr) } @@ -926,7 +926,7 @@ func testDownloadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandl test := func(token string) (int, []byte) { rec := httptest.NewRecorder() - path := "/minio/download/" + bucketName + "/" + objectName + "?token=" + path := "/minio/download/" + bucketName + SlashSeparator + objectName + "?token=" if token != "" { path = path + token } diff --git a/cmd/web-router.go b/cmd/web-router.go index 1eaaa6b40..dcf8576f8 100644 --- a/cmd/web-router.go +++ b/cmd/web-router.go @@ -40,7 +40,7 @@ type indexHandler struct { } func (h indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - r.URL.Path = minioReservedBucketPath + "/" + r.URL.Path = minioReservedBucketPath + SlashSeparator h.handler.ServeHTTP(w, r) } diff --git a/cmd/xl-sets.go b/cmd/xl-sets.go index 0ee86434f..32f04d93f 100644 --- a/cmd/xl-sets.go +++ b/cmd/xl-sets.go @@ -1027,7 +1027,7 @@ func (s *xlSets) listObjectsNonSlash(ctx context.Context, bucket, prefix, marker // walked and merged at this layer. Resulting value through the merge process sends // the data in lexically sorted order. func (s *xlSets) listObjects(ctx context.Context, bucket, prefix, marker, delimiter string, maxKeys int, heal bool) (loi ListObjectsInfo, err error) { - if delimiter != slashSeparator && delimiter != "" { + if delimiter != SlashSeparator && delimiter != "" { // "heal" option passed can be ignored as the heal-listing does not send non-standard delimiter. return s.listObjectsNonSlash(ctx, bucket, prefix, marker, delimiter, maxKeys) } @@ -1054,7 +1054,7 @@ func (s *xlSets) listObjects(ctx context.Context, bucket, prefix, marker, delimi // along // with the prefix. On a flat namespace with 'prefix' // as '/' we don't have any entries, since all the keys are // of form 'keyName/...' - if delimiter == slashSeparator && prefix == slashSeparator { + if delimiter == SlashSeparator && prefix == SlashSeparator { return loi, nil } @@ -1065,7 +1065,7 @@ func (s *xlSets) listObjects(ctx context.Context, bucket, prefix, marker, delimi // Default is recursive, if delimiter is set then list non recursive. recursive := true - if delimiter == slashSeparator { + if delimiter == SlashSeparator { recursive = false } @@ -1092,7 +1092,7 @@ func (s *xlSets) listObjects(ctx context.Context, bucket, prefix, marker, delimi for _, entry := range entries.Files { var objInfo ObjectInfo - if hasSuffix(entry.Name, slashSeparator) { + if hasSuffix(entry.Name, SlashSeparator) { if !recursive { loi.Prefixes = append(loi.Prefixes, entry.Name) continue diff --git a/cmd/xl-v1-common.go b/cmd/xl-v1-common.go index 65c1c903d..0df3ef764 100644 --- a/cmd/xl-v1-common.go +++ b/cmd/xl-v1-common.go @@ -37,7 +37,7 @@ func (xl xlObjects) getLoadBalancedDisks() (disks []StorageAPI) { func (xl xlObjects) parentDirIsObject(ctx context.Context, bucket, parent string) bool { var isParentDirObject func(string) bool isParentDirObject = func(p string) bool { - if p == "." || p == "/" { + if p == "." || p == SlashSeparator { return false } if xl.isObject(bucket, p) { diff --git a/cmd/xl-v1-common_test.go b/cmd/xl-v1-common_test.go index 601d468d7..70c64ac4b 100644 --- a/cmd/xl-v1-common_test.go +++ b/cmd/xl-v1-common_test.go @@ -72,7 +72,7 @@ func TestXLParentDirIsObject(t *testing.T) { // Should not cause infinite loop. { parentIsObject: false, - objectName: "/", + objectName: SlashSeparator, }, { parentIsObject: false, diff --git a/cmd/xl-v1-healing.go b/cmd/xl-v1-healing.go index 29abbb376..7fc391db1 100644 --- a/cmd/xl-v1-healing.go +++ b/cmd/xl-v1-healing.go @@ -697,7 +697,7 @@ func (xl xlObjects) HealObject(ctx context.Context, bucket, object string, dryRu healCtx := logger.SetReqInfo(context.Background(), newReqInfo) // Healing directories handle it separately. - if hasSuffix(object, slashSeparator) { + if hasSuffix(object, SlashSeparator) { return xl.healObjectDir(healCtx, bucket, object, dryRun) } diff --git a/cmd/xl-v1-list-objects.go b/cmd/xl-v1-list-objects.go index c6d0d34ae..be046699f 100644 --- a/cmd/xl-v1-list-objects.go +++ b/cmd/xl-v1-list-objects.go @@ -63,7 +63,7 @@ func listDirFactory(ctx context.Context, disks ...StorageAPI) ListDirFunc { func (xl xlObjects) listObjects(ctx context.Context, bucket, prefix, marker, delimiter string, maxKeys int) (loi ListObjectsInfo, e error) { // Default is recursive, if delimiter is set then list non recursive. recursive := true - if delimiter == slashSeparator { + if delimiter == SlashSeparator { recursive = false } @@ -87,7 +87,7 @@ func (xl xlObjects) listObjects(ctx context.Context, bucket, prefix, marker, del } entry := walkResult.entry var objInfo ObjectInfo - if hasSuffix(entry, slashSeparator) { + if hasSuffix(entry, SlashSeparator) { // Object name needs to be full path. objInfo.Bucket = bucket objInfo.Name = entry @@ -125,7 +125,7 @@ func (xl xlObjects) listObjects(ctx context.Context, bucket, prefix, marker, del result := ListObjectsInfo{} for _, objInfo := range objInfos { - if objInfo.IsDir && delimiter == slashSeparator { + if objInfo.IsDir && delimiter == SlashSeparator { result.Prefixes = append(result.Prefixes, objInfo.Name) continue } @@ -165,7 +165,7 @@ func (xl xlObjects) ListObjects(ctx context.Context, bucket, prefix, marker, del // since according to s3 spec we stop at the 'delimiter' along // with the prefix. On a flat namespace with 'prefix' as '/' // we don't have any entries, since all the keys are of form 'keyName/...' - if delimiter == slashSeparator && prefix == slashSeparator { + if delimiter == SlashSeparator && prefix == SlashSeparator { return loi, nil } diff --git a/cmd/xl-v1-multipart.go b/cmd/xl-v1-multipart.go index 2f9b352cf..8d167760c 100644 --- a/cmd/xl-v1-multipart.go +++ b/cmd/xl-v1-multipart.go @@ -169,7 +169,7 @@ func (xl xlObjects) ListMultipartUploads(ctx context.Context, bucket, object, ke return result, err } for i := range uploadIDs { - uploadIDs[i] = strings.TrimSuffix(uploadIDs[i], slashSeparator) + uploadIDs[i] = strings.TrimSuffix(uploadIDs[i], SlashSeparator) } sort.Strings(uploadIDs) for _, uploadID := range uploadIDs { diff --git a/cmd/xl-v1-object.go b/cmd/xl-v1-object.go index be54d3083..85fadfda4 100644 --- a/cmd/xl-v1-object.go +++ b/cmd/xl-v1-object.go @@ -147,7 +147,7 @@ func (xl xlObjects) GetObjectNInfo(ctx context.Context, bucket, object string, r // Handler directory request by returning a reader that // returns no bytes. - if hasSuffix(object, slashSeparator) { + if hasSuffix(object, SlashSeparator) { var objInfo ObjectInfo if objInfo, err = xl.getObjectInfoDir(ctx, bucket, object); err != nil { nsUnlocker() @@ -216,7 +216,7 @@ func (xl xlObjects) getObject(ctx context.Context, bucket, object string, startO } // If its a directory request, we return an empty body. - if hasSuffix(object, slashSeparator) { + if hasSuffix(object, SlashSeparator) { _, err := writer.Write([]byte("")) logger.LogIf(ctx, err) return toObjectErr(err, bucket, object) @@ -379,7 +379,7 @@ func (xl xlObjects) GetObjectInfo(ctx context.Context, bucket, object string, op return oi, err } - if hasSuffix(object, slashSeparator) { + if hasSuffix(object, SlashSeparator) { info, err := xl.getObjectInfoDir(ctx, bucket, object) if err != nil { return oi, toObjectErr(err, bucket, object) @@ -865,7 +865,7 @@ func (xl xlObjects) deleteObjects(ctx context.Context, bucket string, objects [] } for i, object := range objects { - isObjectDirs[i] = hasSuffix(object, slashSeparator) + isObjectDirs[i] = hasSuffix(object, SlashSeparator) } for i, object := range objects { @@ -972,7 +972,7 @@ func (xl xlObjects) DeleteObject(ctx context.Context, bucket, object string) (er } var writeQuorum int - var isObjectDir = hasSuffix(object, slashSeparator) + var isObjectDir = hasSuffix(object, SlashSeparator) if isObjectDir { _, err = xl.getObjectInfoDir(ctx, bucket, object) diff --git a/cmd/xl-v1-object_test.go b/cmd/xl-v1-object_test.go index 23dc3c37e..dfbb90ee5 100644 --- a/cmd/xl-v1-object_test.go +++ b/cmd/xl-v1-object_test.go @@ -180,7 +180,7 @@ func TestXLDeleteObjectsXLSet(t *testing.T) { switch statErr.(type) { case ObjectNotFound: default: - t.Fatalf("Object %s is not removed", test.bucket+"/"+test.object) + t.Fatalf("Object %s is not removed", test.bucket+SlashSeparator+test.object) } } }