[#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.
|
// panic messages.
|
||||||
const (
|
const (
|
||||||
panicMsgMissingContext = "missing context"
|
panicMsgMissingContext = "missing context"
|
||||||
|
@ -108,11 +122,7 @@ type contextCall struct {
|
||||||
statusRes resCommon
|
statusRes resCommon
|
||||||
|
|
||||||
// request to be signed with a key and sent
|
// request to be signed with a key and sent
|
||||||
req interface {
|
req request
|
||||||
GetMetaHeader() *v2session.RequestMetaHeader
|
|
||||||
SetMetaHeader(*v2session.RequestMetaHeader)
|
|
||||||
SetVerificationHeader(*v2session.RequestVerificationHeader)
|
|
||||||
}
|
|
||||||
|
|
||||||
// function to send a request (unary) and receive a response
|
// function to send a request (unary) and receive a response
|
||||||
call func() (responseV2, error)
|
call func() (responseV2, error)
|
||||||
|
@ -130,6 +140,12 @@ type contextCall struct {
|
||||||
result func(v2 responseV2)
|
result func(v2 responseV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type request interface {
|
||||||
|
GetMetaHeader() *v2session.RequestMetaHeader
|
||||||
|
SetMetaHeader(*v2session.RequestMetaHeader)
|
||||||
|
SetVerificationHeader(*v2session.RequestVerificationHeader)
|
||||||
|
}
|
||||||
|
|
||||||
// sets needed fields of the request meta header.
|
// sets needed fields of the request meta header.
|
||||||
func (x contextCall) prepareRequest() {
|
func (x contextCall) prepareRequest() {
|
||||||
meta := x.req.GetMetaHeader()
|
meta := x.req.GetMetaHeader()
|
||||||
|
@ -153,6 +169,25 @@ func (x contextCall) prepareRequest() {
|
||||||
x.meta.writeToMetaHeader(meta)
|
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.
|
// prepares, signs and writes the request. Result means success.
|
||||||
// If failed, contextCall.err contains the reason.
|
// If failed, contextCall.err contains the reason.
|
||||||
func (x *contextCall) writeRequest() bool {
|
func (x *contextCall) writeRequest() bool {
|
||||||
|
@ -222,6 +257,20 @@ func (x *contextCall) processResponse() bool {
|
||||||
return successfulStatus
|
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.
|
// 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.
|
// If failed, contextCall.err (or statusRes if resolveAPIFailures is set) contains the reason.
|
||||||
func (x *contextCall) readResponse() bool {
|
func (x *contextCall) readResponse() bool {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
||||||
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
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"
|
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
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"
|
"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"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
"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")
|
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.
|
// ResObjectHash groups resulting values of ObjectHash operation.
|
||||||
|
@ -166,43 +169,40 @@ func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectH
|
||||||
panic("missing ranges")
|
panic("missing ranges")
|
||||||
}
|
}
|
||||||
|
|
||||||
// form request body
|
|
||||||
prm.body.SetAddress(&prm.addr)
|
prm.body.SetAddress(&prm.addr)
|
||||||
// ranges and salt are already by prm setters
|
|
||||||
|
|
||||||
if prm.tillichZemor {
|
if prm.tillichZemor {
|
||||||
prm.body.SetType(v2refs.TillichZemor)
|
prm.body.SetType(v2refs.TillichZemor)
|
||||||
} else {
|
} else {
|
||||||
prm.body.SetType(v2refs.SHA256)
|
prm.body.SetType(v2refs.SHA256)
|
||||||
}
|
}
|
||||||
|
|
||||||
// form request
|
|
||||||
var req v2object.GetRangeHashRequest
|
var req v2object.GetRangeHashRequest
|
||||||
|
c.prepareRequest(&req, &prm.meta)
|
||||||
req.SetBody(&prm.body)
|
req.SetBody(&prm.body)
|
||||||
req.SetMetaHeader(&prm.meta)
|
|
||||||
|
|
||||||
// init call context
|
err := signature.SignServiceMessage(&c.prm.key, req)
|
||||||
var (
|
if err != nil {
|
||||||
cc contextCall
|
return nil, fmt.Errorf("sign request: %w", err)
|
||||||
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()
|
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 {
|
if len(res.checksums) == 0 {
|
||||||
cc.err = newErrMissingResponseField("hash list")
|
return nil, newErrMissingResponseField("hash list")
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// process call
|
|
||||||
if !cc.processCall() {
|
|
||||||
return nil, cc.err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &res, nil
|
return &res, nil
|
||||||
|
|
Loading…
Reference in a new issue