forked from TrueCloudLab/frostfs-rest-gw
[#25] Synchronize container get and put params
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
parent
bacf909594
commit
665bcfb52d
9 changed files with 270 additions and 164 deletions
|
@ -322,7 +322,7 @@ func mixTokens(ctx context.Context, t *testing.T, cnrID cid.ID) {
|
|||
func checkPutContainerWithError(t *testing.T, httpClient *http.Client, token *handlers.BearerToken) {
|
||||
reqURL, err := url.Parse(testHost + "/v1/containers")
|
||||
require.NoError(t, err)
|
||||
body, err := json.Marshal(&operations.PutContainerBody{ContainerName: "container"})
|
||||
body, err := json.Marshal(&models.ContainerPutInfo{ContainerName: "container"})
|
||||
require.NoError(t, err)
|
||||
request, err := http.NewRequest(http.MethodPut, reqURL.String(), bytes.NewReader(body))
|
||||
require.NoError(t, err)
|
||||
|
@ -692,6 +692,7 @@ func restContainerGet(ctx context.Context, t *testing.T, owner user.ID, cnrID ci
|
|||
|
||||
require.Equal(t, cnrID.EncodeToString(), *cnrInfo.ContainerID)
|
||||
require.Equal(t, owner.EncodeToString(), *cnrInfo.OwnerID)
|
||||
require.Equal(t, containerName, *cnrInfo.ContainerName)
|
||||
}
|
||||
|
||||
func restContainerDelete(ctx context.Context, t *testing.T, clientPool *pool.Pool, owner user.ID) {
|
||||
|
@ -953,7 +954,7 @@ func restContainerPutInvalid(ctx context.Context, t *testing.T) {
|
|||
query.Add(walletConnectQuery, strconv.FormatBool(useWalletConnect))
|
||||
reqURL.RawQuery = query.Encode()
|
||||
|
||||
body, err := json.Marshal(&operations.PutContainerBody{ContainerName: "nameWithCapitalLetters"})
|
||||
body, err := json.Marshal(&models.ContainerPutInfo{ContainerName: "nameWithCapitalLetters"})
|
||||
require.NoError(t, err)
|
||||
request, err := http.NewRequest(http.MethodPut, reqURL.String(), bytes.NewReader(body))
|
||||
require.NoError(t, err)
|
||||
|
@ -982,7 +983,7 @@ func restContainerPut(ctx context.Context, t *testing.T, clientPool *pool.Pool)
|
|||
}
|
||||
|
||||
// try to create container without name but with name-scope-global
|
||||
body, err := json.Marshal(&operations.PutContainerBody{})
|
||||
body, err := json.Marshal(&models.ContainerPutInfo{})
|
||||
require.NoError(t, err)
|
||||
|
||||
reqURL, err := url.Parse(testHost + "/v1/containers")
|
||||
|
@ -999,7 +1000,13 @@ func restContainerPut(ctx context.Context, t *testing.T, clientPool *pool.Pool)
|
|||
doRequest(t, httpClient, request, http.StatusBadRequest, nil)
|
||||
|
||||
// create container with name in local scope
|
||||
body, err = json.Marshal(&operations.PutContainerBody{})
|
||||
containerPutInfo := &models.ContainerPutInfo{
|
||||
Attributes: []*models.Attribute{{
|
||||
Key: util.NewString(attrKey),
|
||||
Value: util.NewString(attrValue),
|
||||
}},
|
||||
}
|
||||
body, err = json.Marshal(containerPutInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
reqURL, err = url.Parse(testHost + "/v1/containers")
|
||||
|
@ -1011,7 +1018,6 @@ func restContainerPut(ctx context.Context, t *testing.T, clientPool *pool.Pool)
|
|||
request, err = http.NewRequest(http.MethodPut, reqURL.String(), bytes.NewReader(body))
|
||||
require.NoError(t, err)
|
||||
prepareCommonHeaders(request.Header, bearerToken)
|
||||
request.Header.Add("X-Attribute-"+attrKey, attrValue)
|
||||
|
||||
addr := &operations.PutContainerOKBody{}
|
||||
doRequest(t, httpClient, request, http.StatusOK, addr)
|
||||
|
|
|
@ -33,6 +33,10 @@ type ContainerInfo struct {
|
|||
// Required: true
|
||||
ContainerID *string `json:"containerId"`
|
||||
|
||||
// container name
|
||||
// Required: true
|
||||
ContainerName *string `json:"containerName"`
|
||||
|
||||
// owner Id
|
||||
// Required: true
|
||||
OwnerID *string `json:"ownerId"`
|
||||
|
@ -62,6 +66,10 @@ func (m *ContainerInfo) Validate(formats strfmt.Registry) error {
|
|||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateContainerName(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateOwnerID(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
@ -125,6 +133,15 @@ func (m *ContainerInfo) validateContainerID(formats strfmt.Registry) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *ContainerInfo) validateContainerName(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("containerName", "body", m.ContainerName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ContainerInfo) validateOwnerID(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("ownerId", "body", m.OwnerID); err != nil {
|
||||
|
|
126
gen/models/container_put_info.go
Normal file
126
gen/models/container_put_info.go
Normal file
|
@ -0,0 +1,126 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// ContainerPutInfo Represent request body to create container. To specify container name use appropriate property (name provided in attributes will be ignored).
|
||||
// Example: {"attributes":[{"key":"Custom-Attribute","value":"value"}],"basicAcl":"public-read-write","containerName":"container","placementPolicy":"REP 3"}
|
||||
//
|
||||
// swagger:model ContainerPutInfo
|
||||
type ContainerPutInfo struct {
|
||||
|
||||
// attributes
|
||||
Attributes []*Attribute `json:"attributes"`
|
||||
|
||||
// basic Acl
|
||||
BasicACL string `json:"basicAcl,omitempty"`
|
||||
|
||||
// container name
|
||||
ContainerName string `json:"containerName,omitempty"`
|
||||
|
||||
// placement policy
|
||||
PlacementPolicy string `json:"placementPolicy,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this container put info
|
||||
func (m *ContainerPutInfo) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateAttributes(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ContainerPutInfo) validateAttributes(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.Attributes) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(m.Attributes); i++ {
|
||||
if swag.IsZero(m.Attributes[i]) { // not required
|
||||
continue
|
||||
}
|
||||
|
||||
if m.Attributes[i] != nil {
|
||||
if err := m.Attributes[i].Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("attributes" + "." + strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("attributes" + "." + strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this container put info based on the context it is used
|
||||
func (m *ContainerPutInfo) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.contextValidateAttributes(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ContainerPutInfo) contextValidateAttributes(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
for i := 0; i < len(m.Attributes); i++ {
|
||||
|
||||
if m.Attributes[i] != nil {
|
||||
if err := m.Attributes[i].ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("attributes" + "." + strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("attributes" + "." + strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *ContainerPutInfo) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *ContainerPutInfo) UnmarshalBinary(b []byte) error {
|
||||
var res ContainerPutInfo
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
|
@ -159,23 +159,7 @@ func init() {
|
|||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"basicAcl": {
|
||||
"type": "string"
|
||||
},
|
||||
"containerName": {
|
||||
"type": "string"
|
||||
},
|
||||
"placementPolicy": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"basicAcl": "public-read-write",
|
||||
"containerName": "container",
|
||||
"placementPolicy": "REP 3"
|
||||
}
|
||||
"$ref": "#/definitions/ContainerPutInfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -574,6 +558,7 @@ func init() {
|
|||
"type": "object",
|
||||
"required": [
|
||||
"containerId",
|
||||
"containerName",
|
||||
"version",
|
||||
"ownerId",
|
||||
"basicAcl",
|
||||
|
@ -593,6 +578,9 @@ func init() {
|
|||
"containerId": {
|
||||
"type": "string"
|
||||
},
|
||||
"containerName": {
|
||||
"type": "string"
|
||||
},
|
||||
"ownerId": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -639,6 +627,38 @@ func init() {
|
|||
}
|
||||
}
|
||||
},
|
||||
"ContainerPutInfo": {
|
||||
"description": "Represent request body to create container. To specify container name use appropriate property (name provided in attributes will be ignored).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attributes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Attribute"
|
||||
}
|
||||
},
|
||||
"basicAcl": {
|
||||
"type": "string"
|
||||
},
|
||||
"containerName": {
|
||||
"type": "string"
|
||||
},
|
||||
"placementPolicy": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"attributes": [
|
||||
{
|
||||
"key": "Custom-Attribute",
|
||||
"value": "value"
|
||||
}
|
||||
],
|
||||
"basicAcl": "public-read-write",
|
||||
"containerName": "container",
|
||||
"placementPolicy": "REP 3"
|
||||
}
|
||||
},
|
||||
"Eacl": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
@ -1252,23 +1272,7 @@ func init() {
|
|||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"basicAcl": {
|
||||
"type": "string"
|
||||
},
|
||||
"containerName": {
|
||||
"type": "string"
|
||||
},
|
||||
"placementPolicy": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"basicAcl": "public-read-write",
|
||||
"containerName": "container",
|
||||
"placementPolicy": "REP 3"
|
||||
}
|
||||
"$ref": "#/definitions/ContainerPutInfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -1750,6 +1754,7 @@ func init() {
|
|||
"type": "object",
|
||||
"required": [
|
||||
"containerId",
|
||||
"containerName",
|
||||
"version",
|
||||
"ownerId",
|
||||
"basicAcl",
|
||||
|
@ -1769,6 +1774,9 @@ func init() {
|
|||
"containerId": {
|
||||
"type": "string"
|
||||
},
|
||||
"containerName": {
|
||||
"type": "string"
|
||||
},
|
||||
"ownerId": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -1815,6 +1823,38 @@ func init() {
|
|||
}
|
||||
}
|
||||
},
|
||||
"ContainerPutInfo": {
|
||||
"description": "Represent request body to create container. To specify container name use appropriate property (name provided in attributes will be ignored).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attributes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Attribute"
|
||||
}
|
||||
},
|
||||
"basicAcl": {
|
||||
"type": "string"
|
||||
},
|
||||
"containerName": {
|
||||
"type": "string"
|
||||
},
|
||||
"placementPolicy": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"attributes": [
|
||||
{
|
||||
"key": "Custom-Attribute",
|
||||
"value": "value"
|
||||
}
|
||||
],
|
||||
"basicAcl": "public-read-write",
|
||||
"containerName": "container",
|
||||
"placementPolicy": "REP 3"
|
||||
}
|
||||
},
|
||||
"Eacl": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
|
|
@ -75,50 +75,6 @@ func (o *PutContainer) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
|||
|
||||
}
|
||||
|
||||
// PutContainerBody put container body
|
||||
// Example: {"basicAcl":"public-read-write","containerName":"container","placementPolicy":"REP 3"}
|
||||
//
|
||||
// swagger:model PutContainerBody
|
||||
type PutContainerBody struct {
|
||||
|
||||
// basic Acl
|
||||
BasicACL string `json:"basicAcl,omitempty"`
|
||||
|
||||
// container name
|
||||
ContainerName string `json:"containerName,omitempty"`
|
||||
|
||||
// placement policy
|
||||
PlacementPolicy string `json:"placementPolicy,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this put container body
|
||||
func (o *PutContainerBody) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validates this put container body based on context it is used
|
||||
func (o *PutContainerBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (o *PutContainerBody) MarshalBinary() ([]byte, error) {
|
||||
if o == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(o)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (o *PutContainerBody) UnmarshalBinary(b []byte) error {
|
||||
var res PutContainerBody
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*o = res
|
||||
return nil
|
||||
}
|
||||
|
||||
// PutContainerOKBody put container o k body
|
||||
// Example: {"containerId":"5HZTn5qkRnmgSz9gSrw22CEdPPk6nQhkwf2Mgzyvkikv"}
|
||||
//
|
||||
|
|
|
@ -16,6 +16,8 @@ import (
|
|||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
|
||||
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
|
||||
)
|
||||
|
||||
// NewPutContainerParams creates a new PutContainerParams object
|
||||
|
@ -59,7 +61,7 @@ type PutContainerParams struct {
|
|||
Required: true
|
||||
In: body
|
||||
*/
|
||||
Container PutContainerBody
|
||||
Container *models.ContainerPutInfo
|
||||
/*Provide this parameter to register container name in NNS service
|
||||
In: query
|
||||
Default: false
|
||||
|
@ -93,7 +95,7 @@ func (o *PutContainerParams) BindRequest(r *http.Request, route *middleware.Matc
|
|||
|
||||
if runtime.HasBody(r) {
|
||||
defer r.Body.Close()
|
||||
var body PutContainerBody
|
||||
var body models.ContainerPutInfo
|
||||
if err := route.Consumer.Consume(r.Body, &body); err != nil {
|
||||
if err == io.EOF {
|
||||
res = append(res, errors.Required("container", "body", ""))
|
||||
|
@ -112,7 +114,7 @@ func (o *PutContainerParams) BindRequest(r *http.Request, route *middleware.Matc
|
|||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
o.Container = body
|
||||
o.Container = &body
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -6,12 +6,12 @@ import (
|
|||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
containerv2 "github.com/nspcc-dev/neofs-api-go/v2/container"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
sessionv2 "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
|
||||
|
@ -50,9 +50,7 @@ func (a *API) PutContainers(params operations.PutContainerParams, principal *mod
|
|||
return operations.NewPutContainerBadRequest().WithPayload(resp)
|
||||
}
|
||||
|
||||
userAttributes := prepareUserAttributes(params.HTTPRequest.Header)
|
||||
|
||||
cnrID, err := createContainer(params.HTTPRequest.Context(), a.pool, stoken, ¶ms, userAttributes)
|
||||
cnrID, err := createContainer(params.HTTPRequest.Context(), a.pool, stoken, ¶ms)
|
||||
if err != nil {
|
||||
resp := a.logAndGetErrorResponse("create container", err)
|
||||
return operations.NewPutContainerBadRequest().WithPayload(resp)
|
||||
|
@ -237,6 +235,7 @@ func getContainerInfo(ctx context.Context, p *pool.Pool, cnrID cid.ID) (*models.
|
|||
|
||||
return &models.ContainerInfo{
|
||||
ContainerID: util.NewString(cnrID.String()),
|
||||
ContainerName: util.NewString(container.Name(*cnr)),
|
||||
OwnerID: util.NewString(cnr.Owner().String()),
|
||||
BasicACL: util.NewString(cnr.BasicACL().EncodeToString()),
|
||||
PlacementPolicy: util.NewString(sb.String()),
|
||||
|
@ -244,13 +243,6 @@ func getContainerInfo(ctx context.Context, p *pool.Pool, cnrID cid.ID) (*models.
|
|||
}, nil
|
||||
}
|
||||
|
||||
func prepareUserAttributes(header http.Header) map[string]string {
|
||||
filtered := filterHeaders(header)
|
||||
delete(filtered, attributeName)
|
||||
delete(filtered, attributeTimestamp)
|
||||
return filtered
|
||||
}
|
||||
|
||||
func parseContainerID(containerID string) (cid.ID, error) {
|
||||
var cnrID cid.ID
|
||||
if err := cnrID.DecodeString(containerID); err != nil {
|
||||
|
@ -300,7 +292,7 @@ func getContainerEACL(ctx context.Context, p *pool.Pool, cnrID cid.ID) (*models.
|
|||
return tableResp, nil
|
||||
}
|
||||
|
||||
func createContainer(ctx context.Context, p *pool.Pool, stoken session.Container, params *operations.PutContainerParams, userAttrs map[string]string) (cid.ID, error) {
|
||||
func createContainer(ctx context.Context, p *pool.Pool, stoken session.Container, params *operations.PutContainerParams) (cid.ID, error) {
|
||||
request := params.Container
|
||||
|
||||
if request.PlacementPolicy == "" {
|
||||
|
@ -333,8 +325,13 @@ func createContainer(ctx context.Context, p *pool.Pool, stoken session.Container
|
|||
container.SetName(&cnr, request.ContainerName)
|
||||
}
|
||||
|
||||
for key, val := range userAttrs {
|
||||
cnr.SetAttribute(key, val)
|
||||
for _, attr := range request.Attributes {
|
||||
switch *attr.Key {
|
||||
case attributeName, attributeTimestamp,
|
||||
containerv2.SysAttributeName, containerv2.SysAttributeZone:
|
||||
default:
|
||||
cnr.SetAttribute(*attr.Key, *attr.Value)
|
||||
}
|
||||
}
|
||||
|
||||
if *params.NameScopeGlobal { // we don't check for nil because there is default false value
|
||||
|
|
|
@ -3,9 +3,7 @@ package handlers
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
objectv2 "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||
|
@ -27,7 +25,6 @@ type epochDurations struct {
|
|||
}
|
||||
|
||||
const (
|
||||
UserAttributeHeaderPrefix = "X-Attribute-"
|
||||
SystemAttributePrefix = "__NEOFS__"
|
||||
|
||||
ExpirationDurationAttr = SystemAttributePrefix + "EXPIRATION_DURATION"
|
||||
|
@ -35,54 +32,6 @@ const (
|
|||
ExpirationRFC3339Attr = SystemAttributePrefix + "EXPIRATION_RFC3339"
|
||||
)
|
||||
|
||||
var neofsAttributeHeaderPrefixes = [...]string{"Neofs-", "NEOFS-", "neofs-"}
|
||||
|
||||
func systemTranslator(key, prefix string) string {
|
||||
// replace specified prefix with `__NEOFS__`
|
||||
key = strings.Replace(key, prefix, SystemAttributePrefix, 1)
|
||||
|
||||
// replace `-` with `_`
|
||||
key = strings.ReplaceAll(key, "-", "_")
|
||||
|
||||
// replace with uppercase
|
||||
return strings.ToUpper(key)
|
||||
}
|
||||
|
||||
func filterHeaders(header http.Header) map[string]string {
|
||||
result := make(map[string]string)
|
||||
prefix := UserAttributeHeaderPrefix
|
||||
|
||||
for key, vals := range header {
|
||||
if len(key) == 0 || len(vals) == 0 || len(vals[0]) == 0 {
|
||||
continue
|
||||
}
|
||||
// checks that key has attribute prefix
|
||||
if !strings.HasPrefix(key, prefix) {
|
||||
continue
|
||||
}
|
||||
|
||||
// removing attribute prefix
|
||||
key = strings.TrimPrefix(key, prefix)
|
||||
|
||||
// checks that it's a system NeoFS header
|
||||
for _, system := range neofsAttributeHeaderPrefixes {
|
||||
if strings.HasPrefix(key, system) {
|
||||
key = systemTranslator(key, system)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// checks that attribute key not empty
|
||||
if len(key) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
result[key] = vals[0]
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GetObjectAttributes forms object attributes from request headers.
|
||||
func GetObjectAttributes(ctx context.Context, pool *pool.Pool, attrs []*models.Attribute, prm PrmAttributes) ([]object.Attribute, error) {
|
||||
headers := make(map[string]string, len(attrs))
|
||||
|
|
|
@ -229,18 +229,7 @@ paths:
|
|||
required: true
|
||||
description: Container info
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
containerName:
|
||||
type: string
|
||||
placementPolicy:
|
||||
type: string
|
||||
basicAcl:
|
||||
type: string
|
||||
example:
|
||||
containerName: container
|
||||
placementPolicy: "REP 3"
|
||||
basicAcl: public-read-write
|
||||
$ref: '#/definitions/ContainerPutInfo'
|
||||
responses:
|
||||
200:
|
||||
description: Address of uploaded objects
|
||||
|
@ -506,11 +495,34 @@ definitions:
|
|||
enum:
|
||||
- object
|
||||
- container
|
||||
ContainerPutInfo:
|
||||
description: Represent request body to create container. To specify container name use appropriate property (name provided in attributes will be ignored).
|
||||
type: object
|
||||
properties:
|
||||
containerName:
|
||||
type: string
|
||||
placementPolicy:
|
||||
type: string
|
||||
basicAcl:
|
||||
type: string
|
||||
attributes:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Attribute'
|
||||
example:
|
||||
containerName: container
|
||||
placementPolicy: "REP 3"
|
||||
basicAcl: public-read-write
|
||||
attributes:
|
||||
- key: Custom-Attribute
|
||||
value: value
|
||||
ContainerInfo:
|
||||
type: object
|
||||
properties:
|
||||
containerId:
|
||||
type: string
|
||||
containerName:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
ownerId:
|
||||
|
@ -525,6 +537,7 @@ definitions:
|
|||
$ref: '#/definitions/Attribute'
|
||||
required:
|
||||
- containerId
|
||||
- containerName
|
||||
- version
|
||||
- ownerId
|
||||
- basicAcl
|
||||
|
|
Loading…
Reference in a new issue