[#337] client: Add option to specify callback of response information
There is a need to analyze some response information in API client. Define `ResponseMetaInfo` structure of response information. Add `WithResponseInfoHandler` client option which allows to set the response info callback. The callback is called right after any response is received. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
3844a3ac74
commit
da89c2b71f
8 changed files with 139 additions and 0 deletions
|
@ -43,6 +43,11 @@ func (c *clientImpl) GetBalance(ctx context.Context, owner *owner.ID, opts ...Ca
|
|||
return nil, fmt.Errorf("transport error: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't verify response message: %w", err)
|
||||
|
|
|
@ -130,6 +130,11 @@ func (c *clientImpl) PutContainer(ctx context.Context, cnr *container.Container,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't verify response message: %w", err)
|
||||
|
@ -166,6 +171,11 @@ func (c *clientImpl) GetContainer(ctx context.Context, id *cid.ID, opts ...CallO
|
|||
return nil, fmt.Errorf("transport error: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't verify response message: %w", err)
|
||||
|
@ -238,6 +248,11 @@ func (c *clientImpl) ListContainers(ctx context.Context, ownerID *owner.ID, opts
|
|||
return nil, fmt.Errorf("transport error: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't verify response message: %w", err)
|
||||
|
@ -292,6 +307,11 @@ func (c *clientImpl) DeleteContainer(ctx context.Context, id *cid.ID, opts ...Ca
|
|||
return fmt.Errorf("transport error: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := v2signature.VerifyServiceMessage(resp); err != nil {
|
||||
return fmt.Errorf("can't verify response message: %w", err)
|
||||
}
|
||||
|
@ -324,6 +344,11 @@ func (c *clientImpl) GetEACL(ctx context.Context, id *cid.ID, opts ...CallOption
|
|||
return nil, fmt.Errorf("transport error: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't verify response message: %w", err)
|
||||
|
@ -388,6 +413,11 @@ func (c *clientImpl) SetEACL(ctx context.Context, eacl *eacl.Table, opts ...Call
|
|||
return fmt.Errorf("transport error: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't verify response message: %w", err)
|
||||
|
@ -433,6 +463,11 @@ func (c *clientImpl) AnnounceContainerUsedSpace(
|
|||
return fmt.Errorf("transport error: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't verify response message: %w", err)
|
||||
|
|
|
@ -67,6 +67,11 @@ func (c *clientImpl) EndpointInfo(ctx context.Context, opts ...CallOption) (*End
|
|||
return nil, fmt.Errorf("transport error: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't verify response message: %w", err)
|
||||
|
@ -105,6 +110,11 @@ func (c *clientImpl) NetworkInfo(ctx context.Context, opts ...CallOption) (*netm
|
|||
return nil, fmt.Errorf("v2 NetworkInfo RPC failure: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("response message verification failed: %w", err)
|
||||
|
|
|
@ -313,6 +313,11 @@ func (c *clientImpl) PutObject(ctx context.Context, p *PutObjectParams, opts ...
|
|||
return nil, fmt.Errorf("closing the stream failed: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOpts, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify response structure
|
||||
if err := signature.VerifyServiceMessage(resp); err != nil {
|
||||
return nil, fmt.Errorf("response verification failed: %w", err)
|
||||
|
@ -417,6 +422,11 @@ func (c *clientImpl) DeleteObject(ctx context.Context, p *DeleteObjectParams, op
|
|||
return fmt.Errorf("sending the request failed: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOpts, resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// verify response structure
|
||||
if err := signature.VerifyServiceMessage(resp); err != nil {
|
||||
return fmt.Errorf("response verification failed: %w", err)
|
||||
|
@ -623,6 +633,11 @@ loop:
|
|||
return nil, fmt.Errorf("reading the response failed: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOpts, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify response structure
|
||||
if err := signature.VerifyServiceMessage(resp); err != nil {
|
||||
return nil, fmt.Errorf("response verification failed: %w", err)
|
||||
|
@ -781,6 +796,11 @@ func (c *clientImpl) GetObjectHeader(ctx context.Context, p *ObjectHeaderParams,
|
|||
return nil, fmt.Errorf("sending the request failed: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOpts, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify response structure
|
||||
if err := signature.VerifyServiceMessage(resp); err != nil {
|
||||
return nil, fmt.Errorf("response verification failed: %w", err)
|
||||
|
@ -979,6 +999,11 @@ func (c *clientImpl) ObjectPayloadRangeData(ctx context.Context, p *RangeDataPar
|
|||
return nil, fmt.Errorf("reading the response failed: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOpts, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify response structure
|
||||
if err := signature.VerifyServiceMessage(resp); err != nil {
|
||||
return nil, fmt.Errorf("could not verify %T: %w", resp, err)
|
||||
|
@ -1128,6 +1153,11 @@ func (c *clientImpl) objectPayloadRangeHash(ctx context.Context, p *RangeChecksu
|
|||
return nil, fmt.Errorf("sending the request failed: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOpts, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify response structure
|
||||
if err := signature.VerifyServiceMessage(resp); err != nil {
|
||||
return nil, fmt.Errorf("response verification failed: %w", err)
|
||||
|
@ -1276,6 +1306,11 @@ func (c *clientImpl) SearchObject(ctx context.Context, p *SearchObjectParams, op
|
|||
return nil, fmt.Errorf("reading the response failed: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOpts, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify response structure
|
||||
if err := signature.VerifyServiceMessage(resp); err != nil {
|
||||
return nil, fmt.Errorf("could not verify %T: %w", resp, err)
|
||||
|
|
|
@ -33,6 +33,8 @@ type (
|
|||
key *ecdsa.PrivateKey
|
||||
|
||||
rawOpts []client.Option
|
||||
|
||||
cbRespInfo func(ResponseMetaInfo) error
|
||||
}
|
||||
|
||||
v2SessionReqInfo struct {
|
||||
|
|
|
@ -77,6 +77,11 @@ func (c *clientImpl) AnnounceLocalTrust(ctx context.Context, prm AnnounceLocalTr
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't verify response message: %w", err)
|
||||
|
@ -152,6 +157,11 @@ func (c *clientImpl) AnnounceIntermediateTrust(ctx context.Context, prm Announce
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't verify response message: %w", err)
|
||||
|
|
37
pkg/client/response.go
Normal file
37
pkg/client/response.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||
)
|
||||
|
||||
// ResponseMetaInfo groups meta information about any NeoFS API response.
|
||||
type ResponseMetaInfo struct {
|
||||
key []byte
|
||||
}
|
||||
|
||||
// ResponderKey returns responder's public key in a binary format.
|
||||
//
|
||||
// Result must not be mutated.
|
||||
func (x ResponseMetaInfo) ResponderKey() []byte {
|
||||
return x.key
|
||||
}
|
||||
|
||||
// WithResponseInfoHandler allows to specify handler of response meta information for the all Client operations.
|
||||
// The handler is called right after the response is received. Client returns handler's error immediately.
|
||||
func WithResponseInfoHandler(f func(ResponseMetaInfo) error) Option {
|
||||
return func(opts *clientOptions) {
|
||||
opts.cbRespInfo = f
|
||||
}
|
||||
}
|
||||
|
||||
func (c *clientImpl) handleResponseInfoV2(opts *callOptions, resp interface {
|
||||
GetVerificationHeader() *session.ResponseVerificationHeader
|
||||
}) error {
|
||||
if c.opts.cbRespInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.opts.cbRespInfo(ResponseMetaInfo{
|
||||
key: resp.GetVerificationHeader().GetBodySignature().GetKey(),
|
||||
})
|
||||
}
|
|
@ -55,6 +55,11 @@ func (c *clientImpl) CreateSession(ctx context.Context, expiration uint64, opts
|
|||
return nil, fmt.Errorf("transport error: %w", err)
|
||||
}
|
||||
|
||||
// handle response meta info
|
||||
if err := c.handleResponseInfoV2(callOptions, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = v2signature.VerifyServiceMessage(resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't verify response message: %w", err)
|
||||
|
|
Loading…
Reference in a new issue