From 14b20e6634002e50f8774fa4096822fbf959cbb4 Mon Sep 17 00:00:00 2001 From: Tatiana Nesterenko Date: Thu, 9 Nov 2023 22:18:04 +0000 Subject: [PATCH] api: add HTTP-like object getter Add `GET /get/{cid}/{oid}` and `HEAD /get/{cid}/{oid}` APIs. Signed-off-by: Tatiana Nesterenko --- gen/restapi/doc.go | 1 + gen/restapi/embedded_spec.go | 346 +++++++++++++++++ .../operations/get_container_object.go | 71 ++++ .../get_container_object_parameters.go | 131 +++++++ .../get_container_object_responses.go | 366 +++++++++++++++++ .../operations/head_container_object.go | 71 ++++ .../head_container_object_parameters.go | 131 +++++++ .../head_container_object_responses.go | 367 ++++++++++++++++++ .../operations/head_head_container_object.go | 56 +++ .../head_head_container_object_parameters.go | 95 +++++ .../head_head_container_object_responses.go | 126 ++++++ gen/restapi/operations/neofs_rest_gw_api.go | 50 +++ go.mod | 24 +- go.sum | 117 ++---- handlers/api.go | 14 + handlers/objects.go | 324 +++++++++++++++- spec/rest.yaml | 108 ++++++ 17 files changed, 2293 insertions(+), 105 deletions(-) create mode 100644 gen/restapi/operations/get_container_object.go create mode 100644 gen/restapi/operations/get_container_object_parameters.go create mode 100644 gen/restapi/operations/get_container_object_responses.go create mode 100644 gen/restapi/operations/head_container_object.go create mode 100644 gen/restapi/operations/head_container_object_parameters.go create mode 100644 gen/restapi/operations/head_container_object_responses.go create mode 100644 gen/restapi/operations/head_head_container_object.go create mode 100644 gen/restapi/operations/head_head_container_object_parameters.go create mode 100644 gen/restapi/operations/head_head_container_object_responses.go diff --git a/gen/restapi/doc.go b/gen/restapi/doc.go index bc68476..67ffad3 100644 --- a/gen/restapi/doc.go +++ b/gen/restapi/doc.go @@ -13,6 +13,7 @@ // - application/json // // Produces: +// - application/octet-stream // - application/json // // swagger:meta diff --git a/gen/restapi/embedded_spec.go b/gen/restapi/embedded_spec.go index d99e6f3..56e5b22 100644 --- a/gen/restapi/embedded_spec.go +++ b/gen/restapi/embedded_spec.go @@ -523,6 +523,166 @@ func init() { } ] }, + "/get/{containerId}/{objectId}": { + "get": { + "security": [ + {}, + { + "BearerAuth": [] + }, + { + "CookieAuth": [] + } + ], + "produces": [ + "application/octet-stream" + ], + "summary": "Get object by container ID and object ID. Also returns custom users' header attributes ` + "`" + `X-Attribute-*` + "`" + `", + "operationId": "getContainerObject", + "parameters": [ + { + "type": "boolean", + "description": "Set the Content-Disposition header as attachment in response. This make the browser to download object as file instead of showing it on the page.", + "name": "download", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Object.", + "schema": { + "type": "string", + "format": "binary" + }, + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Content-Disposition": { + "type": "string" + }, + "Content-Length": { + "type": "string" + }, + "Content-Type": { + "type": "string" + }, + "Last-Modified": { + "type": "string" + }, + "X-Attribute-FileName": { + "type": "string" + }, + "X-Attribute-Timestamp": { + "type": "integer" + }, + "X-Container-Id": { + "type": "string" + }, + "X-Object-Id": { + "type": "string" + }, + "X-Owner-Id": { + "type": "string" + } + } + }, + "400": { + "description": "Bad request.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "head": { + "security": [ + {}, + { + "BearerAuth": [] + }, + { + "CookieAuth": [] + } + ], + "summary": "Get object info (head) by container ID and object ID. Also returns custom users' header attributes ` + "`" + `X-Attribute-*` + "`" + `", + "operationId": "headContainerObject", + "parameters": [ + { + "type": "boolean", + "description": "Set the Content-Disposition header as attachment in response. This make the browser to download object as file instead of showing it on the page.", + "name": "download", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Object info.", + "schema": { + "$ref": "#/definitions/ObjectInfo" + }, + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Content-Disposition": { + "type": "string" + }, + "Content-Length": { + "type": "string" + }, + "Content-Type": { + "type": "string" + }, + "Last-Modified": { + "type": "string" + }, + "X-Attribute-FileName": { + "type": "string" + }, + "X-Attribute-Timestamp": { + "type": "integer" + }, + "X-Container-Id": { + "type": "string" + }, + "X-Object-Id": { + "type": "string" + }, + "X-Owner-Id": { + "type": "string" + } + } + }, + "400": { + "description": "Bad request.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "parameters": [ + { + "$ref": "#/parameters/containerId" + }, + { + "$ref": "#/parameters/objectId" + } + ] + }, "/objects": { "put": { "consumes": [ @@ -1657,11 +1817,20 @@ func init() { "type": "apiKey", "name": "Authorization", "in": "header" + }, + "CookieAuth": { + "description": "Bearer cookie with base64-encoded token contents.", + "type": "apiKey", + "name": "cookie", + "in": "header" } }, "security": [ { "BearerAuth": [] + }, + { + "CookieAuth": [] } ] }`)) @@ -2220,6 +2389,174 @@ func init() { } ] }, + "/get/{containerId}/{objectId}": { + "get": { + "security": [ + {}, + { + "BearerAuth": [] + }, + { + "CookieAuth": [] + } + ], + "produces": [ + "application/octet-stream" + ], + "summary": "Get object by container ID and object ID. Also returns custom users' header attributes ` + "`" + `X-Attribute-*` + "`" + `", + "operationId": "getContainerObject", + "parameters": [ + { + "type": "boolean", + "description": "Set the Content-Disposition header as attachment in response. This make the browser to download object as file instead of showing it on the page.", + "name": "download", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Object.", + "schema": { + "type": "string", + "format": "binary" + }, + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Content-Disposition": { + "type": "string" + }, + "Content-Length": { + "type": "string" + }, + "Content-Type": { + "type": "string" + }, + "Last-Modified": { + "type": "string" + }, + "X-Attribute-FileName": { + "type": "string" + }, + "X-Attribute-Timestamp": { + "type": "integer" + }, + "X-Container-Id": { + "type": "string" + }, + "X-Object-Id": { + "type": "string" + }, + "X-Owner-Id": { + "type": "string" + } + } + }, + "400": { + "description": "Bad request.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "head": { + "security": [ + {}, + { + "BearerAuth": [] + }, + { + "CookieAuth": [] + } + ], + "summary": "Get object info (head) by container ID and object ID. Also returns custom users' header attributes ` + "`" + `X-Attribute-*` + "`" + `", + "operationId": "headContainerObject", + "parameters": [ + { + "type": "boolean", + "description": "Set the Content-Disposition header as attachment in response. This make the browser to download object as file instead of showing it on the page.", + "name": "download", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Object info.", + "schema": { + "$ref": "#/definitions/ObjectInfo" + }, + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Content-Disposition": { + "type": "string" + }, + "Content-Length": { + "type": "string" + }, + "Content-Type": { + "type": "string" + }, + "Last-Modified": { + "type": "string" + }, + "X-Attribute-FileName": { + "type": "string" + }, + "X-Attribute-Timestamp": { + "type": "integer" + }, + "X-Container-Id": { + "type": "string" + }, + "X-Object-Id": { + "type": "string" + }, + "X-Owner-Id": { + "type": "string" + } + } + }, + "400": { + "description": "Bad request.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not found", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "parameters": [ + { + "type": "string", + "description": "Base58 encoded container id.", + "name": "containerId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Base58 encoded object id.", + "name": "objectId", + "in": "path", + "required": true + } + ] + }, "/objects": { "put": { "consumes": [ @@ -3425,11 +3762,20 @@ func init() { "type": "apiKey", "name": "Authorization", "in": "header" + }, + "CookieAuth": { + "description": "Bearer cookie with base64-encoded token contents.", + "type": "apiKey", + "name": "cookie", + "in": "header" } }, "security": [ { "BearerAuth": [] + }, + { + "CookieAuth": [] } ] }`)) diff --git a/gen/restapi/operations/get_container_object.go b/gen/restapi/operations/get_container_object.go new file mode 100644 index 0000000..4a20b45 --- /dev/null +++ b/gen/restapi/operations/get_container_object.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" + + "github.com/nspcc-dev/neofs-rest-gw/gen/models" +) + +// GetContainerObjectHandlerFunc turns a function with the right signature into a get container object handler +type GetContainerObjectHandlerFunc func(GetContainerObjectParams, *models.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetContainerObjectHandlerFunc) Handle(params GetContainerObjectParams, principal *models.Principal) middleware.Responder { + return fn(params, principal) +} + +// GetContainerObjectHandler interface for that can handle valid get container object params +type GetContainerObjectHandler interface { + Handle(GetContainerObjectParams, *models.Principal) middleware.Responder +} + +// NewGetContainerObject creates a new http.Handler for the get container object operation +func NewGetContainerObject(ctx *middleware.Context, handler GetContainerObjectHandler) *GetContainerObject { + return &GetContainerObject{Context: ctx, Handler: handler} +} + +/* GetContainerObject swagger:route GET /get/{containerId}/{objectId} getContainerObject + +Get object by container ID and object ID. Also returns custom users' header attributes `X-Attribute-*` + +*/ +type GetContainerObject struct { + Context *middleware.Context + Handler GetContainerObjectHandler +} + +func (o *GetContainerObject) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetContainerObjectParams() + uprinc, aCtx, err := o.Context.Authorize(r, route) + if err != nil { + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + if aCtx != nil { + *r = *aCtx + } + var principal *models.Principal + if uprinc != nil { + principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise + } + + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params, principal) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/gen/restapi/operations/get_container_object_parameters.go b/gen/restapi/operations/get_container_object_parameters.go new file mode 100644 index 0000000..ec77db4 --- /dev/null +++ b/gen/restapi/operations/get_container_object_parameters.go @@ -0,0 +1,131 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetContainerObjectParams creates a new GetContainerObjectParams object +// +// There are no default values defined in the spec. +func NewGetContainerObjectParams() GetContainerObjectParams { + + return GetContainerObjectParams{} +} + +// GetContainerObjectParams contains all the bound params for the get container object operation +// typically these are obtained from a http.Request +// +// swagger:parameters getContainerObject +type GetContainerObjectParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /*Base58 encoded container id. + Required: true + In: path + */ + ContainerID string + /*Set the Content-Disposition header as attachment in response. This make the browser to download object as file instead of showing it on the page. + In: query + */ + Download *bool + /*Base58 encoded object id. + Required: true + In: path + */ + ObjectID string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetContainerObjectParams() beforehand. +func (o *GetContainerObjectParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rContainerID, rhkContainerID, _ := route.Params.GetOK("containerId") + if err := o.bindContainerID(rContainerID, rhkContainerID, route.Formats); err != nil { + res = append(res, err) + } + + qDownload, qhkDownload, _ := qs.GetOK("download") + if err := o.bindDownload(qDownload, qhkDownload, route.Formats); err != nil { + res = append(res, err) + } + + rObjectID, rhkObjectID, _ := route.Params.GetOK("objectId") + if err := o.bindObjectID(rObjectID, rhkObjectID, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindContainerID binds and validates parameter ContainerID from path. +func (o *GetContainerObjectParams) bindContainerID(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.ContainerID = raw + + return nil +} + +// bindDownload binds and validates parameter Download from query. +func (o *GetContainerObjectParams) bindDownload(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("download", "query", "bool", raw) + } + o.Download = &value + + return nil +} + +// bindObjectID binds and validates parameter ObjectID from path. +func (o *GetContainerObjectParams) bindObjectID(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.ObjectID = raw + + return nil +} diff --git a/gen/restapi/operations/get_container_object_responses.go b/gen/restapi/operations/get_container_object_responses.go new file mode 100644 index 0000000..dc43b12 --- /dev/null +++ b/gen/restapi/operations/get_container_object_responses.go @@ -0,0 +1,366 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "io" + "net/http" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/swag" + + "github.com/nspcc-dev/neofs-rest-gw/gen/models" +) + +// GetContainerObjectOKCode is the HTTP code returned for type GetContainerObjectOK +const GetContainerObjectOKCode int = 200 + +/*GetContainerObjectOK Object. + +swagger:response getContainerObjectOK +*/ +type GetContainerObjectOK struct { + /* + + */ + AccessControlAllowOrigin string `json:"Access-Control-Allow-Origin"` + /* + + */ + ContentDisposition string `json:"Content-Disposition"` + /* + + */ + ContentLength string `json:"Content-Length"` + /* + + */ + ContentType string `json:"Content-Type"` + /* + + */ + LastModified string `json:"Last-Modified"` + /* + + */ + XAttributeFileName string `json:"X-Attribute-FileName"` + /* + + */ + XAttributeTimestamp int64 `json:"X-Attribute-Timestamp"` + /* + + */ + XContainerID string `json:"X-Container-Id"` + /* + + */ + XObjectID string `json:"X-Object-Id"` + /* + + */ + XOwnerID string `json:"X-Owner-Id"` + + /* + In: Body + */ + Payload io.ReadCloser `json:"body,omitempty"` +} + +// NewGetContainerObjectOK creates GetContainerObjectOK with default headers values +func NewGetContainerObjectOK() *GetContainerObjectOK { + + return &GetContainerObjectOK{} +} + +// WithAccessControlAllowOrigin adds the accessControlAllowOrigin to the get container object o k response +func (o *GetContainerObjectOK) WithAccessControlAllowOrigin(accessControlAllowOrigin string) *GetContainerObjectOK { + o.AccessControlAllowOrigin = accessControlAllowOrigin + return o +} + +// SetAccessControlAllowOrigin sets the accessControlAllowOrigin to the get container object o k response +func (o *GetContainerObjectOK) SetAccessControlAllowOrigin(accessControlAllowOrigin string) { + o.AccessControlAllowOrigin = accessControlAllowOrigin +} + +// WithContentDisposition adds the contentDisposition to the get container object o k response +func (o *GetContainerObjectOK) WithContentDisposition(contentDisposition string) *GetContainerObjectOK { + o.ContentDisposition = contentDisposition + return o +} + +// SetContentDisposition sets the contentDisposition to the get container object o k response +func (o *GetContainerObjectOK) SetContentDisposition(contentDisposition string) { + o.ContentDisposition = contentDisposition +} + +// WithContentLength adds the contentLength to the get container object o k response +func (o *GetContainerObjectOK) WithContentLength(contentLength string) *GetContainerObjectOK { + o.ContentLength = contentLength + return o +} + +// SetContentLength sets the contentLength to the get container object o k response +func (o *GetContainerObjectOK) SetContentLength(contentLength string) { + o.ContentLength = contentLength +} + +// WithContentType adds the contentType to the get container object o k response +func (o *GetContainerObjectOK) WithContentType(contentType string) *GetContainerObjectOK { + o.ContentType = contentType + return o +} + +// SetContentType sets the contentType to the get container object o k response +func (o *GetContainerObjectOK) SetContentType(contentType string) { + o.ContentType = contentType +} + +// WithLastModified adds the lastModified to the get container object o k response +func (o *GetContainerObjectOK) WithLastModified(lastModified string) *GetContainerObjectOK { + o.LastModified = lastModified + return o +} + +// SetLastModified sets the lastModified to the get container object o k response +func (o *GetContainerObjectOK) SetLastModified(lastModified string) { + o.LastModified = lastModified +} + +// WithXAttributeFileName adds the xAttributeFileName to the get container object o k response +func (o *GetContainerObjectOK) WithXAttributeFileName(xAttributeFileName string) *GetContainerObjectOK { + o.XAttributeFileName = xAttributeFileName + return o +} + +// SetXAttributeFileName sets the xAttributeFileName to the get container object o k response +func (o *GetContainerObjectOK) SetXAttributeFileName(xAttributeFileName string) { + o.XAttributeFileName = xAttributeFileName +} + +// WithXAttributeTimestamp adds the xAttributeTimestamp to the get container object o k response +func (o *GetContainerObjectOK) WithXAttributeTimestamp(xAttributeTimestamp int64) *GetContainerObjectOK { + o.XAttributeTimestamp = xAttributeTimestamp + return o +} + +// SetXAttributeTimestamp sets the xAttributeTimestamp to the get container object o k response +func (o *GetContainerObjectOK) SetXAttributeTimestamp(xAttributeTimestamp int64) { + o.XAttributeTimestamp = xAttributeTimestamp +} + +// WithXContainerID adds the xContainerId to the get container object o k response +func (o *GetContainerObjectOK) WithXContainerID(xContainerID string) *GetContainerObjectOK { + o.XContainerID = xContainerID + return o +} + +// SetXContainerID sets the xContainerId to the get container object o k response +func (o *GetContainerObjectOK) SetXContainerID(xContainerID string) { + o.XContainerID = xContainerID +} + +// WithXObjectID adds the xObjectId to the get container object o k response +func (o *GetContainerObjectOK) WithXObjectID(xObjectID string) *GetContainerObjectOK { + o.XObjectID = xObjectID + return o +} + +// SetXObjectID sets the xObjectId to the get container object o k response +func (o *GetContainerObjectOK) SetXObjectID(xObjectID string) { + o.XObjectID = xObjectID +} + +// WithXOwnerID adds the xOwnerId to the get container object o k response +func (o *GetContainerObjectOK) WithXOwnerID(xOwnerID string) *GetContainerObjectOK { + o.XOwnerID = xOwnerID + return o +} + +// SetXOwnerID sets the xOwnerId to the get container object o k response +func (o *GetContainerObjectOK) SetXOwnerID(xOwnerID string) { + o.XOwnerID = xOwnerID +} + +// WithPayload adds the payload to the get container object o k response +func (o *GetContainerObjectOK) WithPayload(payload io.ReadCloser) *GetContainerObjectOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get container object o k response +func (o *GetContainerObjectOK) SetPayload(payload io.ReadCloser) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetContainerObjectOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + // response header Access-Control-Allow-Origin + + accessControlAllowOrigin := o.AccessControlAllowOrigin + if accessControlAllowOrigin != "" { + rw.Header().Set("Access-Control-Allow-Origin", accessControlAllowOrigin) + } + + // response header Content-Disposition + + contentDisposition := o.ContentDisposition + if contentDisposition != "" { + rw.Header().Set("Content-Disposition", contentDisposition) + } + + // response header Content-Length + + contentLength := o.ContentLength + if contentLength != "" { + rw.Header().Set("Content-Length", contentLength) + } + + // response header Content-Type + + contentType := o.ContentType + if contentType != "" { + rw.Header().Set("Content-Type", contentType) + } + + // response header Last-Modified + + lastModified := o.LastModified + if lastModified != "" { + rw.Header().Set("Last-Modified", lastModified) + } + + // response header X-Attribute-FileName + + xAttributeFileName := o.XAttributeFileName + if xAttributeFileName != "" { + rw.Header().Set("X-Attribute-FileName", xAttributeFileName) + } + + // response header X-Attribute-Timestamp + + xAttributeTimestamp := swag.FormatInt64(o.XAttributeTimestamp) + if xAttributeTimestamp != "" { + rw.Header().Set("X-Attribute-Timestamp", xAttributeTimestamp) + } + + // response header X-Container-Id + + xContainerID := o.XContainerID + if xContainerID != "" { + rw.Header().Set("X-Container-Id", xContainerID) + } + + // response header X-Object-Id + + xObjectID := o.XObjectID + if xObjectID != "" { + rw.Header().Set("X-Object-Id", xObjectID) + } + + // response header X-Owner-Id + + xOwnerID := o.XOwnerID + if xOwnerID != "" { + rw.Header().Set("X-Owner-Id", xOwnerID) + } + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetContainerObjectBadRequestCode is the HTTP code returned for type GetContainerObjectBadRequest +const GetContainerObjectBadRequestCode int = 400 + +/*GetContainerObjectBadRequest Bad request. + +swagger:response getContainerObjectBadRequest +*/ +type GetContainerObjectBadRequest struct { + + /* + In: Body + */ + Payload *models.ErrorResponse `json:"body,omitempty"` +} + +// NewGetContainerObjectBadRequest creates GetContainerObjectBadRequest with default headers values +func NewGetContainerObjectBadRequest() *GetContainerObjectBadRequest { + + return &GetContainerObjectBadRequest{} +} + +// WithPayload adds the payload to the get container object bad request response +func (o *GetContainerObjectBadRequest) WithPayload(payload *models.ErrorResponse) *GetContainerObjectBadRequest { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get container object bad request response +func (o *GetContainerObjectBadRequest) SetPayload(payload *models.ErrorResponse) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetContainerObjectBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(400) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// GetContainerObjectNotFoundCode is the HTTP code returned for type GetContainerObjectNotFound +const GetContainerObjectNotFoundCode int = 404 + +/*GetContainerObjectNotFound Not found + +swagger:response getContainerObjectNotFound +*/ +type GetContainerObjectNotFound struct { + + /* + In: Body + */ + Payload *models.ErrorResponse `json:"body,omitempty"` +} + +// NewGetContainerObjectNotFound creates GetContainerObjectNotFound with default headers values +func NewGetContainerObjectNotFound() *GetContainerObjectNotFound { + + return &GetContainerObjectNotFound{} +} + +// WithPayload adds the payload to the get container object not found response +func (o *GetContainerObjectNotFound) WithPayload(payload *models.ErrorResponse) *GetContainerObjectNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get container object not found response +func (o *GetContainerObjectNotFound) SetPayload(payload *models.ErrorResponse) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetContainerObjectNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/gen/restapi/operations/head_container_object.go b/gen/restapi/operations/head_container_object.go new file mode 100644 index 0000000..a94642e --- /dev/null +++ b/gen/restapi/operations/head_container_object.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" + + "github.com/nspcc-dev/neofs-rest-gw/gen/models" +) + +// HeadContainerObjectHandlerFunc turns a function with the right signature into a head container object handler +type HeadContainerObjectHandlerFunc func(HeadContainerObjectParams, *models.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn HeadContainerObjectHandlerFunc) Handle(params HeadContainerObjectParams, principal *models.Principal) middleware.Responder { + return fn(params, principal) +} + +// HeadContainerObjectHandler interface for that can handle valid head container object params +type HeadContainerObjectHandler interface { + Handle(HeadContainerObjectParams, *models.Principal) middleware.Responder +} + +// NewHeadContainerObject creates a new http.Handler for the head container object operation +func NewHeadContainerObject(ctx *middleware.Context, handler HeadContainerObjectHandler) *HeadContainerObject { + return &HeadContainerObject{Context: ctx, Handler: handler} +} + +/* HeadContainerObject swagger:route HEAD /get/{containerId}/{objectId} headContainerObject + +Get object info (head) by container ID and object ID. Also returns custom users' header attributes `X-Attribute-*` + +*/ +type HeadContainerObject struct { + Context *middleware.Context + Handler HeadContainerObjectHandler +} + +func (o *HeadContainerObject) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewHeadContainerObjectParams() + uprinc, aCtx, err := o.Context.Authorize(r, route) + if err != nil { + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + if aCtx != nil { + *r = *aCtx + } + var principal *models.Principal + if uprinc != nil { + principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise + } + + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params, principal) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/gen/restapi/operations/head_container_object_parameters.go b/gen/restapi/operations/head_container_object_parameters.go new file mode 100644 index 0000000..b492a12 --- /dev/null +++ b/gen/restapi/operations/head_container_object_parameters.go @@ -0,0 +1,131 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewHeadContainerObjectParams creates a new HeadContainerObjectParams object +// +// There are no default values defined in the spec. +func NewHeadContainerObjectParams() HeadContainerObjectParams { + + return HeadContainerObjectParams{} +} + +// HeadContainerObjectParams contains all the bound params for the head container object operation +// typically these are obtained from a http.Request +// +// swagger:parameters headContainerObject +type HeadContainerObjectParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /*Base58 encoded container id. + Required: true + In: path + */ + ContainerID string + /*Set the Content-Disposition header as attachment in response. This make the browser to download object as file instead of showing it on the page. + In: query + */ + Download *bool + /*Base58 encoded object id. + Required: true + In: path + */ + ObjectID string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewHeadContainerObjectParams() beforehand. +func (o *HeadContainerObjectParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rContainerID, rhkContainerID, _ := route.Params.GetOK("containerId") + if err := o.bindContainerID(rContainerID, rhkContainerID, route.Formats); err != nil { + res = append(res, err) + } + + qDownload, qhkDownload, _ := qs.GetOK("download") + if err := o.bindDownload(qDownload, qhkDownload, route.Formats); err != nil { + res = append(res, err) + } + + rObjectID, rhkObjectID, _ := route.Params.GetOK("objectId") + if err := o.bindObjectID(rObjectID, rhkObjectID, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindContainerID binds and validates parameter ContainerID from path. +func (o *HeadContainerObjectParams) bindContainerID(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.ContainerID = raw + + return nil +} + +// bindDownload binds and validates parameter Download from query. +func (o *HeadContainerObjectParams) bindDownload(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("download", "query", "bool", raw) + } + o.Download = &value + + return nil +} + +// bindObjectID binds and validates parameter ObjectID from path. +func (o *HeadContainerObjectParams) bindObjectID(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.ObjectID = raw + + return nil +} diff --git a/gen/restapi/operations/head_container_object_responses.go b/gen/restapi/operations/head_container_object_responses.go new file mode 100644 index 0000000..832e030 --- /dev/null +++ b/gen/restapi/operations/head_container_object_responses.go @@ -0,0 +1,367 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/swag" + + "github.com/nspcc-dev/neofs-rest-gw/gen/models" +) + +// HeadContainerObjectOKCode is the HTTP code returned for type HeadContainerObjectOK +const HeadContainerObjectOKCode int = 200 + +/*HeadContainerObjectOK Object info. + +swagger:response headContainerObjectOK +*/ +type HeadContainerObjectOK struct { + /* + + */ + AccessControlAllowOrigin string `json:"Access-Control-Allow-Origin"` + /* + + */ + ContentDisposition string `json:"Content-Disposition"` + /* + + */ + ContentLength string `json:"Content-Length"` + /* + + */ + ContentType string `json:"Content-Type"` + /* + + */ + LastModified string `json:"Last-Modified"` + /* + + */ + XAttributeFileName string `json:"X-Attribute-FileName"` + /* + + */ + XAttributeTimestamp int64 `json:"X-Attribute-Timestamp"` + /* + + */ + XContainerID string `json:"X-Container-Id"` + /* + + */ + XObjectID string `json:"X-Object-Id"` + /* + + */ + XOwnerID string `json:"X-Owner-Id"` + + /* + In: Body + */ + Payload *models.ObjectInfo `json:"body,omitempty"` +} + +// NewHeadContainerObjectOK creates HeadContainerObjectOK with default headers values +func NewHeadContainerObjectOK() *HeadContainerObjectOK { + + return &HeadContainerObjectOK{} +} + +// WithAccessControlAllowOrigin adds the accessControlAllowOrigin to the head container object o k response +func (o *HeadContainerObjectOK) WithAccessControlAllowOrigin(accessControlAllowOrigin string) *HeadContainerObjectOK { + o.AccessControlAllowOrigin = accessControlAllowOrigin + return o +} + +// SetAccessControlAllowOrigin sets the accessControlAllowOrigin to the head container object o k response +func (o *HeadContainerObjectOK) SetAccessControlAllowOrigin(accessControlAllowOrigin string) { + o.AccessControlAllowOrigin = accessControlAllowOrigin +} + +// WithContentDisposition adds the contentDisposition to the head container object o k response +func (o *HeadContainerObjectOK) WithContentDisposition(contentDisposition string) *HeadContainerObjectOK { + o.ContentDisposition = contentDisposition + return o +} + +// SetContentDisposition sets the contentDisposition to the head container object o k response +func (o *HeadContainerObjectOK) SetContentDisposition(contentDisposition string) { + o.ContentDisposition = contentDisposition +} + +// WithContentLength adds the contentLength to the head container object o k response +func (o *HeadContainerObjectOK) WithContentLength(contentLength string) *HeadContainerObjectOK { + o.ContentLength = contentLength + return o +} + +// SetContentLength sets the contentLength to the head container object o k response +func (o *HeadContainerObjectOK) SetContentLength(contentLength string) { + o.ContentLength = contentLength +} + +// WithContentType adds the contentType to the head container object o k response +func (o *HeadContainerObjectOK) WithContentType(contentType string) *HeadContainerObjectOK { + o.ContentType = contentType + return o +} + +// SetContentType sets the contentType to the head container object o k response +func (o *HeadContainerObjectOK) SetContentType(contentType string) { + o.ContentType = contentType +} + +// WithLastModified adds the lastModified to the head container object o k response +func (o *HeadContainerObjectOK) WithLastModified(lastModified string) *HeadContainerObjectOK { + o.LastModified = lastModified + return o +} + +// SetLastModified sets the lastModified to the head container object o k response +func (o *HeadContainerObjectOK) SetLastModified(lastModified string) { + o.LastModified = lastModified +} + +// WithXAttributeFileName adds the xAttributeFileName to the head container object o k response +func (o *HeadContainerObjectOK) WithXAttributeFileName(xAttributeFileName string) *HeadContainerObjectOK { + o.XAttributeFileName = xAttributeFileName + return o +} + +// SetXAttributeFileName sets the xAttributeFileName to the head container object o k response +func (o *HeadContainerObjectOK) SetXAttributeFileName(xAttributeFileName string) { + o.XAttributeFileName = xAttributeFileName +} + +// WithXAttributeTimestamp adds the xAttributeTimestamp to the head container object o k response +func (o *HeadContainerObjectOK) WithXAttributeTimestamp(xAttributeTimestamp int64) *HeadContainerObjectOK { + o.XAttributeTimestamp = xAttributeTimestamp + return o +} + +// SetXAttributeTimestamp sets the xAttributeTimestamp to the head container object o k response +func (o *HeadContainerObjectOK) SetXAttributeTimestamp(xAttributeTimestamp int64) { + o.XAttributeTimestamp = xAttributeTimestamp +} + +// WithXContainerID adds the xContainerId to the head container object o k response +func (o *HeadContainerObjectOK) WithXContainerID(xContainerID string) *HeadContainerObjectOK { + o.XContainerID = xContainerID + return o +} + +// SetXContainerID sets the xContainerId to the head container object o k response +func (o *HeadContainerObjectOK) SetXContainerID(xContainerID string) { + o.XContainerID = xContainerID +} + +// WithXObjectID adds the xObjectId to the head container object o k response +func (o *HeadContainerObjectOK) WithXObjectID(xObjectID string) *HeadContainerObjectOK { + o.XObjectID = xObjectID + return o +} + +// SetXObjectID sets the xObjectId to the head container object o k response +func (o *HeadContainerObjectOK) SetXObjectID(xObjectID string) { + o.XObjectID = xObjectID +} + +// WithXOwnerID adds the xOwnerId to the head container object o k response +func (o *HeadContainerObjectOK) WithXOwnerID(xOwnerID string) *HeadContainerObjectOK { + o.XOwnerID = xOwnerID + return o +} + +// SetXOwnerID sets the xOwnerId to the head container object o k response +func (o *HeadContainerObjectOK) SetXOwnerID(xOwnerID string) { + o.XOwnerID = xOwnerID +} + +// WithPayload adds the payload to the head container object o k response +func (o *HeadContainerObjectOK) WithPayload(payload *models.ObjectInfo) *HeadContainerObjectOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the head container object o k response +func (o *HeadContainerObjectOK) SetPayload(payload *models.ObjectInfo) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *HeadContainerObjectOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + // response header Access-Control-Allow-Origin + + accessControlAllowOrigin := o.AccessControlAllowOrigin + if accessControlAllowOrigin != "" { + rw.Header().Set("Access-Control-Allow-Origin", accessControlAllowOrigin) + } + + // response header Content-Disposition + + contentDisposition := o.ContentDisposition + if contentDisposition != "" { + rw.Header().Set("Content-Disposition", contentDisposition) + } + + // response header Content-Length + + contentLength := o.ContentLength + if contentLength != "" { + rw.Header().Set("Content-Length", contentLength) + } + + // response header Content-Type + + contentType := o.ContentType + if contentType != "" { + rw.Header().Set("Content-Type", contentType) + } + + // response header Last-Modified + + lastModified := o.LastModified + if lastModified != "" { + rw.Header().Set("Last-Modified", lastModified) + } + + // response header X-Attribute-FileName + + xAttributeFileName := o.XAttributeFileName + if xAttributeFileName != "" { + rw.Header().Set("X-Attribute-FileName", xAttributeFileName) + } + + // response header X-Attribute-Timestamp + + xAttributeTimestamp := swag.FormatInt64(o.XAttributeTimestamp) + if xAttributeTimestamp != "" { + rw.Header().Set("X-Attribute-Timestamp", xAttributeTimestamp) + } + + // response header X-Container-Id + + xContainerID := o.XContainerID + if xContainerID != "" { + rw.Header().Set("X-Container-Id", xContainerID) + } + + // response header X-Object-Id + + xObjectID := o.XObjectID + if xObjectID != "" { + rw.Header().Set("X-Object-Id", xObjectID) + } + + // response header X-Owner-Id + + xOwnerID := o.XOwnerID + if xOwnerID != "" { + rw.Header().Set("X-Owner-Id", xOwnerID) + } + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// HeadContainerObjectBadRequestCode is the HTTP code returned for type HeadContainerObjectBadRequest +const HeadContainerObjectBadRequestCode int = 400 + +/*HeadContainerObjectBadRequest Bad request. + +swagger:response headContainerObjectBadRequest +*/ +type HeadContainerObjectBadRequest struct { + + /* + In: Body + */ + Payload *models.ErrorResponse `json:"body,omitempty"` +} + +// NewHeadContainerObjectBadRequest creates HeadContainerObjectBadRequest with default headers values +func NewHeadContainerObjectBadRequest() *HeadContainerObjectBadRequest { + + return &HeadContainerObjectBadRequest{} +} + +// WithPayload adds the payload to the head container object bad request response +func (o *HeadContainerObjectBadRequest) WithPayload(payload *models.ErrorResponse) *HeadContainerObjectBadRequest { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the head container object bad request response +func (o *HeadContainerObjectBadRequest) SetPayload(payload *models.ErrorResponse) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *HeadContainerObjectBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(400) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// HeadContainerObjectNotFoundCode is the HTTP code returned for type HeadContainerObjectNotFound +const HeadContainerObjectNotFoundCode int = 404 + +/*HeadContainerObjectNotFound Not found + +swagger:response headContainerObjectNotFound +*/ +type HeadContainerObjectNotFound struct { + + /* + In: Body + */ + Payload *models.ErrorResponse `json:"body,omitempty"` +} + +// NewHeadContainerObjectNotFound creates HeadContainerObjectNotFound with default headers values +func NewHeadContainerObjectNotFound() *HeadContainerObjectNotFound { + + return &HeadContainerObjectNotFound{} +} + +// WithPayload adds the payload to the head container object not found response +func (o *HeadContainerObjectNotFound) WithPayload(payload *models.ErrorResponse) *HeadContainerObjectNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the head container object not found response +func (o *HeadContainerObjectNotFound) SetPayload(payload *models.ErrorResponse) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *HeadContainerObjectNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/gen/restapi/operations/head_head_container_object.go b/gen/restapi/operations/head_head_container_object.go new file mode 100644 index 0000000..204f8b4 --- /dev/null +++ b/gen/restapi/operations/head_head_container_object.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// HeadHeadContainerObjectHandlerFunc turns a function with the right signature into a head head container object handler +type HeadHeadContainerObjectHandlerFunc func(HeadHeadContainerObjectParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn HeadHeadContainerObjectHandlerFunc) Handle(params HeadHeadContainerObjectParams) middleware.Responder { + return fn(params) +} + +// HeadHeadContainerObjectHandler interface for that can handle valid head head container object params +type HeadHeadContainerObjectHandler interface { + Handle(HeadHeadContainerObjectParams) middleware.Responder +} + +// NewHeadHeadContainerObject creates a new http.Handler for the head head container object operation +func NewHeadHeadContainerObject(ctx *middleware.Context, handler HeadHeadContainerObjectHandler) *HeadHeadContainerObject { + return &HeadHeadContainerObject{Context: ctx, Handler: handler} +} + +/* + HeadHeadContainerObject swagger:route HEAD /head/{containerId}/{objectId} headHeadContainerObject + +Get object info (head) by container id and object id +*/ +type HeadHeadContainerObject struct { + Context *middleware.Context + Handler HeadHeadContainerObjectHandler +} + +func (o *HeadHeadContainerObject) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewHeadHeadContainerObjectParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/gen/restapi/operations/head_head_container_object_parameters.go b/gen/restapi/operations/head_head_container_object_parameters.go new file mode 100644 index 0000000..a74ab4d --- /dev/null +++ b/gen/restapi/operations/head_head_container_object_parameters.go @@ -0,0 +1,95 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewHeadHeadContainerObjectParams creates a new HeadHeadContainerObjectParams object +// +// There are no default values defined in the spec. +func NewHeadHeadContainerObjectParams() HeadHeadContainerObjectParams { + + return HeadHeadContainerObjectParams{} +} + +// HeadHeadContainerObjectParams contains all the bound params for the head head container object operation +// typically these are obtained from a http.Request +// +// swagger:parameters headHeadContainerObject +type HeadHeadContainerObjectParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /*Base58 encoded container id. + Required: true + In: path + */ + ContainerID string + /*Base58 encoded object id. + Required: true + In: path + */ + ObjectID string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewHeadHeadContainerObjectParams() beforehand. +func (o *HeadHeadContainerObjectParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rContainerID, rhkContainerID, _ := route.Params.GetOK("containerId") + if err := o.bindContainerID(rContainerID, rhkContainerID, route.Formats); err != nil { + res = append(res, err) + } + + rObjectID, rhkObjectID, _ := route.Params.GetOK("objectId") + if err := o.bindObjectID(rObjectID, rhkObjectID, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindContainerID binds and validates parameter ContainerID from path. +func (o *HeadHeadContainerObjectParams) bindContainerID(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.ContainerID = raw + + return nil +} + +// bindObjectID binds and validates parameter ObjectID from path. +func (o *HeadHeadContainerObjectParams) bindObjectID(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.ObjectID = raw + + return nil +} diff --git a/gen/restapi/operations/head_head_container_object_responses.go b/gen/restapi/operations/head_head_container_object_responses.go new file mode 100644 index 0000000..f2ba5d3 --- /dev/null +++ b/gen/restapi/operations/head_head_container_object_responses.go @@ -0,0 +1,126 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/nspcc-dev/neofs-rest-gw/gen/models" +) + +// HeadHeadContainerObjectOKCode is the HTTP code returned for type HeadHeadContainerObjectOK +const HeadHeadContainerObjectOKCode int = 200 + +/* +HeadHeadContainerObjectOK Object info. + +swagger:response headHeadContainerObjectOK +*/ +type HeadHeadContainerObjectOK struct { + /* + + */ + AccessControlAllowOrigin string `json:"Access-Control-Allow-Origin"` + + /* + In: Body + */ + Payload *models.ObjectInfo `json:"body,omitempty"` +} + +// NewHeadHeadContainerObjectOK creates HeadHeadContainerObjectOK with default headers values +func NewHeadHeadContainerObjectOK() *HeadHeadContainerObjectOK { + + return &HeadHeadContainerObjectOK{} +} + +// WithAccessControlAllowOrigin adds the accessControlAllowOrigin to the head head container object o k response +func (o *HeadHeadContainerObjectOK) WithAccessControlAllowOrigin(accessControlAllowOrigin string) *HeadHeadContainerObjectOK { + o.AccessControlAllowOrigin = accessControlAllowOrigin + return o +} + +// SetAccessControlAllowOrigin sets the accessControlAllowOrigin to the head head container object o k response +func (o *HeadHeadContainerObjectOK) SetAccessControlAllowOrigin(accessControlAllowOrigin string) { + o.AccessControlAllowOrigin = accessControlAllowOrigin +} + +// WithPayload adds the payload to the head head container object o k response +func (o *HeadHeadContainerObjectOK) WithPayload(payload *models.ObjectInfo) *HeadHeadContainerObjectOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the head head container object o k response +func (o *HeadHeadContainerObjectOK) SetPayload(payload *models.ObjectInfo) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *HeadHeadContainerObjectOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + // response header Access-Control-Allow-Origin + + accessControlAllowOrigin := o.AccessControlAllowOrigin + if accessControlAllowOrigin != "" { + rw.Header().Set("Access-Control-Allow-Origin", accessControlAllowOrigin) + } + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// HeadHeadContainerObjectBadRequestCode is the HTTP code returned for type HeadHeadContainerObjectBadRequest +const HeadHeadContainerObjectBadRequestCode int = 400 + +/* +HeadHeadContainerObjectBadRequest Bad request. + +swagger:response headHeadContainerObjectBadRequest +*/ +type HeadHeadContainerObjectBadRequest struct { + + /* + In: Body + */ + Payload *models.ErrorResponse `json:"body,omitempty"` +} + +// NewHeadHeadContainerObjectBadRequest creates HeadHeadContainerObjectBadRequest with default headers values +func NewHeadHeadContainerObjectBadRequest() *HeadHeadContainerObjectBadRequest { + + return &HeadHeadContainerObjectBadRequest{} +} + +// WithPayload adds the payload to the head head container object bad request response +func (o *HeadHeadContainerObjectBadRequest) WithPayload(payload *models.ErrorResponse) *HeadHeadContainerObjectBadRequest { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the head head container object bad request response +func (o *HeadHeadContainerObjectBadRequest) SetPayload(payload *models.ErrorResponse) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *HeadHeadContainerObjectBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(400) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/gen/restapi/operations/neofs_rest_gw_api.go b/gen/restapi/operations/neofs_rest_gw_api.go index a99480a..c052e48 100644 --- a/gen/restapi/operations/neofs_rest_gw_api.go +++ b/gen/restapi/operations/neofs_rest_gw_api.go @@ -42,6 +42,7 @@ func NewNeofsRestGwAPI(spec *loads.Document) *NeofsRestGwAPI { JSONConsumer: runtime.JSONConsumer(), + BinProducer: runtime.ByteStreamProducer(), JSONProducer: runtime.JSONProducer(), AuthHandler: AuthHandlerFunc(func(params AuthParams) middleware.Responder { @@ -65,9 +66,15 @@ func NewNeofsRestGwAPI(spec *loads.Document) *NeofsRestGwAPI { GetContainerEACLHandler: GetContainerEACLHandlerFunc(func(params GetContainerEACLParams) middleware.Responder { return middleware.NotImplemented("operation GetContainerEACL has not yet been implemented") }), + GetContainerObjectHandler: GetContainerObjectHandlerFunc(func(params GetContainerObjectParams, principal *models.Principal) middleware.Responder { + return middleware.NotImplemented("operation GetContainerObject has not yet been implemented") + }), GetObjectInfoHandler: GetObjectInfoHandlerFunc(func(params GetObjectInfoParams, principal *models.Principal) middleware.Responder { return middleware.NotImplemented("operation GetObjectInfo has not yet been implemented") }), + HeadContainerObjectHandler: HeadContainerObjectHandlerFunc(func(params HeadContainerObjectParams, principal *models.Principal) middleware.Responder { + return middleware.NotImplemented("operation HeadContainerObject has not yet been implemented") + }), ListContainersHandler: ListContainersHandlerFunc(func(params ListContainersParams) middleware.Responder { return middleware.NotImplemented("operation ListContainers has not yet been implemented") }), @@ -112,6 +119,10 @@ func NewNeofsRestGwAPI(spec *loads.Document) *NeofsRestGwAPI { BearerAuthAuth: func(token string) (*models.Principal, error) { return nil, errors.NotImplemented("api key auth (BearerAuth) Authorization from header param [Authorization] has not yet been implemented") }, + // Applies when the "cookie" header is set + CookieAuthAuth: func(token string) (*models.Principal, error) { + return nil, errors.NotImplemented("api key auth (CookieAuth) cookie from header param [cookie] has not yet been implemented") + }, // default authorizer is authorized meaning no requests are blocked APIAuthorizer: security.Authorized(), } @@ -146,6 +157,9 @@ type NeofsRestGwAPI struct { // - application/json JSONConsumer runtime.Consumer + // BinProducer registers a producer for the following mime types: + // - application/octet-stream + BinProducer runtime.Producer // JSONProducer registers a producer for the following mime types: // - application/json JSONProducer runtime.Producer @@ -154,6 +168,10 @@ type NeofsRestGwAPI struct { // it performs authentication based on an api key Authorization provided in the header BearerAuthAuth func(string) (*models.Principal, error) + // CookieAuthAuth registers a function that takes a token and returns a principal + // it performs authentication based on an api key cookie provided in the header + CookieAuthAuth func(string) (*models.Principal, error) + // APIAuthorizer provides access control (ACL/RBAC/ABAC) by providing access to the request and authenticated principal APIAuthorizer runtime.Authorizer @@ -171,8 +189,12 @@ type NeofsRestGwAPI struct { GetContainerHandler GetContainerHandler // GetContainerEACLHandler sets the operation handler for the get container e ACL operation GetContainerEACLHandler GetContainerEACLHandler + // GetContainerObjectHandler sets the operation handler for the get container object operation + GetContainerObjectHandler GetContainerObjectHandler // GetObjectInfoHandler sets the operation handler for the get object info operation GetObjectInfoHandler GetObjectInfoHandler + // HeadContainerObjectHandler sets the operation handler for the head container object operation + HeadContainerObjectHandler HeadContainerObjectHandler // ListContainersHandler sets the operation handler for the list containers operation ListContainersHandler ListContainersHandler // OptionsAuthHandler sets the operation handler for the options auth operation @@ -272,6 +294,9 @@ func (o *NeofsRestGwAPI) Validate() error { unregistered = append(unregistered, "JSONConsumer") } + if o.BinProducer == nil { + unregistered = append(unregistered, "BinProducer") + } if o.JSONProducer == nil { unregistered = append(unregistered, "JSONProducer") } @@ -279,6 +304,9 @@ func (o *NeofsRestGwAPI) Validate() error { if o.BearerAuthAuth == nil { unregistered = append(unregistered, "AuthorizationAuth") } + if o.CookieAuthAuth == nil { + unregistered = append(unregistered, "CookieAuth") + } if o.AuthHandler == nil { unregistered = append(unregistered, "AuthHandler") @@ -301,9 +329,15 @@ func (o *NeofsRestGwAPI) Validate() error { if o.GetContainerEACLHandler == nil { unregistered = append(unregistered, "GetContainerEACLHandler") } + if o.GetContainerObjectHandler == nil { + unregistered = append(unregistered, "GetContainerObjectHandler") + } if o.GetObjectInfoHandler == nil { unregistered = append(unregistered, "GetObjectInfoHandler") } + if o.HeadContainerObjectHandler == nil { + unregistered = append(unregistered, "HeadContainerObjectHandler") + } if o.ListContainersHandler == nil { unregistered = append(unregistered, "ListContainersHandler") } @@ -367,6 +401,12 @@ func (o *NeofsRestGwAPI) AuthenticatorsFor(schemes map[string]spec.SecuritySchem return o.BearerAuthAuth(token) }) + case "CookieAuth": + scheme := schemes[name] + result[name] = o.APIKeyAuthenticator(scheme.Name, scheme.In, func(token string) (interface{}, error) { + return o.CookieAuthAuth(token) + }) + } } return result @@ -400,6 +440,8 @@ func (o *NeofsRestGwAPI) ProducersFor(mediaTypes []string) map[string]runtime.Pr result := make(map[string]runtime.Producer, len(mediaTypes)) for _, mt := range mediaTypes { switch mt { + case "application/octet-stream": + result["application/octet-stream"] = o.BinProducer case "application/json": result["application/json"] = o.JSONProducer } @@ -473,7 +515,15 @@ func (o *NeofsRestGwAPI) initHandlerCache() { if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } + o.handlers["GET"]["/get/{containerId}/{objectId}"] = NewGetContainerObject(o.context, o.GetContainerObjectHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } o.handlers["GET"]["/objects/{containerId}/{objectId}"] = NewGetObjectInfo(o.context, o.GetObjectInfoHandler) + if o.handlers["HEAD"] == nil { + o.handlers["HEAD"] = make(map[string]http.Handler) + } + o.handlers["HEAD"]["/get/{containerId}/{objectId}"] = NewHeadContainerObject(o.context, o.HeadContainerObjectHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } diff --git a/go.mod b/go.mod index 4ad5ad3..dde2a51 100644 --- a/go.mod +++ b/go.mod @@ -6,19 +6,19 @@ require ( github.com/go-openapi/errors v0.20.4 github.com/go-openapi/loads v0.21.2 github.com/go-openapi/runtime v0.26.0 - github.com/go-openapi/spec v0.20.9 - github.com/go-openapi/strfmt v0.21.7 + github.com/go-openapi/spec v0.20.11 + github.com/go-openapi/strfmt v0.21.9 github.com/go-openapi/swag v0.22.4 - github.com/go-openapi/validate v0.22.1 - github.com/google/uuid v1.3.1 + github.com/go-openapi/validate v0.22.3 + github.com/google/uuid v1.4.0 github.com/nspcc-dev/neo-go v0.102.0 github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 - github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11 + github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20230912200451-c0eefd5bd81c github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.25.0 go.uber.org/zap v1.26.0 - golang.org/x/net v0.17.0 + golang.org/x/net v0.19.0 ) require ( @@ -28,7 +28,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect @@ -98,13 +98,13 @@ require ( github.com/spf13/viper v1.10.1 github.com/subosito/gotenv v1.2.0 // indirect github.com/urfave/cli v1.22.12 // indirect - go.mongodb.org/mongo-driver v1.12.1 // indirect + go.mongodb.org/mongo-driver v1.13.1 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.10.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/crypto v0.16.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect google.golang.org/grpc v1.57.1 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.66.2 // indirect diff --git a/go.sum b/go.sum index ac7193c..8e1d537 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,6 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM= github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -112,11 +110,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= -github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M= github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= @@ -125,57 +120,28 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34 github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= github.com/go-openapi/runtime v0.26.0 h1:HYOFtG00FM1UvqrcxbEJg/SwvDRvYLQKGhw2zaQjTcc= github.com/go-openapi/runtime v0.26.0/go.mod h1:QgRGeZwrUcSHdeh4Ka9Glvo0ug1LC5WyE+EV88plZrQ= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8= -github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= +github.com/go-openapi/spec v0.20.11 h1:J/TzFDLTt4Rcl/l1PmyErvkqlJDncGvPTMnCI39I4gY= +github.com/go-openapi/spec v0.20.11/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= -github.com/go-openapi/strfmt v0.21.7 h1:rspiXgNWgeUzhjo1YU01do6qsahtJNByjLVbPLNHb8k= -github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew= +github.com/go-openapi/strfmt v0.21.9 h1:LnEGOO9qyEC1v22Bzr323M98G13paIUGPU7yeJtG9Xs= +github.com/go-openapi/strfmt v0.21.9/go.mod h1:0k3v301mglEaZRJdDDGSlN6Npq4VMVU69DE0LUyf7uA= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= -github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= +github.com/go-openapi/validate v0.22.3 h1:KxG9mu5HBRYbecRb37KRCihvGGtND2aXziBAv0NNfyI= +github.com/go-openapi/validate v0.22.3/go.mod h1:kVxh31KbfsxU8ZyoHaDbLBWU5CnMdqBUEtadQ2G4d5M= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -236,8 +202,8 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= @@ -248,8 +214,6 @@ github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -261,15 +225,12 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -289,8 +250,6 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -326,8 +285,8 @@ github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkb github.com/nspcc-dev/neofs-api-go/v2 v2.14.0/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM= github.com/nspcc-dev/neofs-crypto v0.4.0 h1:5LlrUAM5O0k1+sH/sktBtrgfWtq1pgpDs09fZo+KYi4= github.com/nspcc-dev/neofs-crypto v0.4.0/go.mod h1:6XJ8kbXgOfevbI2WMruOtI+qUJXNwSGM/E9eClXxPHs= -github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11 h1:QOc8ZRN5DXlAeRPh5QG9u8rMLgoeRNiZF5/vL7QupWg= -github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11/go.mod h1:W+ImTNRnSNMH8w43H1knCcIqwu7dLHePXtlJNZ7EFIs= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20230912200451-c0eefd5bd81c h1:qdjwsVPibYl889rEjp4IbmeRzf3foogDZR9jefqmDGA= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20230912200451-c0eefd5bd81c/go.mod h1:W+ImTNRnSNMH8w43H1knCcIqwu7dLHePXtlJNZ7EFIs= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= github.com/nspcc-dev/tzhash v1.7.0 h1:/+aL33NC7y5OIGnY2kYgjZt8mg7LVGFMdj/KAJLndnk= @@ -340,7 +299,6 @@ github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYB github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.1.8 h1:zICRlc+C1XzivLc3nzE+cbJV4LIi8tib6YG0MqC6OqA= github.com/opencontainers/runc v1.1.8/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -378,10 +336,8 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= @@ -391,8 +347,6 @@ github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -403,10 +357,8 @@ github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= @@ -437,10 +389,8 @@ github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9f github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8= github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= @@ -451,11 +401,9 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE= -go.mongodb.org/mongo-driver v1.12.1/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ= +go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= +go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -470,17 +418,15 @@ go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -546,14 +492,13 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -565,7 +510,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -580,13 +524,10 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -614,7 +555,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -627,24 +567,23 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -655,13 +594,9 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -797,14 +732,12 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= diff --git a/handlers/api.go b/handlers/api.go index 03b6866..2e44538 100644 --- a/handlers/api.go +++ b/handlers/api.go @@ -127,6 +127,9 @@ func (a *API) Configure(api *operations.NeofsRestGwAPI) http.Handler { api.PutContainerEACLHandler = operations.PutContainerEACLHandlerFunc(a.PutContainerEACL) api.GetContainerEACLHandler = operations.GetContainerEACLHandlerFunc(a.GetContainerEACL) + api.GetContainerObjectHandler = operations.GetContainerObjectHandlerFunc(a.GetContainerObject) + api.HeadContainerObjectHandler = operations.HeadContainerObjectHandlerFunc(a.HeadContainerObject) + api.BearerAuthAuth = func(s string) (*models.Principal, error) { if !strings.HasPrefix(s, BearerPrefix) { return nil, fmt.Errorf("has not bearer token") @@ -138,6 +141,17 @@ func (a *API) Configure(api *operations.NeofsRestGwAPI) http.Handler { return (*models.Principal)(&s), nil } + api.CookieAuthAuth = func(s string) (*models.Principal, error) { + if !strings.HasPrefix(s, BearerPrefix) { + return nil, fmt.Errorf("has not bearer token") + } + if s = strings.TrimPrefix(s, BearerPrefix); len(s) == 0 { + return nil, fmt.Errorf("bearer token is empty") + } + + return (*models.Principal)(&s), nil + } + api.PreServerShutdown = func() {} api.ServerShutdown = func() { diff --git a/handlers/objects.go b/handlers/objects.go index c3cf9bb..55f8b38 100644 --- a/handlers/objects.go +++ b/handlers/objects.go @@ -8,17 +8,26 @@ import ( "errors" "fmt" "io" + "net/http" + "path" + "strconv" "strings" + "time" + "unicode" + "unicode/utf8" + "github.com/go-openapi/runtime" "github.com/go-openapi/runtime/middleware" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neofs-api-go/v2/acl" + "github.com/nspcc-dev/neofs-api-go/v2/container" "github.com/nspcc-dev/neofs-api-go/v2/refs" "github.com/nspcc-dev/neofs-rest-gw/gen/models" "github.com/nspcc-dev/neofs-rest-gw/gen/restapi/operations" "github.com/nspcc-dev/neofs-rest-gw/internal/util" "github.com/nspcc-dev/neofs-sdk-go/bearer" "github.com/nspcc-dev/neofs-sdk-go/client" + apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" "github.com/nspcc-dev/neofs-sdk-go/object" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" @@ -28,9 +37,16 @@ import ( ) const ( - attributeFilePath = "FilePath" + attributeFilePath = "FilePath" + sizeToDetectType = 512 + userAttributeHeaderPrefix = "X-Attribute-" ) +type readCloser struct { + io.Reader + io.Closer +} + // PutObjects handler that uploads object to NeoFS. func (a *API) PutObjects(params operations.PutObjectParams, principal *models.Principal) middleware.Responder { errorResponse := operations.NewPutObjectBadRequest() @@ -305,6 +321,295 @@ func (a *API) SearchObjects(params operations.SearchObjectsParams, principal *mo WithAccessControlAllowOrigin("*") } +// GetContainerObject handler that returns object (using container ID and object ID). +func (a *API) GetContainerObject(params operations.GetContainerObjectParams, principal *models.Principal) middleware.Responder { + errorResponse := operations.NewGetContainerObjectBadRequest() + ctx := params.HTTPRequest.Context() + + addr, err := parseAddress(params.ContainerID, params.ObjectID) + if err != nil { + resp := a.logAndGetErrorResponse("invalid address", err) + return errorResponse.WithPayload(resp) + } + + var prm client.PrmObjectGet + + if principal != nil { + btoken, err := getBearerTokenFromString(string(*principal)) + if err != nil { + resp := a.logAndGetErrorResponse("get bearer token", err) + return errorResponse.WithPayload(resp) + } + attachBearer(&prm, btoken) + } + + header, payloadReader, err := a.pool.ObjectGetInit(ctx, addr.Container(), addr.Object(), a.signer, prm) + if err != nil { + if isNotFoundError(err) { + resp := a.logAndGetErrorResponse("not found", err) + return operations.NewGetContainerObjectNotFound().WithPayload(resp) + } + resp := a.logAndGetErrorResponse("get object", err) + return errorResponse.WithPayload(resp) + } + + payloadSize := header.PayloadSize() + res := operations.NewGetContainerObjectOK() + + responder, contentType := a.setAttributes(res, payloadSize, params.ContainerID, params.ObjectID, header, params.HTTPRequest.URL.Query().Get("download")) + var payload io.ReadCloser = payloadReader + if len(contentType) == 0 { + if payloadSize > 0 { + // determine the Content-Type from the payload head + var payloadHead []byte + + contentType, payloadHead, err = readContentType(payloadSize, func(uint64) (io.Reader, error) { + return payload, nil + }) + if err != nil { + resp := a.logAndGetErrorResponse("invalid ContentType", err) + return errorResponse.WithPayload(resp) + } + + // reset payload reader since a part of the data has been read + var headReader io.Reader = bytes.NewReader(payloadHead) + + if uint64(len(payloadHead)) != payloadSize { // otherwise, we've already read full payload + headReader = io.MultiReader(headReader, payload) + } + + payload = readCloser{headReader, payload} + } else { + contentType = http.DetectContentType(nil) + } + } + + res.WithContentType(contentType). + WithPayload(payload) + + if responder != nil { + return responder + } + + return res +} + +// HeadContainerObject handler that returns object info (using container ID and object ID). +func (a *API) HeadContainerObject(params operations.HeadContainerObjectParams, principal *models.Principal) middleware.Responder { + errorResponse := operations.NewHeadContainerObjectBadRequest() + ctx := params.HTTPRequest.Context() + + addr, err := parseAddress(params.ContainerID, params.ObjectID) + if err != nil { + resp := a.logAndGetErrorResponse("invalid address", err) + return errorResponse.WithPayload(resp) + } + + var prm client.PrmObjectHead + + if principal != nil { + btoken, err := getBearerTokenFromString(string(*principal)) + if err != nil { + resp := a.logAndGetErrorResponse("get bearer token", err) + return errorResponse.WithPayload(resp) + } + attachBearer(&prm, btoken) + } + + header, err := a.pool.ObjectHead(ctx, addr.Container(), addr.Object(), a.signer, prm) + if err != nil { + if isNotFoundError(err) { + resp := a.logAndGetErrorResponse("not found", err) + return operations.NewHeadContainerObjectNotFound().WithPayload(resp) + } + resp := a.logAndGetErrorResponse("head object", err) + return errorResponse.WithPayload(resp) + } + + payloadSize := header.PayloadSize() + res := operations.NewHeadContainerObjectOK() + + responder, contentType := a.setAttributes(res, payloadSize, params.ContainerID, params.ObjectID, *header, params.HTTPRequest.URL.Query().Get("download")) + if len(contentType) == 0 { + if payloadSize > 0 { + contentType, _, err = readContentType(payloadSize, func(sz uint64) (io.Reader, error) { + var prmRange client.PrmObjectRange + + resObj, err := a.pool.ObjectRangeInit(ctx, addr.Container(), addr.Object(), 0, sz, a.signer, prmRange) + if err != nil { + return nil, err + } + return resObj, nil + }) + if err != nil { + resp := a.logAndGetErrorResponse("invalid ContentType", err) + return errorResponse.WithPayload(resp) + } + } else { + contentType = http.DetectContentType(nil) + } + } + + res.WithContentType(contentType) + + if responder != nil { + return responder + } + + return res +} + +func isNotFoundError(err error) bool { + return errors.Is(err, apistatus.ErrObjectNotFound) || + errors.Is(err, apistatus.ErrContainerNotFound) || + errors.Is(err, apistatus.ErrObjectAlreadyRemoved) +} + +type attributeSetter interface { + SetContentLength(contentLength string) + SetXContainerID(xContainerID string) + SetXObjectID(xObjectID string) + SetXOwnerID(xOwnerID string) + SetContentDisposition(contentDisposition string) + SetXAttributeFileName(xAttributeFileName string) + SetXAttributeTimestamp(xAttributeTimestamp int64) + SetLastModified(lastModified string) + WriteResponse(rw http.ResponseWriter, producer runtime.Producer) +} + +func (a *API) setAttributes(res attributeSetter, payloadSize uint64, cid string, oid string, header object.Object, download string) (middleware.Responder, string) { + res.SetContentLength(strconv.FormatUint(payloadSize, 10)) + res.SetXContainerID(cid) + res.SetXObjectID(oid) + res.SetXOwnerID(header.OwnerID().EncodeToString()) + + var ( + contentType, filename string + responder middleware.Responder + ) + attributes := header.Attributes() + if len(attributes) > 0 { + responder = middleware.ResponderFunc(func(rw http.ResponseWriter, pr runtime.Producer) { + for _, attr := range attributes { + key := attr.Key() + val := attr.Value() + if !isValidToken(key) || !isValidValue(val) { + continue + } + switch key { + case object.AttributeFileName: + filename = val + res.SetXAttributeFileName(val) + case object.AttributeTimestamp: + attrTimestamp, err := strconv.ParseInt(val, 10, 64) + if err != nil { + a.log.Info("attribute timestamp parsing error", + zap.String("container ID", cid), + zap.String("object ID", oid), + zap.Error(err)) + continue + } + res.SetXAttributeTimestamp(attrTimestamp) + res.SetLastModified(time.Unix(attrTimestamp, 0).UTC().Format(http.TimeFormat)) + case object.AttributeContentType: + contentType = val + default: + if strings.HasPrefix(key, container.SysAttributePrefix) { + key = systemBackwardTranslator(key) + } + rw.Header().Set(userAttributeHeaderPrefix+key, attr.Value()) + } + } + res.WriteResponse(rw, pr) + }) + } + + var dis = "inline" + switch download { + case "1", "t", "T", "true", "TRUE", "True", "y", "yes", "Y", "YES", "Yes": + dis = "attachment" + } + res.SetContentDisposition(dis + "; filename=" + path.Base(filename)) + + return responder, contentType +} + +// initializes io.Reader with the limited size and detects Content-Type from it. +// Returns r's error directly. Also returns the processed data. +func readContentType(maxSize uint64, rInit func(uint64) (io.Reader, error)) (string, []byte, error) { + if maxSize > sizeToDetectType { + maxSize = sizeToDetectType + } + + buf := make([]byte, maxSize) + + r, err := rInit(maxSize) + if err != nil { + return "", nil, err + } + + n, err := io.ReadFull(r, buf) + if err != nil && !errors.Is(err, io.EOF) { + return "", nil, err + } + + buf = buf[:n] + + return http.DetectContentType(buf), buf, nil +} + +func isValidToken(s string) bool { + for _, c := range s { + if c <= ' ' || c > 127 { + return false + } + if strings.ContainsRune("()<>@,;:\\\"/[]?={}", c) { + return false + } + } + return true +} + +func isValidValue(s string) bool { + for _, c := range s { + // HTTP specification allows for more technically, but we don't want to escape things. + if c < ' ' || c > 127 || c == '"' { + return false + } + } + return true +} + +// systemBackwardTranslator is used to convert headers looking like '__NEOFS__ATTR_NAME' to 'Neofs-Attr-Name'. +func systemBackwardTranslator(key string) string { + // trim specified prefix '__NEOFS__' + key = strings.TrimPrefix(key, container.SysAttributePrefix) + + var res strings.Builder + res.WriteString("Neofs-") + + strs := strings.Split(key, "_") + for i, s := range strs { + s = title(strings.ToLower(s)) + res.WriteString(s) + if i != len(strs)-1 { + res.WriteString("-") + } + } + + return res.String() +} + +func title(str string) string { + if str == "" { + return "" + } + + r, size := utf8.DecodeRuneInString(str) + r0 := unicode.ToTitle(r) + return string(r0) + str[size:] +} + func headObjectBaseInfo(ctx context.Context, p *pool.Pool, cnrID cid.ID, objID oid.ID, btoken *bearer.Token, signer user.Signer) (*models.ObjectBaseInfo, error) { var prm client.PrmObjectHead attachBearer(&prm, btoken) @@ -426,6 +731,23 @@ func prepareBearerToken(bt *BearerToken, isWalletConnect, isFullToken bool) (*be return &btoken, nil } +func getBearerTokenFromString(token string) (*bearer.Token, error) { + data, err := base64.StdEncoding.DecodeString(token) + if err != nil { + return nil, fmt.Errorf("can't base64-decode bearer token: %w", err) + } + + var btoken bearer.Token + if err = btoken.Unmarshal(data); err != nil { + return nil, fmt.Errorf("couldn't unmarshall bearer token: %w", err) + } + if !btoken.VerifySignature() { + return nil, fmt.Errorf("invalid signature") + } + + return &btoken, nil +} + func prepareOffsetLength(params operations.GetObjectInfoParams, objSize uint64) (uint64, uint64, error) { var offset, length uint64 if params.RangeOffset != nil || params.RangeLength != nil { diff --git a/spec/rest.yaml b/spec/rest.yaml index 4f3ba57..976e425 100644 --- a/spec/rest.yaml +++ b/spec/rest.yaml @@ -15,9 +15,15 @@ securityDefinitions: in: header name: Authorization description: Bearer token body to provide with NeoFS request. Must have 'Bearer ' prefix. + CookieAuth: + type: apiKey + in: header + name: cookie + description: Bearer cookie with base64-encoded token contents. security: - BearerAuth: [ ] + - CookieAuth: [ ] parameters: signatureParam: @@ -557,6 +563,108 @@ paths: schema: $ref: '#/definitions/ErrorResponse' + /get/{containerId}/{objectId}: + parameters: + - $ref: '#/parameters/containerId' + - $ref: '#/parameters/objectId' + get: + operationId: getContainerObject + summary: Get object by container ID and object ID. Also returns custom users' header attributes `X-Attribute-*` + security: + - {} + - BearerAuth: [ ] + - CookieAuth: [ ] + produces: + - application/octet-stream + parameters: + - name: download + in: query + description: Set the Content-Disposition header as attachment in response. This make the browser to download object as file instead of showing it on the page. + required: false + type: boolean + responses: + 200: + headers: + Access-Control-Allow-Origin: + type: string + Content-Length: + type: string + Content-Type: + type: string + Content-Disposition: + type: string + Last-Modified: + type: string + X-Object-Id: + type: string + X-Owner-Id: + type: string + X-Container-Id: + type: string + X-Attribute-FileName: + type: string + X-Attribute-Timestamp: + type: integer + description: Object. + schema: + type: string + format: binary + 400: + description: Bad request. + schema: + $ref: '#/definitions/ErrorResponse' + 404: + description: Not found + schema: + $ref: '#/definitions/ErrorResponse' + head: + operationId: headContainerObject + summary: Get object info (head) by container ID and object ID. Also returns custom users' header attributes `X-Attribute-*` + security: + - {} + - BearerAuth: [ ] + - CookieAuth: [ ] + parameters: + - name: download + in: query + description: Set the Content-Disposition header as attachment in response. This make the browser to download object as file instead of showing it on the page. + required: false + type: boolean + responses: + 200: + headers: + Access-Control-Allow-Origin: + type: string + Content-Length: + type: string + Content-Type: + type: string + Content-Disposition: + type: string + Last-Modified: + type: string + X-Object-Id: + type: string + X-Owner-Id: + type: string + X-Container-Id: + type: string + X-Attribute-FileName: + type: string + X-Attribute-Timestamp: + type: integer + description: Object info. + schema: + $ref: "#/definitions/ObjectInfo" + 400: + description: Bad request. + schema: + $ref: '#/definitions/ErrorResponse' + 404: + description: Not found + schema: + $ref: '#/definitions/ErrorResponse' + definitions: BinaryBearer: description: Bearer token for object operations that is represented in binary form.