Fix access denied error handling for GET requests #1340
3 changed files with 29 additions and 12 deletions
|
@ -2,9 +2,11 @@ package getsvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util"
|
||||||
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -120,6 +122,12 @@ func (exec *request) analyzeStatus(ctx context.Context, execCnr bool) {
|
||||||
exec.log.Debug(logs.OperationFinishedWithError,
|
exec.log.Debug(logs.OperationFinishedWithError,
|
||||||
zap.Error(exec.err),
|
zap.Error(exec.err),
|
||||||
)
|
)
|
||||||
|
var errAccessDenied *apistatus.ObjectAccessDenied
|
||||||
|
if execCnr && errors.As(exec.err, &errAccessDenied) {
|
||||||
|
// Local get can't return access denied error, so this error was returned by
|
||||||
|
// write to the output stream. So there is no need to try to find object on other nodes.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if execCnr {
|
if execCnr {
|
||||||
exec.executeOnContainer(ctx)
|
exec.executeOnContainer(ctx)
|
||||||
|
|
|
@ -31,6 +31,7 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool {
|
||||||
var errECInfo *objectSDK.ECInfoError
|
var errECInfo *objectSDK.ECInfoError
|
||||||
var errRemoved *apistatus.ObjectAlreadyRemoved
|
var errRemoved *apistatus.ObjectAlreadyRemoved
|
||||||
var errOutOfRange *apistatus.ObjectOutOfRange
|
var errOutOfRange *apistatus.ObjectOutOfRange
|
||||||
|
var errAccessDenied *apistatus.ObjectAccessDenied
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
default:
|
default:
|
||||||
|
@ -38,8 +39,12 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool {
|
||||||
if r.status != statusEC {
|
if r.status != statusEC {
|
||||||
// for raw requests, continue to collect other parts
|
// for raw requests, continue to collect other parts
|
||||||
r.status = statusUndefined
|
r.status = statusUndefined
|
||||||
|
if errors.As(err, &errAccessDenied) {
|
||||||
|
r.err = err
|
||||||
|
} else {
|
||||||
r.err = new(apistatus.ObjectNotFound)
|
r.err = new(apistatus.ObjectNotFound)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
case err == nil:
|
case err == nil:
|
||||||
r.status = statusOK
|
r.status = statusOK
|
||||||
|
|
|
@ -24,11 +24,13 @@ import (
|
||||||
|
|
||||||
type getRequestForwarder struct {
|
type getRequestForwarder struct {
|
||||||
OnceResign sync.Once
|
OnceResign sync.Once
|
||||||
OnceHeaderSending sync.Once
|
|
||||||
GlobalProgress int
|
GlobalProgress int
|
||||||
Key *ecdsa.PrivateKey
|
Key *ecdsa.PrivateKey
|
||||||
Request *objectV2.GetRequest
|
Request *objectV2.GetRequest
|
||||||
Stream *streamObjectWriter
|
Stream *streamObjectWriter
|
||||||
|
|
||||||
|
headerSent bool
|
||||||
|
headerSentGuard sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *getRequestForwarder) forwardRequestToNode(ctx context.Context, addr network.Address, c client.MultiAddressClient, pubkey []byte) (*objectSDK.Object, error) {
|
func (f *getRequestForwarder) forwardRequestToNode(ctx context.Context, addr network.Address, c client.MultiAddressClient, pubkey []byte) (*objectSDK.Object, error) {
|
||||||
|
@ -83,13 +85,15 @@ func (f *getRequestForwarder) writeHeader(ctx context.Context, v *objectV2.GetOb
|
||||||
obj.SetSignature(v.GetSignature())
|
obj.SetSignature(v.GetSignature())
|
||||||
obj.SetHeader(v.GetHeader())
|
obj.SetHeader(v.GetHeader())
|
||||||
|
|
||||||
var err error
|
f.headerSentGuard.Lock()
|
||||||
fyrchik marked this conversation as resolved
|
|||||||
f.OnceHeaderSending.Do(func() {
|
defer f.headerSentGuard.Unlock()
|
||||||
err = f.Stream.WriteHeader(ctx, objectSDK.NewFromV2(obj))
|
if f.headerSent {
|
||||||
})
|
return nil
|
||||||
if err != nil {
|
}
|
||||||
|
if err := f.Stream.WriteHeader(ctx, objectSDK.NewFromV2(obj)); err != nil {
|
||||||
return errCouldNotWriteObjHeader(err)
|
return errCouldNotWriteObjHeader(err)
|
||||||
}
|
}
|
||||||
|
f.headerSent = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue
Missed this in support branch, could you explain, how is this different from
sync.Once
?sync.Once
doesn't takeerr
into account: in case of errorsync.Once
will not run second time.