Compare commits

..

1 commit

Author SHA1 Message Date
e844ace43d [#142] Fix multipart-objects download
All checks were successful
/ DCO (pull_request) Successful in 1m3s
/ Vulncheck (pull_request) Successful in 1m29s
/ Builds (pull_request) Successful in 57s
/ Lint (pull_request) Successful in 2m8s
/ Tests (pull_request) Successful in 1m0s
Signed-off-by: Nikita Zinkevich <n.zinkevich@yadro.com>
2024-10-15 15:43:35 +03:00
6 changed files with 23 additions and 27 deletions

View file

@ -189,7 +189,7 @@ func New(params *AppParams, config Config, tree *tree.Tree) *Handler {
// byAddress is a wrapper for function (e.g. request.headObject, request.receiveFile) that
// prepares request and object address to it.
func (h *Handler) byAddress(c *fasthttp.RequestCtx, f func(context.Context, request, oid.Address, *data.BucketInfo)) {
func (h *Handler) byAddress(c *fasthttp.RequestCtx, f func(context.Context, request, oid.Address)) {
var (
idCnr, _ = c.UserValue("cid").(string)
idObj, _ = c.UserValue("oid").(string)
@ -213,12 +213,12 @@ func (h *Handler) byAddress(c *fasthttp.RequestCtx, f func(context.Context, requ
addr := newAddress(bktInfo.CID, *objID)
f(ctx, *h.newRequest(c, log), addr, bktInfo)
f(ctx, *h.newRequest(c, log), addr)
}
// byObjectName is a wrapper for function (e.g. request.headObject, request.receiveFile) that
// prepares request and object address to it.
func (h *Handler) byObjectName(c *fasthttp.RequestCtx, f func(context.Context, request, oid.Address, *data.BucketInfo)) {
func (h *Handler) byObjectName(c *fasthttp.RequestCtx, f func(context.Context, request, oid.Address)) {
var (
bucketname = c.UserValue("cid").(string)
key = c.UserValue("oid").(string)
@ -266,11 +266,11 @@ func (h *Handler) byObjectName(c *fasthttp.RequestCtx, f func(context.Context, r
}
addr := newAddress(bktInfo.CID, foundOid.OID)
f(ctx, *h.newRequest(c, log), addr, bktInfo)
f(ctx, *h.newRequest(c, log), addr)
}
// byAttribute is a wrapper similar to byAddress.
func (h *Handler) byAttribute(c *fasthttp.RequestCtx, f func(context.Context, request, oid.Address, *data.BucketInfo)) {
func (h *Handler) byAttribute(c *fasthttp.RequestCtx, f func(context.Context, request, oid.Address)) {
scid, _ := c.UserValue("cid").(string)
key, _ := c.UserValue("attr_key").(string)
val, _ := c.UserValue("attr_val").(string)
@ -327,7 +327,7 @@ func (h *Handler) byAttribute(c *fasthttp.RequestCtx, f func(context.Context, re
addrObj.SetContainer(bktInfo.CID)
addrObj.SetObject(buf[0])
f(ctx, *h.newRequest(c, log), addrObj, bktInfo)
f(ctx, *h.newRequest(c, log), addrObj)
}
// resolveContainer decode container id, if it's not a valid container id

View file

@ -7,7 +7,6 @@ import (
"strconv"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/data"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/utils"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
@ -25,7 +24,7 @@ const (
hdrContainerID = "X-Container-Id"
)
func (h *Handler) headObject(ctx context.Context, req request, objectAddress oid.Address, _ *data.BucketInfo) {
func (h *Handler) headObject(ctx context.Context, req request, objectAddress oid.Address) {
var start = time.Now()
btoken := bearerToken(ctx)

View file

@ -66,8 +66,6 @@ func (h *Handler) getPayload(p getMultiobjectBodyParams) (io.ReadCloser, uint64,
}
ctx := p.req.RequestCtx
params := PrmInitMultiObjectReader{
Off: 0,
Ln: 0,
Addr: newAddress(cid, oid),
Bearer: bearerToken(ctx),
}

View file

@ -9,7 +9,6 @@ import (
"strconv"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/data"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/response"
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/utils"
@ -51,19 +50,16 @@ func readContentType(maxSize uint64, rInit func(uint64) (io.Reader, error)) (str
type getMultiobjectBodyParams struct {
obj *Object
req request
bktinfo *data.BucketInfo
strSize string
}
func (h *Handler) receiveFile(ctx context.Context, req request, objAddress oid.Address, bktInfo *data.BucketInfo) {
func (h *Handler) receiveFile(ctx context.Context, req request, objAddress oid.Address) {
var (
shouldDownload = req.QueryArgs().GetBool("download")
start = time.Now()
filename string
filepath string
contentType string
payload io.ReadCloser
payloadSize uint64
)
prm := PrmObjectGet{
@ -81,8 +77,8 @@ func (h *Handler) receiveFile(ctx context.Context, req request, objAddress oid.A
// we can't close reader in this function, so how to do it?
req.setIDs(rObj.Header)
payload = rObj.Payload
payloadSize = rObj.Header.PayloadSize()
payload := rObj.Payload
payloadSize := rObj.Header.PayloadSize()
for _, attr := range rObj.Header.Attributes() {
key := attr.Key()
val := attr.Value()
@ -106,14 +102,10 @@ func (h *Handler) receiveFile(ctx context.Context, req request, objAddress oid.A
contentType = val
case object.AttributeFilePath:
filepath = val
if filename == "" {
filename = filepath
}
case attributeMultipartObjectSize:
payload, payloadSize, err = h.getPayload(getMultiobjectBodyParams{
obj: rObj,
req: req,
bktinfo: bktInfo,
strSize: val,
})
if err != nil {
@ -122,6 +114,10 @@ func (h *Handler) receiveFile(ctx context.Context, req request, objAddress oid.A
}
}
}
if filename == "" {
filename = filepath
}
req.setDisposition(shouldDownload, filename)
req.Response.Header.Set(fasthttp.HeaderContentLength, strconv.FormatUint(payloadSize, 10))

View file

@ -36,7 +36,7 @@ type PartObj struct {
}
type readerInitiator interface {
InitFrostFSObjectPayloadReader(ctx context.Context, p GetFrostFSParams) (io.Reader, error)
InitFrostFSObjectPayloadReader(ctx context.Context, p GetFrostFSParams) (io.ReadCloser, error)
}
// MultiObjectReader implements io.Reader of payloads of the object list stored in the FrostFS network.
@ -51,7 +51,7 @@ type MultiObjectReader struct {
prm GetFrostFSParams
curIndex int
curReader io.Reader
curReader io.ReadCloser
parts []PartObj
}
@ -175,6 +175,9 @@ func (x *MultiObjectReader) Read(p []byte) (n int, err error) {
if !errors.Is(err, io.EOF) {
return n, err
}
if err = x.curReader.Close(); err != nil {
return n, err
}
x.curIndex++
}
@ -208,7 +211,7 @@ func (x *MultiObjectReader) Read(p []byte) (n int, err error) {
// InitFrostFSObjectPayloadReader initializes payload reader of the FrostFS object.
// Zero range corresponds to full payload (panics if only offset is set).
func (x *FrostFS) InitFrostFSObjectPayloadReader(ctx context.Context, p GetFrostFSParams) (io.Reader, error) {
func (x *FrostFS) InitFrostFSObjectPayloadReader(ctx context.Context, p GetFrostFSParams) (io.ReadCloser, error) {
var prmAuth handler.PrmAuth
if p.Off+p.Ln != 0 {

View file

@ -17,14 +17,14 @@ type readerInitiatorMock struct {
parts map[oid.ID][]byte
}
func (r *readerInitiatorMock) InitFrostFSObjectPayloadReader(_ context.Context, p GetFrostFSParams) (io.Reader, error) {
func (r *readerInitiatorMock) InitFrostFSObjectPayloadReader(_ context.Context, p GetFrostFSParams) (io.ReadCloser, error) {
partPayload, ok := r.parts[p.Addr.Object()]
if !ok {
return nil, errors.New("part not found")
}
if p.Off+p.Ln == 0 {
return bytes.NewReader(partPayload), nil
return io.NopCloser(bytes.NewReader(partPayload)), nil
}
if p.Off > uint64(len(partPayload)-1) {
@ -35,7 +35,7 @@ func (r *readerInitiatorMock) InitFrostFSObjectPayloadReader(_ context.Context,
return nil, fmt.Errorf("invalid range: %d-%d/%d", p.Off, p.Off+p.Ln, len(partPayload))
}
return bytes.NewReader(partPayload[p.Off : p.Off+p.Ln]), nil
return io.NopCloser(bytes.NewReader(partPayload[p.Off : p.Off+p.Ln])), nil
}
func prepareDataReader() ([]byte, []PartObj, *readerInitiatorMock) {