2020-10-02 12:23:52 +00:00
|
|
|
package v2
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2020-12-14 12:07:20 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
2020-10-02 12:23:52 +00:00
|
|
|
objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
|
2022-05-12 16:37:46 +00:00
|
|
|
refsV2 "github.com/nspcc-dev/neofs-api-go/v2/refs"
|
2020-10-02 12:23:52 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
2021-11-10 07:08:33 +00:00
|
|
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
|
|
|
eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl"
|
2022-03-03 14:19:05 +00:00
|
|
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
2022-01-26 12:11:13 +00:00
|
|
|
objectSDKAddress "github.com/nspcc-dev/neofs-sdk-go/object/address"
|
|
|
|
objectSDKID "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
2021-11-10 07:08:33 +00:00
|
|
|
sessionSDK "github.com/nspcc-dev/neofs-sdk-go/session"
|
2020-10-02 12:23:52 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type Option func(*cfg)
|
|
|
|
|
|
|
|
type cfg struct {
|
|
|
|
storage ObjectStorage
|
|
|
|
|
|
|
|
msg xHeaderSource
|
2020-12-15 09:06:04 +00:00
|
|
|
|
2022-02-11 12:25:05 +00:00
|
|
|
addr *objectSDKAddress.Address
|
2020-10-02 12:23:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ObjectStorage interface {
|
2022-01-26 12:11:13 +00:00
|
|
|
Head(*objectSDKAddress.Address) (*object.Object, error)
|
2020-10-02 12:23:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Request interface {
|
|
|
|
GetMetaHeader() *session.RequestMetaHeader
|
|
|
|
}
|
|
|
|
|
|
|
|
type Response interface {
|
|
|
|
GetMetaHeader() *session.ResponseMetaHeader
|
|
|
|
}
|
|
|
|
|
|
|
|
type headerSource struct {
|
|
|
|
*cfg
|
|
|
|
}
|
|
|
|
|
|
|
|
func defaultCfg() *cfg {
|
|
|
|
return &cfg{
|
|
|
|
storage: new(localStorage),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-20 09:45:58 +00:00
|
|
|
func NewMessageHeaderSource(opts ...Option) eaclSDK.TypedHeaderSource {
|
2020-10-02 12:23:52 +00:00
|
|
|
cfg := defaultCfg()
|
|
|
|
|
|
|
|
for i := range opts {
|
|
|
|
opts[i](cfg)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &headerSource{
|
|
|
|
cfg: cfg,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-20 09:45:58 +00:00
|
|
|
func (h *headerSource) HeadersOfType(typ eaclSDK.FilterHeaderType) ([]eaclSDK.Header, bool) {
|
2020-10-02 12:23:52 +00:00
|
|
|
switch typ {
|
|
|
|
default:
|
|
|
|
return nil, true
|
|
|
|
case eaclSDK.HeaderFromRequest:
|
|
|
|
return requestHeaders(h.msg), true
|
|
|
|
case eaclSDK.HeaderFromObject:
|
2020-12-14 13:50:45 +00:00
|
|
|
return h.objectHeaders()
|
2020-10-02 12:23:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-20 09:45:58 +00:00
|
|
|
func requestHeaders(msg xHeaderSource) []eaclSDK.Header {
|
2020-10-02 12:23:52 +00:00
|
|
|
xHdrs := msg.GetXHeaders()
|
|
|
|
|
2022-01-20 09:45:58 +00:00
|
|
|
res := make([]eaclSDK.Header, 0, len(xHdrs))
|
2020-10-02 12:23:52 +00:00
|
|
|
|
|
|
|
for i := range xHdrs {
|
2022-03-15 12:11:35 +00:00
|
|
|
res = append(res, sessionSDK.NewXHeaderFromV2(&xHdrs[i]))
|
2020-10-02 12:23:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
2022-01-20 09:45:58 +00:00
|
|
|
func (h *headerSource) objectHeaders() ([]eaclSDK.Header, bool) {
|
2020-10-02 12:23:52 +00:00
|
|
|
switch m := h.msg.(type) {
|
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("unexpected message type %T", h.msg))
|
|
|
|
case *requestXHeaderSource:
|
|
|
|
switch req := m.req.(type) {
|
|
|
|
case *objectV2.GetRequest:
|
2020-12-15 09:06:04 +00:00
|
|
|
return h.localObjectHeaders(h.addr)
|
2020-10-02 12:23:52 +00:00
|
|
|
case *objectV2.HeadRequest:
|
2020-12-15 09:06:04 +00:00
|
|
|
return h.localObjectHeaders(h.addr)
|
2020-12-18 12:51:29 +00:00
|
|
|
case
|
|
|
|
*objectV2.GetRangeRequest,
|
|
|
|
*objectV2.GetRangeHashRequest,
|
|
|
|
*objectV2.DeleteRequest:
|
2022-02-11 12:25:05 +00:00
|
|
|
return addressHeaders(h.addr), true
|
2020-10-02 12:23:52 +00:00
|
|
|
case *objectV2.PutRequest:
|
|
|
|
if v, ok := req.GetBody().GetObjectPart().(*objectV2.PutObjectPartInit); ok {
|
|
|
|
oV2 := new(objectV2.Object)
|
|
|
|
oV2.SetObjectID(v.GetObjectID())
|
|
|
|
oV2.SetHeader(v.GetHeader())
|
|
|
|
|
2022-02-11 12:25:05 +00:00
|
|
|
if h.addr == nil {
|
2022-05-12 16:37:46 +00:00
|
|
|
idV2 := v.GetObjectID()
|
|
|
|
var id objectSDKID.ID
|
|
|
|
|
|
|
|
if idV2 == nil {
|
|
|
|
// FIXME(@cthulhu-rider): #1386 we need to either return error or check it earlier
|
|
|
|
_ = id.ReadFromV2(*idV2)
|
|
|
|
}
|
|
|
|
|
|
|
|
cnrV2 := v.GetHeader().GetContainerID()
|
|
|
|
var cnr cid.ID
|
|
|
|
|
|
|
|
if cnrV2 != nil {
|
|
|
|
// FIXME(@cthulhu-rider): #1386 we need to either return error or check it earlier
|
|
|
|
_ = cnr.ReadFromV2(*cnrV2)
|
|
|
|
}
|
|
|
|
|
|
|
|
h.addr = new(objectSDKAddress.Address)
|
|
|
|
h.addr.SetContainerID(cnr)
|
|
|
|
h.addr.SetObjectID(id)
|
2020-12-14 13:50:45 +00:00
|
|
|
}
|
|
|
|
|
2022-02-11 12:25:05 +00:00
|
|
|
hs := headersFromObject(object.NewFromV2(oV2), h.addr)
|
2020-12-15 09:06:04 +00:00
|
|
|
|
2020-12-14 13:50:45 +00:00
|
|
|
return hs, true
|
2020-12-14 12:07:20 +00:00
|
|
|
}
|
|
|
|
case *objectV2.SearchRequest:
|
2022-05-12 16:37:46 +00:00
|
|
|
cnrV2 := req.GetBody().GetContainerID()
|
|
|
|
var cnr cid.ID
|
|
|
|
|
|
|
|
if cnrV2 != nil {
|
|
|
|
// FIXME(@cthulhu-rider): #1386 we need to either return error or check it earlier
|
|
|
|
_ = cnr.ReadFromV2(*cnrV2)
|
|
|
|
}
|
|
|
|
|
|
|
|
return []eaclSDK.Header{cidHeader(&cnr)}, true
|
2020-10-02 12:23:52 +00:00
|
|
|
}
|
|
|
|
case *responseXHeaderSource:
|
|
|
|
switch resp := m.resp.(type) {
|
2020-12-14 12:07:20 +00:00
|
|
|
default:
|
2020-12-15 09:06:04 +00:00
|
|
|
hs, _ := h.localObjectHeaders(h.addr)
|
2020-12-14 13:50:45 +00:00
|
|
|
return hs, true
|
2020-10-02 12:23:52 +00:00
|
|
|
case *objectV2.GetResponse:
|
|
|
|
if v, ok := resp.GetBody().GetObjectPart().(*objectV2.GetObjectPartInit); ok {
|
|
|
|
oV2 := new(objectV2.Object)
|
|
|
|
oV2.SetObjectID(v.GetObjectID())
|
|
|
|
oV2.SetHeader(v.GetHeader())
|
|
|
|
|
2022-02-11 12:25:05 +00:00
|
|
|
return headersFromObject(object.NewFromV2(oV2), h.addr), true
|
2020-10-02 12:23:52 +00:00
|
|
|
}
|
|
|
|
case *objectV2.HeadResponse:
|
|
|
|
oV2 := new(objectV2.Object)
|
|
|
|
|
|
|
|
var hdr *objectV2.Header
|
|
|
|
|
|
|
|
switch v := resp.GetBody().GetHeaderPart().(type) {
|
2020-12-07 17:49:47 +00:00
|
|
|
case *objectV2.ShortHeader:
|
2020-10-02 12:23:52 +00:00
|
|
|
hdr = new(objectV2.Header)
|
2020-12-07 17:49:47 +00:00
|
|
|
|
2022-05-12 16:37:46 +00:00
|
|
|
id, _ := h.addr.ContainerID()
|
|
|
|
|
|
|
|
var idV2 refsV2.ContainerID
|
|
|
|
id.WriteToV2(&idV2)
|
|
|
|
|
|
|
|
hdr.SetContainerID(&idV2)
|
2020-12-07 17:49:47 +00:00
|
|
|
hdr.SetVersion(v.GetVersion())
|
|
|
|
hdr.SetCreationEpoch(v.GetCreationEpoch())
|
|
|
|
hdr.SetOwnerID(v.GetOwnerID())
|
|
|
|
hdr.SetObjectType(v.GetObjectType())
|
|
|
|
hdr.SetPayloadLength(v.GetPayloadLength())
|
|
|
|
case *objectV2.HeaderWithSignature:
|
|
|
|
hdr = v.GetHeader()
|
2020-10-02 12:23:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
oV2.SetHeader(hdr)
|
|
|
|
|
2022-02-11 12:25:05 +00:00
|
|
|
return headersFromObject(object.NewFromV2(oV2), h.addr), true
|
2020-10-02 12:23:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-14 13:50:45 +00:00
|
|
|
return nil, true
|
2020-10-02 12:23:52 +00:00
|
|
|
}
|
|
|
|
|
2022-02-11 12:25:05 +00:00
|
|
|
func (h *headerSource) localObjectHeaders(addr *objectSDKAddress.Address) ([]eaclSDK.Header, bool) {
|
2020-12-14 12:07:20 +00:00
|
|
|
obj, err := h.storage.Head(addr)
|
2020-10-02 12:23:52 +00:00
|
|
|
if err == nil {
|
2020-12-15 09:06:04 +00:00
|
|
|
return headersFromObject(obj, addr), true
|
2020-12-14 12:07:20 +00:00
|
|
|
}
|
|
|
|
|
2020-12-14 13:50:45 +00:00
|
|
|
return addressHeaders(addr), false
|
2020-12-14 12:07:20 +00:00
|
|
|
}
|
|
|
|
|
2022-02-11 12:25:05 +00:00
|
|
|
func cidHeader(idCnr *cid.ID) eaclSDK.Header {
|
2020-12-14 12:07:20 +00:00
|
|
|
return &sysObjHdr{
|
|
|
|
k: acl.FilterObjectContainerID,
|
2022-02-11 12:25:05 +00:00
|
|
|
v: cidValue(idCnr),
|
2020-12-14 12:07:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-26 12:11:13 +00:00
|
|
|
func oidHeader(oid *objectSDKID.ID) eaclSDK.Header {
|
2020-12-14 12:07:20 +00:00
|
|
|
return &sysObjHdr{
|
|
|
|
k: acl.FilterObjectID,
|
|
|
|
v: idValue(oid),
|
2020-10-02 12:23:52 +00:00
|
|
|
}
|
2020-12-14 12:07:20 +00:00
|
|
|
}
|
|
|
|
|
2022-01-26 12:11:13 +00:00
|
|
|
func addressHeaders(addr *objectSDKAddress.Address) []eaclSDK.Header {
|
2022-05-12 16:37:46 +00:00
|
|
|
cnr, _ := addr.ContainerID()
|
|
|
|
|
2022-01-20 09:45:58 +00:00
|
|
|
res := make([]eaclSDK.Header, 1, 2)
|
2022-05-12 16:37:46 +00:00
|
|
|
res[0] = cidHeader(&cnr)
|
2020-10-02 12:23:52 +00:00
|
|
|
|
2022-05-12 16:37:46 +00:00
|
|
|
if oid, ok := addr.ObjectID(); ok {
|
|
|
|
res = append(res, oidHeader(&oid))
|
2020-12-14 12:07:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return res
|
2020-10-02 12:23:52 +00:00
|
|
|
}
|