[#151] index page: Add browse via native protocol
All checks were successful
/ DCO (pull_request) Successful in 2m14s
/ Vulncheck (pull_request) Successful in 2m13s
/ Builds (pull_request) Successful in 1m6s
/ Lint (pull_request) Successful in 2m55s
/ Tests (pull_request) Successful in 1m37s

Signed-off-by: Nikita Zinkevich <n.zinkevich@yadro.com>
This commit is contained in:
Nikita Zinkevich 2024-11-14 13:25:38 +03:00
parent 524117a344
commit 3b26cf921c
Signed by: nzinkevich
GPG key ID: 748EA1D0B2E6420A
4 changed files with 164 additions and 48 deletions

View file

@ -23,12 +23,16 @@ import (
// DownloadByAddressOrBucketName handles download requests using simple cid/oid or bucketname/key format.
func (h *Handler) DownloadByAddressOrBucketName(c *fasthttp.RequestCtx) {
cnrIDStr, _ := c.UserValue("cid").(string)
var cnrID cid.ID
if err := cnrID.DecodeString(cnrIDStr); err != nil {
h.byS3Path(c, h.receiveFile)
} else {
oidURLParam := c.UserValue("oid").(string)
downloadQueryParam := c.QueryArgs().GetBool("download")
switch {
case isObjectID(oidURLParam):
h.byNativeAddress(c, h.receiveFile)
case !isContainerRoot(oidURLParam) && (downloadQueryParam || !isDir(oidURLParam)):
h.byS3Path(c, h.receiveFile)
default:
h.browseIndex(c)
}
}

View file

@ -208,16 +208,6 @@ func (h *Handler) byNativeAddress(c *fasthttp.RequestCtx, f func(context.Context
objID := new(oid.ID)
if err = objID.DecodeString(idObj); err != nil {
if h.config.IndexPageEnabled() {
c.SetStatusCode(fasthttp.StatusNotFound)
h.browseObjects(c, browseParams{
bucketInfo: bktInfo,
prefix: idObj,
listObjects: h.getDirObjectsNative,
isNative: true,
})
return
}
log.Error(logs.WrongObjectID, zap.Error(err))
response.Error(c, "wrong object id", fasthttp.StatusBadRequest)
return
@ -233,7 +223,6 @@ func (h *Handler) byNativeAddress(c *fasthttp.RequestCtx, f func(context.Context
func (h *Handler) byS3Path(c *fasthttp.RequestCtx, f func(context.Context, request, oid.Address)) {
bucketname := c.UserValue("cid").(string)
key := c.UserValue("oid").(string)
download := c.QueryArgs().GetBool("download")
ctx := utils.GetContextFromRequest(c)
reqLog := utils.GetReqLogOrDefault(ctx, h.log)
@ -252,20 +241,6 @@ func (h *Handler) byS3Path(c *fasthttp.RequestCtx, f func(context.Context, reque
}
foundOid, err := h.tree.GetLatestVersion(ctx, &bktInfo.CID, unescapedKey)
if h.config.IndexPageEnabled() && !download && string(c.Method()) != fasthttp.MethodHead {
if isDir(unescapedKey) || isContainerRoot(unescapedKey) {
if code := checkErrorType(err); code == fasthttp.StatusNotFound || code == fasthttp.StatusOK {
c.SetStatusCode(code)
h.browseObjects(c, browseParams{
bucketInfo: bktInfo,
prefix: unescapedKey,
listObjects: h.getDirObjectsS3,
isNative: false,
})
return
}
}
}
if err != nil {
if errors.Is(err, tree.ErrNodeAccessDenied) {
response.Error(c, "Access Denied", fasthttp.StatusForbidden)
@ -412,3 +387,54 @@ func (h *Handler) readContainer(ctx context.Context, cnrID cid.ID) (*data.Bucket
return bktInfo, err
}
func (h *Handler) browseIndex(c *fasthttp.RequestCtx) {
if !h.config.IndexPageEnabled() {
c.SetStatusCode(fasthttp.StatusNotFound)
return
}
cidURLParam := c.UserValue("cid").(string)
oidURLParam := c.UserValue("oid").(string)
ctx := utils.GetContextFromRequest(c)
reqLog := utils.GetReqLogOrDefault(ctx, h.log)
log := reqLog.With(zap.String("cid", cidURLParam), zap.String("oid", oidURLParam))
unescapedKey, err := url.QueryUnescape(oidURLParam)
if err != nil {
logAndSendBucketError(c, log, err)
return
}
bktInfo, err := h.getBucketInfo(ctx, cidURLParam, log)
if err != nil {
logAndSendBucketError(c, log, err)
return
}
c.SetStatusCode(fasthttp.StatusOK)
listFunc := h.getDirObjectsS3
isNativeList := false
err = h.tree.CheckSettingsNodeExist(ctx, bktInfo)
if err != nil {
if errors.Is(err, tree.ErrNodeNotFound) {
// tree probe failed, try to use native
listFunc = h.getDirObjectsNative
isNativeList = true
} else {
logAndSendBucketError(c, log, err)
return
}
}
c.SetStatusCode(fasthttp.StatusOK)
h.browseObjects(c, browseParams{
bucketInfo: bktInfo,
prefix: unescapedKey,
listObjects: listFunc,
isNative: isNativeList,
})
}

View file

@ -2,14 +2,12 @@ package handler
import (
"context"
"errors"
"strings"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/response"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/tokens"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/tree"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
@ -47,19 +45,13 @@ func isDir(name string) bool {
return strings.HasSuffix(name, "/")
}
func isContainerRoot(key string) bool {
return key == ""
func isObjectID(s string) bool {
var objID oid.ID
return objID.DecodeString(s) == nil
}
func checkErrorType(err error) int {
switch {
case err == nil:
return fasthttp.StatusOK
case errors.Is(err, tree.ErrNodeAccessDenied):
return fasthttp.StatusForbidden
default:
return fasthttp.StatusNotFound
}
func isContainerRoot(key string) bool {
return key == ""
}
func loadAttributes(attrs []object.Attribute) map[string]string {