forked from TrueCloudLab/frostfs-s3-gw
*: fix golint warnings about comments to exported things.
This commit is contained in:
parent
70a70bfa2c
commit
5eb863dc22
15 changed files with 53 additions and 4 deletions
|
@ -24,6 +24,7 @@ import (
|
||||||
var authorizationFieldRegexp = regexp.MustCompile(`AWS4-HMAC-SHA256 Credential=(?P<access_key_id_cid>[^/]+)/(?P<access_key_id_oid>[^/]+)/(?P<date>[^/]+)/(?P<region>[^/]*)/(?P<service>[^/]+)/aws4_request,\s*SignedHeaders=(?P<signed_header_fields>.+),\s*Signature=(?P<v4_signature>.+)`)
|
var authorizationFieldRegexp = regexp.MustCompile(`AWS4-HMAC-SHA256 Credential=(?P<access_key_id_cid>[^/]+)/(?P<access_key_id_oid>[^/]+)/(?P<date>[^/]+)/(?P<region>[^/]*)/(?P<service>[^/]+)/aws4_request,\s*SignedHeaders=(?P<signed_header_fields>.+),\s*Signature=(?P<v4_signature>.+)`)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// Center is a user authentication interface.
|
||||||
Center interface {
|
Center interface {
|
||||||
Authenticate(request *http.Request) (*token.BearerToken, error)
|
Authenticate(request *http.Request) (*token.BearerToken, error)
|
||||||
}
|
}
|
||||||
|
@ -33,6 +34,7 @@ type (
|
||||||
cli bearer.Credentials
|
cli bearer.Credentials
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Params stores node connection parameters.
|
||||||
Params struct {
|
Params struct {
|
||||||
Client sdk.Client
|
Client sdk.Client
|
||||||
Logger *zap.Logger
|
Logger *zap.Logger
|
||||||
|
|
|
@ -14,6 +14,7 @@ type (
|
||||||
obj layer.Client
|
obj layer.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Params holds logger and client.
|
||||||
Params struct {
|
Params struct {
|
||||||
Log *zap.Logger
|
Log *zap.Logger
|
||||||
Obj layer.Client
|
Obj layer.Client
|
||||||
|
@ -24,6 +25,7 @@ const notSupported = "Not supported by NeoFS S3 Gate: "
|
||||||
|
|
||||||
var _ api.Handler = (*handler)(nil)
|
var _ api.Handler = (*handler)(nil)
|
||||||
|
|
||||||
|
// New creates new api.Handler using given logger and client.
|
||||||
func New(log *zap.Logger, obj layer.Client) (api.Handler, error) {
|
func New(log *zap.Logger, obj layer.Client) (api.Handler, error) {
|
||||||
switch {
|
switch {
|
||||||
case obj == nil:
|
case obj == nil:
|
||||||
|
|
|
@ -22,12 +22,14 @@ type listObjectsArgs struct {
|
||||||
Version string
|
Version string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VersioningConfiguration contains VersioningConfiguration XML representation.
|
||||||
type VersioningConfiguration struct {
|
type VersioningConfiguration struct {
|
||||||
XMLName xml.Name `xml:"VersioningConfiguration"`
|
XMLName xml.Name `xml:"VersioningConfiguration"`
|
||||||
Text string `xml:",chardata"`
|
Text string `xml:",chardata"`
|
||||||
Xmlns string `xml:"xmlns,attr"`
|
Xmlns string `xml:"xmlns,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListMultipartUploadsResult contains ListMultipartUploadsResult XML representation.
|
||||||
type ListMultipartUploadsResult struct {
|
type ListMultipartUploadsResult struct {
|
||||||
XMLName xml.Name `xml:"ListMultipartUploadsResult"`
|
XMLName xml.Name `xml:"ListMultipartUploadsResult"`
|
||||||
Text string `xml:",chardata"`
|
Text string `xml:",chardata"`
|
||||||
|
@ -36,6 +38,7 @@ type ListMultipartUploadsResult struct {
|
||||||
|
|
||||||
var maxObjectList = 10000 // Limit number of objects in a listObjectsResponse/listObjectsVersionsResponse.
|
var maxObjectList = 10000 // Limit number of objects in a listObjectsResponse/listObjectsVersionsResponse.
|
||||||
|
|
||||||
|
// ListBucketsHandler handles bucket listing requests.
|
||||||
func (h *handler) ListBucketsHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListBucketsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
|
@ -134,6 +137,7 @@ func (h *handler) listObjects(w http.ResponseWriter, r *http.Request) (*listObje
|
||||||
return arg, list, nil
|
return arg, list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListObjectsV1Handler handles objects listing requests for API version 1.
|
||||||
func (h *handler) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) {
|
||||||
var rid = api.GetRequestID(r.Context())
|
var rid = api.GetRequestID(r.Context())
|
||||||
if arg, list, err := h.listObjects(w, r); err != nil {
|
if arg, list, err := h.listObjects(w, r); err != nil {
|
||||||
|
@ -193,6 +197,7 @@ func encodeV1(arg *listObjectsArgs, list *layer.ListObjectsInfo) *ListObjectsRes
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListObjectsV2Handler handles objects listing requests for API version 2.
|
||||||
func (h *handler) ListObjectsV2Handler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListObjectsV2Handler(w http.ResponseWriter, r *http.Request) {
|
||||||
var rid = api.GetRequestID(r.Context())
|
var rid = api.GetRequestID(r.Context())
|
||||||
if arg, list, err := h.listObjects(w, r); err != nil {
|
if arg, list, err := h.listObjects(w, r); err != nil {
|
||||||
|
@ -278,6 +283,7 @@ func parseListObjectArgs(r *http.Request) (*listObjectsArgs, error) {
|
||||||
return &res, nil
|
return &res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetBucketVersioningHandler implements bucket versioning getter handler.
|
||||||
func (h *handler) GetBucketVersioningHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetBucketVersioningHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
rid = api.GetRequestID(r.Context())
|
rid = api.GetRequestID(r.Context())
|
||||||
|
@ -299,6 +305,7 @@ func (h *handler) GetBucketVersioningHandler(w http.ResponseWriter, r *http.Requ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListMultipartUploadsHandler implements multipart uploads listing handler.
|
||||||
func (h *handler) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
rid = api.GetRequestID(r.Context())
|
rid = api.GetRequestID(r.Context())
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// BucketInfo stores basic bucket data.
|
||||||
BucketInfo struct {
|
BucketInfo struct {
|
||||||
Name string
|
Name string
|
||||||
CID *container.ID
|
CID *container.ID
|
||||||
|
@ -19,6 +20,7 @@ type (
|
||||||
Created time.Time
|
Created time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListObjectsParams represents object listing request parameters.
|
||||||
ListObjectsParams struct {
|
ListObjectsParams struct {
|
||||||
Bucket string
|
Bucket string
|
||||||
Prefix string
|
Prefix string
|
||||||
|
|
|
@ -25,6 +25,7 @@ type (
|
||||||
log *zap.Logger
|
log *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Params stores basic API parameters.
|
||||||
Params struct {
|
Params struct {
|
||||||
Pool pool.Client
|
Pool pool.Client
|
||||||
Logger *zap.Logger
|
Logger *zap.Logger
|
||||||
|
@ -32,6 +33,7 @@ type (
|
||||||
Credential neofs.Credentials
|
Credential neofs.Credentials
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetObjectParams stores object get request parameters.
|
||||||
GetObjectParams struct {
|
GetObjectParams struct {
|
||||||
Bucket string
|
Bucket string
|
||||||
Object string
|
Object string
|
||||||
|
@ -40,6 +42,7 @@ type (
|
||||||
Writer io.Writer
|
Writer io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PutObjectParams stores object put request parameters.
|
||||||
PutObjectParams struct {
|
PutObjectParams struct {
|
||||||
Bucket string
|
Bucket string
|
||||||
Object string
|
Object string
|
||||||
|
@ -48,6 +51,7 @@ type (
|
||||||
Header map[string]string
|
Header map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CopyObjectParams stores object copy request parameters.
|
||||||
CopyObjectParams struct {
|
CopyObjectParams struct {
|
||||||
SrcBucket string
|
SrcBucket string
|
||||||
DstBucket string
|
DstBucket string
|
||||||
|
@ -56,10 +60,12 @@ type (
|
||||||
Header map[string]string
|
Header map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NeoFS provides basic NeoFS interface.
|
||||||
NeoFS interface {
|
NeoFS interface {
|
||||||
Get(ctx context.Context, address *object.Address) (*object.Object, error)
|
Get(ctx context.Context, address *object.Address) (*object.Object, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Client provides S3 API client interface.
|
||||||
Client interface {
|
Client interface {
|
||||||
NeoFS
|
NeoFS
|
||||||
|
|
||||||
|
@ -81,11 +87,13 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrObjectExists = errors.New("object exists")
|
// ErrObjectExists is returned on attempts to create already existing object.
|
||||||
|
ErrObjectExists = errors.New("object exists")
|
||||||
|
// ErrObjectNotExists is returned on attempts to work with non-existing object.
|
||||||
ErrObjectNotExists = errors.New("object not exists")
|
ErrObjectNotExists = errors.New("object not exists")
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGatewayLayer creates instance of layer. It checks credentials
|
// NewLayer creates instance of layer. It checks credentials
|
||||||
// and establishes gRPC connection with node.
|
// and establishes gRPC connection with node.
|
||||||
func NewLayer(log *zap.Logger, cli sdk.Client) Client {
|
func NewLayer(log *zap.Logger, cli sdk.Client) Client {
|
||||||
return &layer{
|
return &layer{
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// ObjectInfo holds S3 object data.
|
||||||
ObjectInfo struct {
|
ObjectInfo struct {
|
||||||
id *object.ID
|
id *object.ID
|
||||||
isDir bool
|
isDir bool
|
||||||
|
@ -52,6 +53,7 @@ type (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
rootSeparator = "root://"
|
rootSeparator = "root://"
|
||||||
|
// PathSeparator is a path components separator string.
|
||||||
PathSeparator = string(os.PathSeparator)
|
PathSeparator = string(os.PathSeparator)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -140,11 +142,14 @@ func nameFromObject(o *object.Object) (string, string) {
|
||||||
return NameFromString(name)
|
return NameFromString(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NameFromString splits name into base file name and directory path.
|
||||||
func NameFromString(name string) (string, string) {
|
func NameFromString(name string) (string, string) {
|
||||||
ind := strings.LastIndex(name, PathSeparator)
|
ind := strings.LastIndex(name, PathSeparator)
|
||||||
return name[ind+1:], name[:ind+1]
|
return name[ind+1:], name[:ind+1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ID returns object ID from ObjectInfo.
|
||||||
func (o *ObjectInfo) ID() *object.ID { return o.id }
|
func (o *ObjectInfo) ID() *object.ID { return o.id }
|
||||||
|
|
||||||
|
// IsDir allows to check if object is a directory.
|
||||||
func (o *ObjectInfo) IsDir() bool { return o.isDir }
|
func (o *ObjectInfo) IsDir() bool { return o.isDir }
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// MaxClients provides HTTP handler wrapper with client limit.
|
||||||
MaxClients interface {
|
MaxClients interface {
|
||||||
Handle(http.HandlerFunc) http.HandlerFunc
|
Handle(http.HandlerFunc) http.HandlerFunc
|
||||||
}
|
}
|
||||||
|
@ -18,6 +19,8 @@ type (
|
||||||
|
|
||||||
const defaultRequestDeadline = time.Second * 30
|
const defaultRequestDeadline = time.Second * 30
|
||||||
|
|
||||||
|
// NewMaxClientsMiddleware returns MaxClients interface with handler wrapper based on
|
||||||
|
// provided count and timeout limits.
|
||||||
func NewMaxClientsMiddleware(count int, timeout time.Duration) MaxClients {
|
func NewMaxClientsMiddleware(count int, timeout time.Duration) MaxClients {
|
||||||
if timeout <= 0 {
|
if timeout <= 0 {
|
||||||
timeout = defaultRequestDeadline
|
timeout = defaultRequestDeadline
|
||||||
|
@ -29,6 +32,7 @@ func NewMaxClientsMiddleware(count int, timeout time.Duration) MaxClients {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handler wraps HTTP handler function with logic limiting access to it.
|
||||||
func (m *maxClients) Handle(f http.HandlerFunc) http.HandlerFunc {
|
func (m *maxClients) Handle(f http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
if m.pool == nil {
|
if m.pool == nil {
|
||||||
|
|
|
@ -103,6 +103,7 @@ func collectHTTPMetrics(ch chan<- prometheus.Metric) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// APIStats wraps http handler for api with basic statistics collection.
|
||||||
func APIStats(api string, f http.HandlerFunc) http.HandlerFunc {
|
func APIStats(api string, f http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
httpStatsMetric.currentS3Requests.Inc(api)
|
httpStatsMetric.currentS3Requests.Inc(api)
|
||||||
|
|
|
@ -33,6 +33,7 @@ type (
|
||||||
tags []KeyVal // Any additional info not accommodated by above fields
|
tags []KeyVal // Any additional info not accommodated by above fields
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ObjectRequest represents object request data.
|
||||||
ObjectRequest struct {
|
ObjectRequest struct {
|
||||||
Bucket string
|
Bucket string
|
||||||
Object string
|
Object string
|
||||||
|
|
|
@ -36,7 +36,7 @@ type (
|
||||||
StatusCode int `xml:"-" json:"-"`
|
StatusCode int `xml:"-" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIError structure.
|
// Error structure represents API error.
|
||||||
Error struct {
|
Error struct {
|
||||||
Code string
|
Code string
|
||||||
Description string
|
Description string
|
||||||
|
@ -168,6 +168,7 @@ func removeSensitiveHeaders(h http.Header) {
|
||||||
h.Del(hdrSSECopyKey)
|
h.Del(hdrSSECopyKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteResponse writes given statusCode and response into w (with mType header if set).
|
||||||
func WriteResponse(w http.ResponseWriter, statusCode int, response []byte, mType mimeType) {
|
func WriteResponse(w http.ResponseWriter, statusCode int, response []byte, mType mimeType) {
|
||||||
setCommonHeaders(w)
|
setCommonHeaders(w)
|
||||||
if mType != MimeNone {
|
if mType != MimeNone {
|
||||||
|
@ -214,6 +215,8 @@ func EncodeToResponse(w http.ResponseWriter, response interface{}) error {
|
||||||
// WriteResponse(w, http.StatusOK, response, MimeXML)
|
// WriteResponse(w, http.StatusOK, response, MimeXML)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// WriteSuccessResponseHeadersOnly writes HTTP (200) OK response with no data
|
||||||
|
// to the client.
|
||||||
func WriteSuccessResponseHeadersOnly(w http.ResponseWriter) {
|
func WriteSuccessResponseHeadersOnly(w http.ResponseWriter) {
|
||||||
WriteResponse(w, http.StatusOK, nil, MimeNone)
|
WriteResponse(w, http.StatusOK, nil, MimeNone)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// Handler is an S3 API handler interface.
|
||||||
Handler interface {
|
Handler interface {
|
||||||
HeadObjectHandler(http.ResponseWriter, *http.Request)
|
HeadObjectHandler(http.ResponseWriter, *http.Request)
|
||||||
CopyObjectPartHandler(http.ResponseWriter, *http.Request)
|
CopyObjectPartHandler(http.ResponseWriter, *http.Request)
|
||||||
|
@ -158,6 +159,7 @@ func logErrorResponse(l *zap.Logger) mux.MiddlewareFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRequestID returns request ID from response writer or context.
|
||||||
func GetRequestID(v interface{}) string {
|
func GetRequestID(v interface{}) string {
|
||||||
switch t := v.(type) {
|
switch t := v.(type) {
|
||||||
case context.Context:
|
case context.Context:
|
||||||
|
@ -169,6 +171,8 @@ func GetRequestID(v interface{}) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attach adds S3 API handlers from h to r for domains with m client limit using
|
||||||
|
// center authentication and log logger.
|
||||||
func Attach(r *mux.Router, domains []string, m MaxClients, h Handler, center auth.Center, log *zap.Logger) {
|
func Attach(r *mux.Router, domains []string, m MaxClients, h Handler, center auth.Center, log *zap.Logger) {
|
||||||
api := r.PathPrefix(SlashSeparator).Subrouter()
|
api := r.PathPrefix(SlashSeparator).Subrouter()
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AttachUserAuth adds user authentication via center to router using log for logging.
|
||||||
func AttachUserAuth(router *mux.Router, center auth.Center, log *zap.Logger) {
|
func AttachUserAuth(router *mux.Router, center auth.Center, log *zap.Logger) {
|
||||||
router.Use(func(h http.Handler) http.Handler {
|
router.Use(func(h http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Healthy is a health check interface.
|
||||||
type Healthy interface {
|
type Healthy interface {
|
||||||
Status() error
|
Status() error
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
// App is the main application structure.
|
||||||
App struct {
|
App struct {
|
||||||
cli pool.Client
|
cli pool.Client
|
||||||
ctr auth.Center
|
ctr auth.Center
|
||||||
|
@ -179,6 +180,7 @@ func newApp(ctx context.Context, l *zap.Logger, v *viper.Viper) *App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait waits for application to finish.
|
||||||
func (a *App) Wait() {
|
func (a *App) Wait() {
|
||||||
a.log.Info("application started")
|
a.log.Info("application started")
|
||||||
|
|
||||||
|
@ -192,6 +194,7 @@ func (a *App) Wait() {
|
||||||
a.log.Info("application finished")
|
a.log.Info("application finished")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Server runs HTTP server to handle S3 API requests.
|
||||||
func (a *App) Server(ctx context.Context) {
|
func (a *App) Server(ctx context.Context) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
|
@ -256,6 +259,7 @@ func (a *App) Server(ctx context.Context) {
|
||||||
close(a.webDone)
|
close(a.webDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Worker runs client worker.
|
||||||
func (a *App) Worker(ctx context.Context) {
|
func (a *App) Worker(ctx context.Context) {
|
||||||
a.cli.Worker(ctx)
|
a.cli.Worker(ctx)
|
||||||
a.log.Info("stopping worker")
|
a.log.Info("stopping worker")
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
package misc
|
package misc
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// ApplicationName is gateway name.
|
||||||
ApplicationName = "neofs-s3-gate"
|
ApplicationName = "neofs-s3-gate"
|
||||||
|
|
||||||
|
// Prefix is configuration environment variables prefix.
|
||||||
Prefix = "S3_GW"
|
Prefix = "S3_GW"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Build = "now"
|
// Build holds build timestamp.
|
||||||
|
Build = "now"
|
||||||
|
// Version contains application version.
|
||||||
Version = "dev"
|
Version = "dev"
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue