perf(alias): disabled log on fs call (close #4054)

pull/4066/head v3.15.1
Andy Hsu 2023-04-07 00:02:07 +08:00
parent a475783b00
commit 0f8a84f67e
12 changed files with 48 additions and 41 deletions

View File

@ -51,7 +51,7 @@ func (d *Alias) getRootAndPath(path string) (string, string) {
} }
func (d *Alias) get(ctx context.Context, path string, dst, sub string) (model.Obj, error) { func (d *Alias) get(ctx context.Context, path string, dst, sub string) (model.Obj, error) {
obj, err := fs.Get(ctx, stdpath.Join(dst, sub)) obj, err := fs.Get(ctx, stdpath.Join(dst, sub), &fs.GetArgs{NoLog: true})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -65,7 +65,7 @@ func (d *Alias) get(ctx context.Context, path string, dst, sub string) (model.Ob
} }
func (d *Alias) list(ctx context.Context, dst, sub string) ([]model.Obj, error) { func (d *Alias) list(ctx context.Context, dst, sub string) ([]model.Obj, error) {
objs, err := fs.List(ctx, stdpath.Join(dst, sub)) objs, err := fs.List(ctx, stdpath.Join(dst, sub), &fs.ListArgs{NoLog: true})
// the obj must implement the model.SetPath interface // the obj must implement the model.SetPath interface
// return objs, err // return objs, err
if err != nil { if err != nil {
@ -83,11 +83,11 @@ func (d *Alias) list(ctx context.Context, dst, sub string) ([]model.Obj, error)
func (d *Alias) link(ctx context.Context, dst, sub string, args model.LinkArgs) (*model.Link, error) { func (d *Alias) link(ctx context.Context, dst, sub string, args model.LinkArgs) (*model.Link, error) {
reqPath := stdpath.Join(dst, sub) reqPath := stdpath.Join(dst, sub)
storage, err := fs.GetStorage(reqPath) storage, err := fs.GetStorage(reqPath, &fs.GetStoragesArgs{NoLog: true})
if err != nil { if err != nil {
return nil, err return nil, err
} }
_, err = fs.Get(ctx, reqPath) _, err = fs.Get(ctx, reqPath, &fs.GetArgs{NoLog: true})
if err != nil { if err != nil {
return nil, err return nil, err
} }

6
go.sum
View File

@ -129,8 +129,6 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hirochachacha/go-smb2 v1.1.0 h1:b6hs9qKIql9eVXAiN0M2wSFY5xnhbHAQoCwRKbaRTZI= github.com/hirochachacha/go-smb2 v1.1.0 h1:b6hs9qKIql9eVXAiN0M2wSFY5xnhbHAQoCwRKbaRTZI=
github.com/hirochachacha/go-smb2 v1.1.0/go.mod h1:8F1A4d5EZzrGu5R7PU163UcMRDJQl4FtcxjBfsY8TZE= github.com/hirochachacha/go-smb2 v1.1.0/go.mod h1:8F1A4d5EZzrGu5R7PU163UcMRDJQl4FtcxjBfsY8TZE=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
@ -216,8 +214,6 @@ github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@ -248,8 +244,6 @@ github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/upyun/go-sdk/v3 v3.0.3 h1:2wUkNk2fyJReMYHMvJyav050D83rYwSjN7mEPR0Pp8Q=
github.com/upyun/go-sdk/v3 v3.0.3/go.mod h1:P/SnuuwhrIgAVRd/ZpzDWqCsBAf/oHg7UggbAxyZa0E=
github.com/upyun/go-sdk/v3 v3.0.4 h1:2DCJa/Yi7/3ZybT9UCPATSzvU3wpPPxhXinNlb1Hi8Q= github.com/upyun/go-sdk/v3 v3.0.4 h1:2DCJa/Yi7/3ZybT9UCPATSzvU3wpPPxhXinNlb1Hi8Q=
github.com/upyun/go-sdk/v3 v3.0.4/go.mod h1:P/SnuuwhrIgAVRd/ZpzDWqCsBAf/oHg7UggbAxyZa0E= github.com/upyun/go-sdk/v3 v3.0.4/go.mod h1:P/SnuuwhrIgAVRd/ZpzDWqCsBAf/oHg7UggbAxyZa0E=
github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc= github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc=

View File

@ -13,8 +13,13 @@ import (
// So, the purpose of this package is to convert mount path to actual path // So, the purpose of this package is to convert mount path to actual path
// then pass the actual path to the op package // then pass the actual path to the op package
func List(ctx context.Context, path string, refresh ...bool) ([]model.Obj, error) { type ListArgs struct {
res, err := list(ctx, path, refresh...) Refresh bool
NoLog bool
}
func List(ctx context.Context, path string, args *ListArgs) ([]model.Obj, error) {
res, err := list(ctx, path, args)
if err != nil { if err != nil {
log.Errorf("failed list %s: %+v", path, err) log.Errorf("failed list %s: %+v", path, err)
return nil, err return nil, err
@ -22,9 +27,13 @@ func List(ctx context.Context, path string, refresh ...bool) ([]model.Obj, error
return res, nil return res, nil
} }
func Get(ctx context.Context, path string) (model.Obj, error) { type GetArgs struct {
NoLog bool
}
func Get(ctx context.Context, path string, args *GetArgs) (model.Obj, error) {
res, err := get(ctx, path) res, err := get(ctx, path)
if err != nil { if err != nil && !args.NoLog {
log.Errorf("failed get %s: %+v", path, err) log.Errorf("failed get %s: %+v", path, err)
return nil, err return nil, err
} }
@ -96,9 +105,13 @@ func PutAsTask(dstDirPath string, file *model.FileStream) error {
return err return err
} }
func GetStorage(path string) (driver.Driver, error) { type GetStoragesArgs struct {
NoLog bool
}
func GetStorage(path string, args *GetStoragesArgs) (driver.Driver, error) {
storageDriver, _, err := op.GetStorageAndActualPath(path) storageDriver, _, err := op.GetStorageAndActualPath(path)
if err != nil { if err != nil && !args.NoLog {
return nil, err return nil, err
} }
return storageDriver, nil return storageDriver, nil

View File

@ -11,7 +11,7 @@ import (
) )
// List files // List files
func list(ctx context.Context, path string, refresh ...bool) ([]model.Obj, error) { func list(ctx context.Context, path string, args *ListArgs) ([]model.Obj, error) {
meta := ctx.Value("meta").(*model.Meta) meta := ctx.Value("meta").(*model.Meta)
user := ctx.Value("user").(*model.User) user := ctx.Value("user").(*model.User)
virtualFiles := op.GetStorageVirtualFilesByPath(path) virtualFiles := op.GetStorageVirtualFilesByPath(path)
@ -24,7 +24,7 @@ func list(ctx context.Context, path string, refresh ...bool) ([]model.Obj, error
if storage != nil { if storage != nil {
_objs, err = op.List(ctx, storage, actualPath, model.ListArgs{ _objs, err = op.List(ctx, storage, actualPath, model.ListArgs{
ReqPath: path, ReqPath: path,
}, refresh...) }, args.Refresh)
if err != nil { if err != nil {
log.Errorf("%+v", err) log.Errorf("%+v", err)
if len(virtualFiles) == 0 { if len(virtualFiles) == 0 {

View File

@ -28,7 +28,7 @@ func WalkFS(ctx context.Context, depth int, name string, info model.Obj, walkFn
} }
meta, _ := op.GetNearestMeta(name) meta, _ := op.GetNearestMeta(name)
// Read directory names. // Read directory names.
objs, err := List(context.WithValue(ctx, "meta", meta), name) objs, err := List(context.WithValue(ctx, "meta", meta), name, &ListArgs{})
if err != nil { if err != nil {
return walkFnErr return walkFnErr
} }

View File

@ -141,7 +141,7 @@ func BuildIndex(ctx context.Context, indexPaths, ignorePaths []string, maxDepth
}) })
return nil return nil
} }
fi, err = fs.Get(ctx, indexPath) fi, err = fs.Get(ctx, indexPath, &fs.GetArgs{})
if err != nil { if err != nil {
return err return err
} }

View File

@ -21,7 +21,7 @@ import (
func Down(c *gin.Context) { func Down(c *gin.Context) {
rawPath := c.MustGet("path").(string) rawPath := c.MustGet("path").(string)
filename := stdpath.Base(rawPath) filename := stdpath.Base(rawPath)
storage, err := fs.GetStorage(rawPath) storage, err := fs.GetStorage(rawPath, &fs.GetStoragesArgs{})
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
@ -65,7 +65,7 @@ func Down(c *gin.Context) {
func Proxy(c *gin.Context) { func Proxy(c *gin.Context) {
rawPath := c.MustGet("path").(string) rawPath := c.MustGet("path").(string)
filename := stdpath.Base(rawPath) filename := stdpath.Base(rawPath)
storage, err := fs.GetStorage(rawPath) storage, err := fs.GetStorage(rawPath, &fs.GetStoragesArgs{})
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return

View File

@ -133,7 +133,7 @@ func FsRecursiveMove(c *gin.Context) {
} }
c.Set("meta", meta) c.Set("meta", meta)
rootFiles, err := fs.List(c, srcDir, false) rootFiles, err := fs.List(c, srcDir, &fs.ListArgs{})
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
@ -154,7 +154,7 @@ func FsRecursiveMove(c *gin.Context) {
if movingFile.IsDir() { if movingFile.IsDir() {
// directory, recursive move // directory, recursive move
subFilePath := movingFilePath subFilePath := movingFilePath
subFiles, err := fs.List(c, subFilePath, true) subFiles, err := fs.List(c, subFilePath, &fs.ListArgs{Refresh: true})
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
@ -293,7 +293,7 @@ func FsRegexRename(c *gin.Context) {
return return
} }
files, err := fs.List(c, reqPath, false) files, err := fs.List(c, reqPath, &fs.ListArgs{})
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
@ -362,7 +362,7 @@ func Link(c *gin.Context) {
//rawPath := stdpath.Join(user.BasePath, req.Path) //rawPath := stdpath.Join(user.BasePath, req.Path)
// why need not join base_path? because it's always the full path // why need not join base_path? because it's always the full path
rawPath := req.Path rawPath := req.Path
storage, err := fs.GetStorage(rawPath) storage, err := fs.GetStorage(rawPath, &fs.GetStoragesArgs{})
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return

View File

@ -79,14 +79,14 @@ func FsList(c *gin.Context) {
common.ErrorStrResp(c, "Refresh without permission", 403) common.ErrorStrResp(c, "Refresh without permission", 403)
return return
} }
objs, err := fs.List(c, reqPath, req.Refresh) objs, err := fs.List(c, reqPath, &fs.ListArgs{Refresh: req.Refresh})
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
} }
total, objs := pagination(objs, &req.PageReq) total, objs := pagination(objs, &req.PageReq)
provider := "unknown" provider := "unknown"
storage, err := fs.GetStorage(reqPath) storage, err := fs.GetStorage(reqPath, &fs.GetStoragesArgs{})
if err == nil { if err == nil {
provider = storage.GetStorage().Driver provider = storage.GetStorage().Driver
} }
@ -132,7 +132,7 @@ func FsDirs(c *gin.Context) {
common.ErrorStrResp(c, "password is incorrect or you have no permission", 403) common.ErrorStrResp(c, "password is incorrect or you have no permission", 403)
return return
} }
objs, err := fs.List(c, reqPath) objs, err := fs.List(c, reqPath, &fs.ListArgs{})
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
@ -247,14 +247,14 @@ func FsGet(c *gin.Context) {
common.ErrorStrResp(c, "password is incorrect or you have no permission", 403) common.ErrorStrResp(c, "password is incorrect or you have no permission", 403)
return return
} }
obj, err := fs.Get(c, reqPath) obj, err := fs.Get(c, reqPath, &fs.GetArgs{})
if err != nil { if err != nil {
common.ErrorResp(c, err, 500) common.ErrorResp(c, err, 500)
return return
} }
var rawURL string var rawURL string
storage, err := fs.GetStorage(reqPath) storage, err := fs.GetStorage(reqPath, &fs.GetStoragesArgs{})
provider := "unknown" provider := "unknown"
if err == nil { if err == nil {
provider = storage.Config().Name provider = storage.Config().Name
@ -297,7 +297,7 @@ func FsGet(c *gin.Context) {
} }
var related []model.Obj var related []model.Obj
parentPath := stdpath.Dir(reqPath) parentPath := stdpath.Dir(reqPath)
sameLevelFiles, err := fs.List(c, parentPath) sameLevelFiles, err := fs.List(c, parentPath, &fs.ListArgs{})
if err == nil { if err == nil {
related = filterRelated(sameLevelFiles, obj) related = filterRelated(sameLevelFiles, obj)
} }

View File

@ -69,7 +69,7 @@ func FsForm(c *gin.Context) {
common.ErrorResp(c, err, 403) common.ErrorResp(c, err, 403)
return return
} }
storage, err := fs.GetStorage(path) storage, err := fs.GetStorage(path, &fs.GetStoragesArgs{})
if err != nil { if err != nil {
common.ErrorResp(c, err, 400) common.ErrorResp(c, err, 400)
return return

View File

@ -84,7 +84,7 @@ func walkFS(ctx context.Context, depth int, name string, info model.Obj, walkFn
} }
meta, _ := op.GetNearestMeta(name) meta, _ := op.GetNearestMeta(name)
// Read directory names. // Read directory names.
objs, err := fs.List(context.WithValue(ctx, "meta", meta), name) objs, err := fs.List(context.WithValue(ctx, "meta", meta), name, &fs.ListArgs{})
//f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0) //f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0)
//if err != nil { //if err != nil {
// return walkFn(name, info, err) // return walkFn(name, info, err)

View File

@ -188,7 +188,7 @@ func (h *Handler) handleOptions(w http.ResponseWriter, r *http.Request) (status
return 403, err return 403, err
} }
allow := "OPTIONS, LOCK, PUT, MKCOL" allow := "OPTIONS, LOCK, PUT, MKCOL"
if fi, err := fs.Get(ctx, reqPath); err == nil { if fi, err := fs.Get(ctx, reqPath, &fs.GetArgs{}); err == nil {
if fi.IsDir() { if fi.IsDir() {
allow = "OPTIONS, LOCK, DELETE, PROPPATCH, COPY, MOVE, UNLOCK, PROPFIND" allow = "OPTIONS, LOCK, DELETE, PROPPATCH, COPY, MOVE, UNLOCK, PROPFIND"
} else { } else {
@ -215,7 +215,7 @@ func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request) (sta
if err != nil { if err != nil {
return 403, err return 403, err
} }
fi, err := fs.Get(ctx, reqPath) fi, err := fs.Get(ctx, reqPath, &fs.GetArgs{})
if err != nil { if err != nil {
return http.StatusNotFound, err return http.StatusNotFound, err
} }
@ -228,7 +228,7 @@ func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request) (sta
} }
w.Header().Set("ETag", etag) w.Header().Set("ETag", etag)
// Let ServeContent determine the Content-Type header. // Let ServeContent determine the Content-Type header.
storage, _ := fs.GetStorage(reqPath) storage, _ := fs.GetStorage(reqPath, &fs.GetStoragesArgs{})
downProxyUrl := storage.GetStorage().DownProxyUrl downProxyUrl := storage.GetStorage().DownProxyUrl
if storage.GetStorage().WebdavNative() || (storage.GetStorage().WebdavProxy() && downProxyUrl == "") { if storage.GetStorage().WebdavNative() || (storage.GetStorage().WebdavProxy() && downProxyUrl == "") {
link, _, err := fs.Link(ctx, reqPath, model.LinkArgs{Header: r.Header}) link, _, err := fs.Link(ctx, reqPath, model.LinkArgs{Header: r.Header})
@ -278,7 +278,7 @@ func (h *Handler) handleDelete(w http.ResponseWriter, r *http.Request) (status i
// "godoc os RemoveAll" says that "If the path does not exist, RemoveAll // "godoc os RemoveAll" says that "If the path does not exist, RemoveAll
// returns nil (no error)." WebDAV semantics are that it should return a // returns nil (no error)." WebDAV semantics are that it should return a
// "404 Not Found". We therefore have to Stat before we RemoveAll. // "404 Not Found". We therefore have to Stat before we RemoveAll.
if _, err := fs.Get(ctx, reqPath); err != nil { if _, err := fs.Get(ctx, reqPath, &fs.GetArgs{}); err != nil {
if errs.IsObjectNotFound(err) { if errs.IsObjectNotFound(err) {
return http.StatusNotFound, err return http.StatusNotFound, err
} }
@ -331,7 +331,7 @@ func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request) (status int,
if err != nil { if err != nil {
return http.StatusMethodNotAllowed, err return http.StatusMethodNotAllowed, err
} }
fi, err := fs.Get(ctx, reqPath) fi, err := fs.Get(ctx, reqPath, &fs.GetArgs{})
if err != nil { if err != nil {
fi = &obj fi = &obj
} }
@ -591,7 +591,7 @@ func (h *Handler) handlePropfind(w http.ResponseWriter, r *http.Request) (status
if err != nil { if err != nil {
return 403, err return 403, err
} }
fi, err := fs.Get(ctx, reqPath) fi, err := fs.Get(ctx, reqPath, &fs.GetArgs{})
if err != nil { if err != nil {
if errs.IsObjectNotFound(err) { if errs.IsObjectNotFound(err) {
return http.StatusNotFound, err return http.StatusNotFound, err
@ -670,7 +670,7 @@ func (h *Handler) handleProppatch(w http.ResponseWriter, r *http.Request) (statu
if err != nil { if err != nil {
return 403, err return 403, err
} }
if _, err := fs.Get(ctx, reqPath); err != nil { if _, err := fs.Get(ctx, reqPath, &fs.GetArgs{}); err != nil {
if errs.IsObjectNotFound(err) { if errs.IsObjectNotFound(err) {
return http.StatusNotFound, err return http.StatusNotFound, err
} }