diff --git a/api/auth/center.go b/api/auth/center.go index 59a36f811..2aca7b6cc 100644 --- a/api/auth/center.go +++ b/api/auth/center.go @@ -24,6 +24,7 @@ import ( var authorizationFieldRegexp = regexp.MustCompile(`AWS4-HMAC-SHA256 Credential=(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/(?P[^/]*)/(?P[^/]+)/aws4_request,\s*SignedHeaders=(?P.+),\s*Signature=(?P.+)`) type ( + // Center is a user authentication interface. Center interface { Authenticate(request *http.Request) (*token.BearerToken, error) } @@ -33,6 +34,7 @@ type ( cli bearer.Credentials } + // Params stores node connection parameters. Params struct { Client sdk.Client Logger *zap.Logger diff --git a/api/handler/api.go b/api/handler/api.go index bdea9147c..293a27c8d 100644 --- a/api/handler/api.go +++ b/api/handler/api.go @@ -14,6 +14,7 @@ type ( obj layer.Client } + // Params holds logger and client. Params struct { Log *zap.Logger Obj layer.Client @@ -24,6 +25,7 @@ const notSupported = "Not supported by NeoFS S3 Gate: " 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) { switch { case obj == nil: diff --git a/api/handler/list.go b/api/handler/list.go index 972ebf007..452f0f7de 100644 --- a/api/handler/list.go +++ b/api/handler/list.go @@ -22,12 +22,14 @@ type listObjectsArgs struct { Version string } +// VersioningConfiguration contains VersioningConfiguration XML representation. type VersioningConfiguration struct { XMLName xml.Name `xml:"VersioningConfiguration"` Text string `xml:",chardata"` Xmlns string `xml:"xmlns,attr"` } +// ListMultipartUploadsResult contains ListMultipartUploadsResult XML representation. type ListMultipartUploadsResult struct { XMLName xml.Name `xml:"ListMultipartUploadsResult"` Text string `xml:",chardata"` @@ -36,6 +38,7 @@ type ListMultipartUploadsResult struct { 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) { var ( err error @@ -134,6 +137,7 @@ func (h *handler) listObjects(w http.ResponseWriter, r *http.Request) (*listObje return arg, list, nil } +// ListObjectsV1Handler handles objects listing requests for API version 1. func (h *handler) ListObjectsV1Handler(w http.ResponseWriter, r *http.Request) { var rid = api.GetRequestID(r.Context()) if arg, list, err := h.listObjects(w, r); err != nil { @@ -193,6 +197,7 @@ func encodeV1(arg *listObjectsArgs, list *layer.ListObjectsInfo) *ListObjectsRes return res } +// ListObjectsV2Handler handles objects listing requests for API version 2. func (h *handler) ListObjectsV2Handler(w http.ResponseWriter, r *http.Request) { var rid = api.GetRequestID(r.Context()) if arg, list, err := h.listObjects(w, r); err != nil { @@ -278,6 +283,7 @@ func parseListObjectArgs(r *http.Request) (*listObjectsArgs, error) { return &res, nil } +// GetBucketVersioningHandler implements bucket versioning getter handler. func (h *handler) GetBucketVersioningHandler(w http.ResponseWriter, r *http.Request) { var ( 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) { var ( rid = api.GetRequestID(r.Context()) diff --git a/api/layer/container.go b/api/layer/container.go index bdfe3e1b2..5138a4d0f 100644 --- a/api/layer/container.go +++ b/api/layer/container.go @@ -12,6 +12,7 @@ import ( ) type ( + // BucketInfo stores basic bucket data. BucketInfo struct { Name string CID *container.ID @@ -19,6 +20,7 @@ type ( Created time.Time } + // ListObjectsParams represents object listing request parameters. ListObjectsParams struct { Bucket string Prefix string diff --git a/api/layer/layer.go b/api/layer/layer.go index 927c02797..46b1144e4 100644 --- a/api/layer/layer.go +++ b/api/layer/layer.go @@ -25,6 +25,7 @@ type ( log *zap.Logger } + // Params stores basic API parameters. Params struct { Pool pool.Client Logger *zap.Logger @@ -32,6 +33,7 @@ type ( Credential neofs.Credentials } + // GetObjectParams stores object get request parameters. GetObjectParams struct { Bucket string Object string @@ -40,6 +42,7 @@ type ( Writer io.Writer } + // PutObjectParams stores object put request parameters. PutObjectParams struct { Bucket string Object string @@ -48,6 +51,7 @@ type ( Header map[string]string } + // CopyObjectParams stores object copy request parameters. CopyObjectParams struct { SrcBucket string DstBucket string @@ -56,10 +60,12 @@ type ( Header map[string]string } + // NeoFS provides basic NeoFS interface. NeoFS interface { Get(ctx context.Context, address *object.Address) (*object.Object, error) } + // Client provides S3 API client interface. Client interface { NeoFS @@ -81,11 +87,13 @@ type ( ) 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") ) -// NewGatewayLayer creates instance of layer. It checks credentials +// NewLayer creates instance of layer. It checks credentials // and establishes gRPC connection with node. func NewLayer(log *zap.Logger, cli sdk.Client) Client { return &layer{ diff --git a/api/layer/util.go b/api/layer/util.go index 014eed896..966560955 100644 --- a/api/layer/util.go +++ b/api/layer/util.go @@ -12,6 +12,7 @@ import ( ) type ( + // ObjectInfo holds S3 object data. ObjectInfo struct { id *object.ID isDir bool @@ -52,6 +53,7 @@ type ( const ( rootSeparator = "root://" + // PathSeparator is a path components separator string. PathSeparator = string(os.PathSeparator) ) @@ -140,11 +142,14 @@ func nameFromObject(o *object.Object) (string, string) { return NameFromString(name) } +// NameFromString splits name into base file name and directory path. func NameFromString(name string) (string, string) { ind := strings.LastIndex(name, PathSeparator) return name[ind+1:], name[:ind+1] } +// ID returns object ID from ObjectInfo. 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 } diff --git a/api/max-clients.go b/api/max-clients.go index 93902f044..f2eb25708 100644 --- a/api/max-clients.go +++ b/api/max-clients.go @@ -6,6 +6,7 @@ import ( ) type ( + // MaxClients provides HTTP handler wrapper with client limit. MaxClients interface { Handle(http.HandlerFunc) http.HandlerFunc } @@ -18,6 +19,8 @@ type ( 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 { if timeout <= 0 { 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 { return func(w http.ResponseWriter, r *http.Request) { if m.pool == nil { diff --git a/api/metrics/api.go b/api/metrics/api.go index 56b406389..503cb171c 100644 --- a/api/metrics/api.go +++ b/api/metrics/api.go @@ -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 { return func(w http.ResponseWriter, r *http.Request) { httpStatsMetric.currentS3Requests.Inc(api) diff --git a/api/reqinfo.go b/api/reqinfo.go index 374a13083..c6594e1f2 100644 --- a/api/reqinfo.go +++ b/api/reqinfo.go @@ -33,6 +33,7 @@ type ( tags []KeyVal // Any additional info not accommodated by above fields } + // ObjectRequest represents object request data. ObjectRequest struct { Bucket string Object string diff --git a/api/response.go b/api/response.go index 872eeac1f..33b34109c 100644 --- a/api/response.go +++ b/api/response.go @@ -36,7 +36,7 @@ type ( StatusCode int `xml:"-" json:"-"` } - // APIError structure. + // Error structure represents API error. Error struct { Code string Description string @@ -168,6 +168,7 @@ func removeSensitiveHeaders(h http.Header) { 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) { setCommonHeaders(w) if mType != MimeNone { @@ -214,6 +215,8 @@ func EncodeToResponse(w http.ResponseWriter, response interface{}) error { // WriteResponse(w, http.StatusOK, response, MimeXML) // } +// WriteSuccessResponseHeadersOnly writes HTTP (200) OK response with no data +// to the client. func WriteSuccessResponseHeadersOnly(w http.ResponseWriter) { WriteResponse(w, http.StatusOK, nil, MimeNone) } diff --git a/api/router.go b/api/router.go index 6291a4442..8ae7b65b3 100644 --- a/api/router.go +++ b/api/router.go @@ -14,6 +14,7 @@ import ( ) type ( + // Handler is an S3 API handler interface. Handler interface { HeadObjectHandler(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 { switch t := v.(type) { 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) { api := r.PathPrefix(SlashSeparator).Subrouter() diff --git a/api/user-auth.go b/api/user-auth.go index ceaa6b9eb..4baaffb6d 100644 --- a/api/user-auth.go +++ b/api/user-auth.go @@ -9,6 +9,7 @@ import ( "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) { router.Use(func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/cmd/gate/app-healthy.go b/cmd/gate/app-healthy.go index 576fe4db6..ca487a93e 100644 --- a/cmd/gate/app-healthy.go +++ b/cmd/gate/app-healthy.go @@ -7,6 +7,7 @@ import ( "github.com/gorilla/mux" ) +// Healthy is a health check interface. type Healthy interface { Status() error } diff --git a/cmd/gate/app.go b/cmd/gate/app.go index 955eb6613..474bd4ada 100644 --- a/cmd/gate/app.go +++ b/cmd/gate/app.go @@ -22,6 +22,7 @@ import ( ) type ( + // App is the main application structure. App struct { cli pool.Client 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() { a.log.Info("application started") @@ -192,6 +194,7 @@ func (a *App) Wait() { a.log.Info("application finished") } +// Server runs HTTP server to handle S3 API requests. func (a *App) Server(ctx context.Context) { var ( err error @@ -256,6 +259,7 @@ func (a *App) Server(ctx context.Context) { close(a.webDone) } +// Worker runs client worker. func (a *App) Worker(ctx context.Context) { a.cli.Worker(ctx) a.log.Info("stopping worker") diff --git a/misc/build.go b/misc/build.go index c014aacad..c954d3554 100644 --- a/misc/build.go +++ b/misc/build.go @@ -1,12 +1,16 @@ package misc const ( + // ApplicationName is gateway name. ApplicationName = "neofs-s3-gate" + // Prefix is configuration environment variables prefix. Prefix = "S3_GW" ) var ( - Build = "now" + // Build holds build timestamp. + Build = "now" + // Version contains application version. Version = "dev" )