@@ -5,8 +5,11 @@ import (
55 "errors"
66 "fmt"
77
8+ "github.com/nspcc-dev/neofs-node/pkg/network"
9+ "github.com/nspcc-dev/neofs-node/pkg/services/object/internal"
810 "github.com/nspcc-dev/neofs-node/pkg/util"
911 apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
12+ "github.com/nspcc-dev/neofs-sdk-go/netmap"
1013 "github.com/nspcc-dev/neofs-sdk-go/object"
1114 "go.uber.org/zap"
1215)
@@ -40,8 +43,45 @@ func (s *Service) Get(ctx context.Context, prm Prm) error {
4043 }
4144 }
4245
46+ ecNodeLists := nodeLists [len (repRules ):]
47+ if prm .forwarder != nil && ! localNodeInSets (s .neoFSNet , ecNodeLists ) {
48+ return s .proxyGetRequest (ctx , ecNodeLists , prm .forwarder , "GET" , nil )
49+ }
50+
4351 return s .copyECObject (ctx , prm .addr .Container (), prm .addr .Object (), prm .common .SessionToken (),
44- ecRules , nodeLists [len (repRules ):], prm .objWriter )
52+ ecRules , ecNodeLists , prm .objWriter )
53+ }
54+
55+ func (s * Service ) proxyGetRequest (ctx context.Context , sortedNodeLists [][]netmap.NodeInfo , proxyFn RequestForwarder ,
56+ req string , headWriter internal.HeaderWriter ) error {
57+ for i := range sortedNodeLists {
58+ for j := range sortedNodeLists [i ] {
59+ conn , node , err := s .conns .(* clientCacheWrapper )._connect (sortedNodeLists [i ][j ])
60+ if err != nil {
61+ // TODO: implement address list stringer for lazy encoding
62+ s .log .Debug ("get conn to remote node" ,
63+ zap .String ("addresses" , network .StringifyGroup (node .AddressGroup ())), zap .Error (err ))
64+ continue
65+ }
66+
67+ hdr , err := proxyFn (ctx , node , conn )
68+ if err == nil {
69+ if headWriter != nil {
70+ return headWriter .WriteHeader (hdr )
71+ }
72+ return nil
73+ }
74+
75+ if errors .Is (err , apistatus .ErrObjectAlreadyRemoved ) || errors .Is (err , apistatus .ErrObjectAccessDenied ) ||
76+ errors .Is (err , apistatus .ErrObjectOutOfRange ) || errors .Is (err , ctx .Err ()) {
77+ return err
78+ }
79+
80+ s .log .Info ("request proxy failed" , zap .String ("request" , req ), zap .Error (err ))
81+ }
82+ }
83+
84+ return apistatus .ErrObjectNotFound
4585}
4686
4787// GetRange serves a request to get an object by address, and returns Streamer instance.
@@ -73,8 +113,13 @@ func (s *Service) GetRange(ctx context.Context, prm RangePrm) error {
73113 }
74114 }
75115
116+ ecNodeLists := nodeLists [len (repRules ):]
117+ if prm .forwarder != nil && ! localNodeInSets (s .neoFSNet , ecNodeLists ) {
118+ return s .proxyGetRequest (ctx , ecNodeLists , prm .forwarder , "RANGE" , nil )
119+ }
120+
76121 return s .copyECObjectRange (ctx , prm .objWriter , prm .addr .Container (), prm .addr .Object (), prm .common .SessionToken (),
77- ecRules , nodeLists [ len ( repRules ):] , prm .rng .GetOffset (), prm .rng .GetLength ())
122+ ecRules , ecNodeLists , prm .rng .GetOffset (), prm .rng .GetLength ())
78123}
79124
80125func (s * Service ) getRange (ctx context.Context , prm RangePrm , opts ... execOption ) error {
@@ -141,8 +186,13 @@ func (s *Service) Head(ctx context.Context, prm HeadPrm) error {
141186 }
142187 }
143188
189+ ecNodeLists := nodeLists [len (repRules ):]
190+ if prm .forwarder != nil && ! localNodeInSets (s .neoFSNet , ecNodeLists ) {
191+ return s .proxyGetRequest (ctx , ecNodeLists , prm .forwarder , "HEAD" , prm .objWriter )
192+ }
193+
144194 return s .copyECObjectHeader (ctx , prm .objWriter , prm .addr .Container (), prm .addr .Object (), prm .common .SessionToken (),
145- ecRules , nodeLists [ len ( repRules ):] )
195+ ecRules , ecNodeLists )
146196}
147197
148198func (s * Service ) get (ctx context.Context , prm commonPrm , opts ... execOption ) statusError {
0 commit comments