git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/client/common.go (about)

     1  package client
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
     8  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
     9  	v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
    10  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
    11  	apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
    12  	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
    13  )
    14  
    15  // structure is embedded to all resulting types in order to inherit status-related methods.
    16  type statusRes struct {
    17  	st apistatus.Status
    18  }
    19  
    20  // Status returns server's status return.
    21  //
    22  // Use apistatus package functionality to handle the status.
    23  func (x statusRes) Status() apistatus.Status {
    24  	return x.st
    25  }
    26  
    27  func writeXHeadersToMeta(xHeaders []string, h *v2session.RequestMetaHeader) {
    28  	if len(xHeaders) == 0 {
    29  		return
    30  	}
    31  
    32  	// TODO (aarifullin): remove the panic when all client parameters will check XHeaders
    33  	// within buildRequest invocation.
    34  	if len(xHeaders)%2 != 0 {
    35  		panic("slice of X-Headers with odd length")
    36  	}
    37  
    38  	hs := make([]v2session.XHeader, len(xHeaders)/2)
    39  	for i := 0; i < len(xHeaders); i += 2 {
    40  		hs[i].SetKey(xHeaders[i])
    41  		hs[i].SetValue(xHeaders[i+1])
    42  	}
    43  
    44  	h.SetXHeaders(hs)
    45  }
    46  
    47  // error messages.
    48  var (
    49  	errorMissingContainer = errors.New("missing container")
    50  	errorMissingObject    = errors.New("missing object")
    51  	errorAccountNotSet    = errors.New("account not set")
    52  	errorServerAddrUnset  = errors.New("server address is unset or empty")
    53  	errorZeroRangeLength  = errors.New("zero range length")
    54  	errorMissingRanges    = errors.New("missing ranges")
    55  	errorInvalidXHeaders  = errors.New("xheaders must be presented only as key-value pairs")
    56  )
    57  
    58  type request interface {
    59  	GetMetaHeader() *v2session.RequestMetaHeader
    60  	SetMetaHeader(*v2session.RequestMetaHeader)
    61  	SetVerificationHeader(*v2session.RequestVerificationHeader)
    62  }
    63  
    64  func (c *Client) prepareRequest(req request, meta *v2session.RequestMetaHeader) {
    65  	ttl := meta.GetTTL()
    66  	if ttl == 0 {
    67  		ttl = 2
    68  	}
    69  
    70  	verV2 := meta.GetVersion()
    71  	if verV2 == nil {
    72  		verV2 = new(refs.Version)
    73  		version.Current().WriteToV2(verV2)
    74  	}
    75  
    76  	meta.SetTTL(ttl)
    77  	meta.SetVersion(verV2)
    78  	meta.SetNetworkMagic(c.prm.NetMagic)
    79  
    80  	req.SetMetaHeader(meta)
    81  }
    82  
    83  // processResponse verifies response signature and converts status to an error if needed.
    84  func (c *Client) processResponse(resp responseV2) (apistatus.Status, error) {
    85  	if c.prm.ResponseInfoCallback != nil {
    86  		rmi := ResponseMetaInfo{
    87  			key:   resp.GetVerificationHeader().GetBodySignature().GetKey(),
    88  			epoch: resp.GetMetaHeader().GetEpoch(),
    89  		}
    90  		if err := c.prm.ResponseInfoCallback(rmi); err != nil {
    91  			return nil, fmt.Errorf("response callback error: %w", err)
    92  		}
    93  	}
    94  
    95  	err := signature.VerifyServiceMessage(resp)
    96  	if err != nil {
    97  		return nil, fmt.Errorf("invalid response signature: %w", err)
    98  	}
    99  
   100  	st := apistatus.FromStatusV2(resp.GetMetaHeader().GetStatus())
   101  	if !c.prm.DisableFrostFSErrorResolution {
   102  		return st, apistatus.ErrFromStatus(st)
   103  	}
   104  	return st, nil
   105  }
   106  
   107  // ExecRaw executes f with underlying git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client.Client
   108  // instance. Communicate over the Protocol Buffers protocol in a more flexible way:
   109  // most often used to transmit data over a fixed version of the FrostFS protocol, as well
   110  // as to support custom services.
   111  //
   112  // The f must not manipulate the client connection passed into it.
   113  //
   114  // Like all other operations, must be called after connecting to the server and
   115  // before closing the connection.
   116  //
   117  // See also Dial and Close.
   118  // See also git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client package docs.
   119  func (c *Client) ExecRaw(f func(client *client.Client) error) error {
   120  	return f(&c.c)
   121  }