Skip to content

Commit

Permalink
handlers/objects: Deduplicate object writing code
Browse files Browse the repository at this point in the history
`NewUploadContainerObject`, `UploadContainerObject` and `PutObject` put
objects to the NeoFS in a very similar way.

Signed-off-by: Leonard Lyubich <[email protected]>
  • Loading branch information
cthulhu-rider committed Jun 25, 2024
1 parent 4437670 commit e6826ee
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 92 deletions.
46 changes: 15 additions & 31 deletions handlers/newObjects.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/nspcc-dev/neofs-rest-gw/handlers/apiserver"
"github.com/nspcc-dev/neofs-rest-gw/internal/util"
"github.com/nspcc-dev/neofs-sdk-go/bearer"
"github.com/nspcc-dev/neofs-sdk-go/client"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
Expand All @@ -22,7 +21,6 @@ import (
func (a *RestAPI) NewUploadContainerObject(ctx echo.Context, containerID apiserver.ContainerId, params apiserver.NewUploadContainerObjectParams) error {
var (
err error
idObj oid.ID
addr oid.Address
btoken *bearer.Token
)
Expand Down Expand Up @@ -98,40 +96,26 @@ func (a *RestAPI) NewUploadContainerObject(ctx echo.Context, containerID apiserv
}
}

var obj object.Object
obj.SetContainerID(idCnr)
a.setOwner(&obj, btoken)
obj.SetAttributes(attributes...)
var hdr object.Object
hdr.SetContainerID(idCnr)
a.setOwner(&hdr, btoken)
hdr.SetAttributes(attributes...)

Check warning on line 102 in handlers/newObjects.go

View check run for this annotation

Codecov / codecov/patch

handlers/newObjects.go#L99-L102

Added lines #L99 - L102 were not covered by tests

var prmPutInit client.PrmObjectPutInit
if btoken != nil {
prmPutInit.WithBearerToken(*btoken)
}

writer, err := a.pool.ObjectPutInit(ctx.Request().Context(), obj, a.signer, prmPutInit)
if err != nil {
resp := a.logAndGetErrorResponse("put object init", err)
return ctx.JSON(http.StatusBadRequest, resp)
}

if cln := ctx.Request().ContentLength; cln >= 0 && uint64(cln) < a.payloadBufferSize { // negative means unknown
if cln != 0 { // otherwise io.CopyBuffer panics
_, err = io.CopyBuffer(writer, ctx.Request().Body, make([]byte, cln))
idObj, err := a.putObject(ctx, hdr, btoken, func(w io.Writer) error {
var err error
if cln := ctx.Request().ContentLength; cln >= 0 && uint64(cln) < a.payloadBufferSize { // negative means unknown
if cln != 0 { // otherwise io.CopyBuffer panics
_, err = io.CopyBuffer(w, ctx.Request().Body, make([]byte, cln))

Check warning on line 108 in handlers/newObjects.go

View check run for this annotation

Codecov / codecov/patch

handlers/newObjects.go#L104-L108

Added lines #L104 - L108 were not covered by tests
}
} else {
_, err = io.CopyBuffer(w, ctx.Request().Body, make([]byte, a.payloadBufferSize))

Check warning on line 111 in handlers/newObjects.go

View check run for this annotation

Codecov / codecov/patch

handlers/newObjects.go#L110-L111

Added lines #L110 - L111 were not covered by tests
}
} else {
_, err = io.CopyBuffer(writer, ctx.Request().Body, make([]byte, a.payloadBufferSize))
}
return err

Check warning on line 113 in handlers/newObjects.go

View check run for this annotation

Codecov / codecov/patch

handlers/newObjects.go#L113

Added line #L113 was not covered by tests
})
if err != nil {
resp := a.logAndGetErrorResponse("write", err)
return ctx.JSON(http.StatusBadRequest, resp)
}

if err = writer.Close(); err != nil {
resp := a.logAndGetErrorResponse("writer close", err)
return ctx.JSON(http.StatusBadRequest, resp)
return err

Check warning on line 116 in handlers/newObjects.go

View check run for this annotation

Codecov / codecov/patch

handlers/newObjects.go#L116

Added line #L116 was not covered by tests
}

idObj = writer.GetResult().StoredObjectID()
addr.SetObject(idObj)
addr.SetContainer(idCnr)

Expand Down
88 changes: 27 additions & 61 deletions handlers/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,37 +117,19 @@ func (a *RestAPI) PutObject(ctx echo.Context, params apiserver.PutObjectParams)
return ctx.JSON(http.StatusBadRequest, resp)
}

var obj object.Object
obj.SetContainerID(cnrID)
attachOwner(&obj, btoken)
obj.SetAttributes(attributes...)

var prmPutInit client.PrmObjectPutInit
if btoken != nil {
prmPutInit.WithBearerToken(*btoken)
}

writer, err := a.pool.ObjectPutInit(ctx.Request().Context(), obj, a.signer, prmPutInit)
if err != nil {
resp := a.logAndGetErrorResponse("put object init", err)
return ctx.JSON(http.StatusBadRequest, resp)
}

var objID oid.ID

_, err = writer.Write(payload)
var hdr object.Object
hdr.SetContainerID(cnrID)
attachOwner(&hdr, btoken)
hdr.SetAttributes(attributes...)

Check warning on line 123 in handlers/objects.go

View check run for this annotation

Codecov / codecov/patch

handlers/objects.go#L120-L123

Added lines #L120 - L123 were not covered by tests

objID, err := a.putObject(ctx, hdr, btoken, func(w io.Writer) error {
_, err := w.Write(payload)
return err
})

Check warning on line 128 in handlers/objects.go

View check run for this annotation

Codecov / codecov/patch

handlers/objects.go#L125-L128

Added lines #L125 - L128 were not covered by tests
if err != nil {
resp := a.logAndGetErrorResponse("write", err)
return ctx.JSON(http.StatusBadRequest, resp)
return err

Check warning on line 130 in handlers/objects.go

View check run for this annotation

Codecov / codecov/patch

handlers/objects.go#L130

Added line #L130 was not covered by tests
}

if err = writer.Close(); err != nil {
resp := a.logAndGetErrorResponse("writer close", err)
return ctx.JSON(http.StatusBadRequest, resp)
}

objID = writer.GetResult().StoredObjectID()

var resp apiserver.Address
resp.ContainerId = body.ContainerId
resp.ObjectId = objID.String()
Expand Down Expand Up @@ -913,7 +895,6 @@ func (a *RestAPI) UploadContainerObject(ctx echo.Context, containerID apiserver.
header *multipart.FileHeader
file multipart.File
err error
idObj oid.ID
addr oid.Address
btoken *bearer.Token
)
Expand Down Expand Up @@ -1017,42 +998,27 @@ func (a *RestAPI) UploadContainerObject(ctx echo.Context, containerID apiserver.
attributes = append(attributes, *timestamp)
}

var obj object.Object
obj.SetContainerID(idCnr)
a.setOwner(&obj, btoken)
obj.SetAttributes(attributes...)
var hdr object.Object
hdr.SetContainerID(idCnr)
a.setOwner(&hdr, btoken)
hdr.SetAttributes(attributes...)

Check warning on line 1004 in handlers/objects.go

View check run for this annotation

Codecov / codecov/patch

handlers/objects.go#L1001-L1004

Added lines #L1001 - L1004 were not covered by tests

var prmPutInit client.PrmObjectPutInit
if btoken != nil {
prmPutInit.WithBearerToken(*btoken)
}

writer, err := a.pool.ObjectPutInit(ctx.Request().Context(), obj, a.signer, prmPutInit)
if err != nil {
resp := a.logAndGetErrorResponse("put object init", err)
return ctx.JSON(http.StatusBadRequest, resp)
}

var buf []byte
if header.Size > 0 && uint64(header.Size) < a.payloadBufferSize {
buf = make([]byte, header.Size)
} else {
// Size field is not documented, so we cannot be sure what exactly non-positive
// values mean. Thus, it's better to keep default behavior for them.
buf = make([]byte, a.payloadBufferSize)
}
_, err = io.CopyBuffer(writer, file, buf)
idObj, err := a.putObject(ctx, hdr, btoken, func(w io.Writer) error {
var buf []byte
if header.Size > 0 && uint64(header.Size) < a.payloadBufferSize {
buf = make([]byte, header.Size)
} else {

Check warning on line 1010 in handlers/objects.go

View check run for this annotation

Codecov / codecov/patch

handlers/objects.go#L1006-L1010

Added lines #L1006 - L1010 were not covered by tests
// Size field is not documented, so we cannot be sure what exactly non-positive
// values mean. Thus, it's better to keep default behavior for them.
buf = make([]byte, a.payloadBufferSize)

Check warning on line 1013 in handlers/objects.go

View check run for this annotation

Codecov / codecov/patch

handlers/objects.go#L1013

Added line #L1013 was not covered by tests
}
_, err = io.CopyBuffer(w, file, buf)
return err

Check warning on line 1016 in handlers/objects.go

View check run for this annotation

Codecov / codecov/patch

handlers/objects.go#L1015-L1016

Added lines #L1015 - L1016 were not covered by tests
})
if err != nil {
resp := a.logAndGetErrorResponse("write", err)
return ctx.JSON(http.StatusBadRequest, resp)
}

if err = writer.Close(); err != nil {
resp := a.logAndGetErrorResponse("writer close", err)
return ctx.JSON(http.StatusBadRequest, resp)
return err

Check warning on line 1019 in handlers/objects.go

View check run for this annotation

Codecov / codecov/patch

handlers/objects.go#L1019

Added line #L1019 was not covered by tests
}

idObj = writer.GetResult().StoredObjectID()
addr.SetObject(idObj)
addr.SetContainer(idCnr)

Expand Down
30 changes: 30 additions & 0 deletions handlers/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"math"
"net/http"
"strconv"
"strings"
"time"

"github.com/labstack/echo/v4"
"github.com/nspcc-dev/neofs-rest-gw/handlers/apiserver"
"github.com/nspcc-dev/neofs-sdk-go/bearer"
"github.com/nspcc-dev/neofs-sdk-go/client"
"github.com/nspcc-dev/neofs-sdk-go/container/acl"
"github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/nspcc-dev/neofs-sdk-go/pool"
"github.com/nspcc-dev/neofs-sdk-go/session"
"go.uber.org/zap"
Expand Down Expand Up @@ -400,3 +404,29 @@ func addExpirationHeaders(headers map[string]string, params apiserver.NewUploadC
headers[ExpirationRFC3339Attr] = *params.XNeofsExpirationRFC3339
}
}

// shares code of NeoFS object recording performed by various RestAPI methods.
func (a *RestAPI) putObject(ctx echo.Context, hdr object.Object, bt *bearer.Token, wp func(io.Writer) error) (oid.ID, error) {
var opts client.PrmObjectPutInit
if bt != nil {
opts.WithBearerToken(*bt)

Check warning on line 412 in handlers/util.go

View check run for this annotation

Codecov / codecov/patch

handlers/util.go#L409-L412

Added lines #L409 - L412 were not covered by tests
}
writer, err := a.pool.ObjectPutInit(ctx.Request().Context(), hdr, a.signer, opts)
if err != nil {
resp := a.logAndGetErrorResponse("put object init", err)
return oid.ID{}, ctx.JSON(http.StatusBadRequest, resp)

Check warning on line 417 in handlers/util.go

View check run for this annotation

Codecov / codecov/patch

handlers/util.go#L414-L417

Added lines #L414 - L417 were not covered by tests
}

err = wp(writer)
if err != nil {
resp := a.logAndGetErrorResponse("write", err)
return oid.ID{}, ctx.JSON(http.StatusBadRequest, resp)

Check warning on line 423 in handlers/util.go

View check run for this annotation

Codecov / codecov/patch

handlers/util.go#L420-L423

Added lines #L420 - L423 were not covered by tests
}

if err = writer.Close(); err != nil {
resp := a.logAndGetErrorResponse("writer close", err)
return oid.ID{}, ctx.JSON(http.StatusBadRequest, resp)

Check warning on line 428 in handlers/util.go

View check run for this annotation

Codecov / codecov/patch

handlers/util.go#L426-L428

Added lines #L426 - L428 were not covered by tests
}

return writer.GetResult().StoredObjectID(), nil

Check warning on line 431 in handlers/util.go

View check run for this annotation

Codecov / codecov/patch

handlers/util.go#L431

Added line #L431 was not covered by tests
}

0 comments on commit e6826ee

Please sign in to comment.