forked from TrueCloudLab/frostfs-sdk-go
[#323] client: Refactor object.Hash
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
0236b03fa7
commit
8c5333ea55
2 changed files with 80 additions and 31 deletions
|
@ -65,6 +65,20 @@ func (x prmCommonMeta) writeToMetaHeader(h *v2session.RequestMetaHeader) {
|
|||
}
|
||||
}
|
||||
|
||||
func writeXHeadersToMeta(xHeaders []string, h *v2session.RequestMetaHeader) {
|
||||
if len(xHeaders) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
hs := make([]v2session.XHeader, len(xHeaders)/2)
|
||||
for i := 0; i < len(xHeaders); i += 2 {
|
||||
hs[i].SetKey(xHeaders[i])
|
||||
hs[i].SetValue(xHeaders[i+1])
|
||||
}
|
||||
|
||||
h.SetXHeaders(hs)
|
||||
}
|
||||
|
||||
// panic messages.
|
||||
const (
|
||||
panicMsgMissingContext = "missing context"
|
||||
|
@ -108,11 +122,7 @@ type contextCall struct {
|
|||
statusRes resCommon
|
||||
|
||||
// request to be signed with a key and sent
|
||||
req interface {
|
||||
GetMetaHeader() *v2session.RequestMetaHeader
|
||||
SetMetaHeader(*v2session.RequestMetaHeader)
|
||||
SetVerificationHeader(*v2session.RequestVerificationHeader)
|
||||
}
|
||||
req request
|
||||
|
||||
// function to send a request (unary) and receive a response
|
||||
call func() (responseV2, error)
|
||||
|
@ -130,6 +140,12 @@ type contextCall struct {
|
|||
result func(v2 responseV2)
|
||||
}
|
||||
|
||||
type request interface {
|
||||
GetMetaHeader() *v2session.RequestMetaHeader
|
||||
SetMetaHeader(*v2session.RequestMetaHeader)
|
||||
SetVerificationHeader(*v2session.RequestVerificationHeader)
|
||||
}
|
||||
|
||||
// sets needed fields of the request meta header.
|
||||
func (x contextCall) prepareRequest() {
|
||||
meta := x.req.GetMetaHeader()
|
||||
|
@ -153,6 +169,25 @@ func (x contextCall) prepareRequest() {
|
|||
x.meta.writeToMetaHeader(meta)
|
||||
}
|
||||
|
||||
func (c *Client) prepareRequest(req request, meta *v2session.RequestMetaHeader) {
|
||||
ttl := meta.GetTTL()
|
||||
if ttl == 0 {
|
||||
ttl = 2
|
||||
}
|
||||
|
||||
verV2 := meta.GetVersion()
|
||||
if verV2 == nil {
|
||||
verV2 = new(refs.Version)
|
||||
version.Current().WriteToV2(verV2)
|
||||
}
|
||||
|
||||
meta.SetTTL(ttl)
|
||||
meta.SetVersion(verV2)
|
||||
meta.SetNetworkMagic(c.prm.netMagic)
|
||||
|
||||
req.SetMetaHeader(meta)
|
||||
}
|
||||
|
||||
// prepares, signs and writes the request. Result means success.
|
||||
// If failed, contextCall.err contains the reason.
|
||||
func (x *contextCall) writeRequest() bool {
|
||||
|
@ -222,6 +257,20 @@ func (x *contextCall) processResponse() bool {
|
|||
return successfulStatus
|
||||
}
|
||||
|
||||
// processResponse verifies response signature and converts status to an error if needed.
|
||||
func (c *Client) processResponse(resp responseV2) (apistatus.Status, error) {
|
||||
err := signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid response signature: %w", err)
|
||||
}
|
||||
|
||||
st := apistatus.FromStatusV2(resp.GetMetaHeader().GetStatus())
|
||||
if c.prm.resolveNeoFSErrors {
|
||||
return st, apistatus.ErrFromStatus(st)
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
// reads response (if rResp is set) and processes it. Result means success.
|
||||
// If failed, contextCall.err (or statusRes if resolveAPIFailures is set) contains the reason.
|
||||
func (x *contextCall) readResponse() bool {
|
||||
|
|
|
@ -2,6 +2,7 @@ package client
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
||||
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||
|
@ -9,7 +10,9 @@ import (
|
|||
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/signature"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
|
@ -117,7 +120,7 @@ func (x *PrmObjectHash) WithXHeaders(hs ...string) {
|
|||
panic("slice of X-Headers with odd length")
|
||||
}
|
||||
|
||||
prmCommonMeta{xHeaders: hs}.writeToMetaHeader(&x.meta)
|
||||
writeXHeadersToMeta(hs, &x.meta)
|
||||
}
|
||||
|
||||
// ResObjectHash groups resulting values of ObjectHash operation.
|
||||
|
@ -166,43 +169,40 @@ func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectH
|
|||
panic("missing ranges")
|
||||
}
|
||||
|
||||
// form request body
|
||||
prm.body.SetAddress(&prm.addr)
|
||||
// ranges and salt are already by prm setters
|
||||
|
||||
if prm.tillichZemor {
|
||||
prm.body.SetType(v2refs.TillichZemor)
|
||||
} else {
|
||||
prm.body.SetType(v2refs.SHA256)
|
||||
}
|
||||
|
||||
// form request
|
||||
var req v2object.GetRangeHashRequest
|
||||
c.prepareRequest(&req, &prm.meta)
|
||||
req.SetBody(&prm.body)
|
||||
req.SetMetaHeader(&prm.meta)
|
||||
|
||||
// init call context
|
||||
var (
|
||||
cc contextCall
|
||||
res ResObjectHash
|
||||
)
|
||||
|
||||
c.initCallContext(&cc)
|
||||
cc.req = &req
|
||||
cc.statusRes = &res
|
||||
cc.call = func() (responseV2, error) {
|
||||
return rpcapi.HashObjectRange(&c.c, &req, client.WithContext(ctx))
|
||||
}
|
||||
cc.result = func(r responseV2) {
|
||||
res.checksums = r.(*v2object.GetRangeHashResponse).GetBody().GetHashList()
|
||||
if len(res.checksums) == 0 {
|
||||
cc.err = newErrMissingResponseField("hash list")
|
||||
}
|
||||
err := signature.SignServiceMessage(&c.prm.key, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("sign request: %w", err)
|
||||
}
|
||||
|
||||
// process call
|
||||
if !cc.processCall() {
|
||||
return nil, cc.err
|
||||
resp, err := rpcapi.HashObjectRange(&c.c, &req, client.WithContext(ctx))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("write request: %w", err)
|
||||
}
|
||||
|
||||
var res ResObjectHash
|
||||
res.st, err = c.processResponse(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !apistatus.IsSuccessful(res.st) {
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
res.checksums = resp.GetBody().GetHashList()
|
||||
if len(res.checksums) == 0 {
|
||||
return nil, newErrMissingResponseField("hash list")
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
|
|
Loading…
Reference in a new issue