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 }