2020-07-22 13:02:32 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
2020-08-11 11:30:02 +00:00
|
|
|
"context"
|
2020-07-22 13:02:32 +00:00
|
|
|
"net/http"
|
2020-11-27 12:28:27 +00:00
|
|
|
"sync"
|
2020-07-22 13:02:32 +00:00
|
|
|
|
2022-12-14 16:58:00 +00:00
|
|
|
"github.com/TrueCloudLab/frostfs-s3-gw/api/auth"
|
2022-12-23 12:28:30 +00:00
|
|
|
"github.com/TrueCloudLab/frostfs-s3-gw/api/data"
|
2020-08-11 11:30:02 +00:00
|
|
|
"github.com/google/uuid"
|
2020-07-22 13:02:32 +00:00
|
|
|
"github.com/gorilla/mux"
|
2020-07-22 19:48:34 +00:00
|
|
|
"go.uber.org/zap"
|
2020-08-11 11:30:02 +00:00
|
|
|
"google.golang.org/grpc/metadata"
|
2020-07-22 13:02:32 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
2021-05-13 20:25:31 +00:00
|
|
|
// Handler is an S3 API handler interface.
|
2020-07-22 13:02:32 +00:00
|
|
|
Handler interface {
|
|
|
|
HeadObjectHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetObjectACLHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutObjectACLHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetObjectTaggingHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutObjectTaggingHandler(http.ResponseWriter, *http.Request)
|
|
|
|
DeleteObjectTaggingHandler(http.ResponseWriter, *http.Request)
|
|
|
|
SelectObjectContentHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetObjectRetentionHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetObjectLegalHoldHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetObjectHandler(http.ResponseWriter, *http.Request)
|
2022-05-12 21:15:08 +00:00
|
|
|
GetObjectAttributesHandler(http.ResponseWriter, *http.Request)
|
2020-07-22 13:02:32 +00:00
|
|
|
CopyObjectHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutObjectRetentionHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutObjectLegalHoldHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutObjectHandler(http.ResponseWriter, *http.Request)
|
|
|
|
DeleteObjectHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketLocationHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketPolicyHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketLifecycleHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketEncryptionHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketACLHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutBucketACLHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketCorsHandler(http.ResponseWriter, *http.Request)
|
2021-10-04 14:32:35 +00:00
|
|
|
PutBucketCorsHandler(http.ResponseWriter, *http.Request)
|
|
|
|
DeleteBucketCorsHandler(http.ResponseWriter, *http.Request)
|
2020-07-22 13:02:32 +00:00
|
|
|
GetBucketWebsiteHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketAccelerateHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketRequestPaymentHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketLoggingHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketReplicationHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketTaggingHandler(http.ResponseWriter, *http.Request)
|
|
|
|
DeleteBucketWebsiteHandler(http.ResponseWriter, *http.Request)
|
|
|
|
DeleteBucketTaggingHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketObjectLockConfigHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketVersioningHandler(http.ResponseWriter, *http.Request)
|
|
|
|
GetBucketNotificationHandler(http.ResponseWriter, *http.Request)
|
|
|
|
ListenBucketNotificationHandler(http.ResponseWriter, *http.Request)
|
|
|
|
ListObjectsV2MHandler(http.ResponseWriter, *http.Request)
|
|
|
|
ListObjectsV2Handler(http.ResponseWriter, *http.Request)
|
|
|
|
ListBucketObjectVersionsHandler(http.ResponseWriter, *http.Request)
|
|
|
|
ListObjectsV1Handler(http.ResponseWriter, *http.Request)
|
|
|
|
PutBucketLifecycleHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutBucketEncryptionHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutBucketPolicyHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutBucketObjectLockConfigHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutBucketTaggingHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutBucketVersioningHandler(http.ResponseWriter, *http.Request)
|
|
|
|
PutBucketNotificationHandler(http.ResponseWriter, *http.Request)
|
2021-06-23 20:21:15 +00:00
|
|
|
CreateBucketHandler(http.ResponseWriter, *http.Request)
|
2020-07-22 13:02:32 +00:00
|
|
|
HeadBucketHandler(http.ResponseWriter, *http.Request)
|
2021-08-30 19:44:53 +00:00
|
|
|
PostObject(http.ResponseWriter, *http.Request)
|
2020-07-22 13:02:32 +00:00
|
|
|
DeleteMultipleObjectsHandler(http.ResponseWriter, *http.Request)
|
|
|
|
DeleteBucketPolicyHandler(http.ResponseWriter, *http.Request)
|
|
|
|
DeleteBucketLifecycleHandler(http.ResponseWriter, *http.Request)
|
|
|
|
DeleteBucketEncryptionHandler(http.ResponseWriter, *http.Request)
|
|
|
|
DeleteBucketHandler(http.ResponseWriter, *http.Request)
|
|
|
|
ListBucketsHandler(http.ResponseWriter, *http.Request)
|
2021-10-04 14:32:35 +00:00
|
|
|
Preflight(w http.ResponseWriter, r *http.Request)
|
|
|
|
AppendCORSHeaders(w http.ResponseWriter, r *http.Request)
|
2021-11-25 15:05:58 +00:00
|
|
|
CreateMultipartUploadHandler(http.ResponseWriter, *http.Request)
|
|
|
|
UploadPartHandler(http.ResponseWriter, *http.Request)
|
|
|
|
UploadPartCopy(w http.ResponseWriter, r *http.Request)
|
|
|
|
CompleteMultipartUploadHandler(http.ResponseWriter, *http.Request)
|
|
|
|
AbortMultipartUploadHandler(http.ResponseWriter, *http.Request)
|
|
|
|
ListPartsHandler(w http.ResponseWriter, r *http.Request)
|
|
|
|
ListMultipartUploadsHandler(http.ResponseWriter, *http.Request)
|
2022-12-23 12:28:30 +00:00
|
|
|
|
|
|
|
ResolveBucket(ctx context.Context, bucket string) (*data.BucketInfo, error)
|
2020-07-22 13:02:32 +00:00
|
|
|
}
|
|
|
|
|
2022-04-13 16:56:58 +00:00
|
|
|
// mimeType represents various MIME types used in API responses.
|
2020-07-22 13:02:32 +00:00
|
|
|
mimeType string
|
2020-08-19 23:28:16 +00:00
|
|
|
|
|
|
|
logResponseWriter struct {
|
2020-11-27 12:28:27 +00:00
|
|
|
sync.Once
|
2020-08-19 23:28:16 +00:00
|
|
|
http.ResponseWriter
|
2020-11-27 12:28:27 +00:00
|
|
|
|
2020-08-19 23:28:16 +00:00
|
|
|
statusCode int
|
|
|
|
}
|
2020-07-22 13:02:32 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2022-04-13 16:56:58 +00:00
|
|
|
// SlashSeparator -- slash separator.
|
2020-07-22 13:02:32 +00:00
|
|
|
SlashSeparator = "/"
|
|
|
|
|
2020-08-22 02:32:48 +00:00
|
|
|
// MimeNone means no response type.
|
|
|
|
MimeNone mimeType = ""
|
|
|
|
|
|
|
|
// MimeXML means response type is XML.
|
|
|
|
MimeXML mimeType = "application/xml"
|
2020-07-22 13:02:32 +00:00
|
|
|
)
|
|
|
|
|
2020-08-19 23:28:16 +00:00
|
|
|
var _ = logErrorResponse
|
|
|
|
|
|
|
|
func (lrw *logResponseWriter) WriteHeader(code int) {
|
2020-11-27 12:28:27 +00:00
|
|
|
lrw.Do(func() {
|
|
|
|
lrw.statusCode = code
|
|
|
|
lrw.ResponseWriter.WriteHeader(code)
|
|
|
|
})
|
2020-08-19 23:28:16 +00:00
|
|
|
}
|
|
|
|
|
2020-08-11 11:30:02 +00:00
|
|
|
func setRequestID(h http.Handler) http.Handler {
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
// generate random UUIDv4
|
|
|
|
id, _ := uuid.NewRandom()
|
|
|
|
|
|
|
|
// set request id into response header
|
|
|
|
w.Header().Set(hdrAmzRequestID, id.String())
|
|
|
|
|
|
|
|
// set request id into gRPC meta header
|
|
|
|
r = r.WithContext(metadata.AppendToOutgoingContext(
|
|
|
|
r.Context(), hdrAmzRequestID, id.String(),
|
|
|
|
))
|
|
|
|
|
|
|
|
// set request info into context
|
|
|
|
r = r.WithContext(prepareContext(w, r))
|
|
|
|
|
|
|
|
// continue execution
|
|
|
|
h.ServeHTTP(w, r)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-10-04 14:32:35 +00:00
|
|
|
func appendCORS(handler Handler) mux.MiddlewareFunc {
|
|
|
|
return func(h http.Handler) http.Handler {
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
handler.AppendCORSHeaders(w, r)
|
|
|
|
h.ServeHTTP(w, r)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-23 12:28:30 +00:00
|
|
|
func resolveBucket(log *zap.Logger, resolveBucket func(ctx context.Context, bucket string) (*data.BucketInfo, error)) mux.MiddlewareFunc {
|
|
|
|
return func(h http.Handler) http.Handler {
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
reqInfo := GetReqInfo(r.Context())
|
|
|
|
|
|
|
|
if reqInfo.BucketName != "" {
|
|
|
|
bktInfo, err := resolveBucket(r.Context(), reqInfo.BucketName)
|
|
|
|
if err != nil {
|
|
|
|
code := WriteErrorResponse(w, reqInfo, err)
|
|
|
|
log.Error("failed to resolve bucket", zap.Int("status", code),
|
|
|
|
zap.String("request_id", reqInfo.RequestID), zap.String("method", reqInfo.API),
|
|
|
|
zap.String("bucket", reqInfo.BucketName), zap.String("object", reqInfo.ObjectName),
|
|
|
|
zap.Error(err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// todo: (@KirillovDenis) consider save bktInfo into ReqInfo
|
|
|
|
// (in order to optimize resolving bucket in further handlers)
|
|
|
|
r = r.WithContext(SetCID(r.Context(), bktInfo.CID))
|
|
|
|
}
|
|
|
|
|
|
|
|
h.ServeHTTP(w, r)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-19 23:28:16 +00:00
|
|
|
func logErrorResponse(l *zap.Logger) mux.MiddlewareFunc {
|
|
|
|
return func(h http.Handler) http.Handler {
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
lw := &logResponseWriter{ResponseWriter: w}
|
2022-10-24 15:28:28 +00:00
|
|
|
reqInfo := GetReqInfo(r.Context())
|
2020-08-19 23:28:16 +00:00
|
|
|
|
|
|
|
// pass execution:
|
|
|
|
h.ServeHTTP(lw, r)
|
|
|
|
|
2022-10-25 15:14:46 +00:00
|
|
|
// Ignore >400 status codes
|
|
|
|
if lw.statusCode >= http.StatusBadRequest {
|
2020-11-27 12:28:27 +00:00
|
|
|
return
|
2020-08-19 23:28:16 +00:00
|
|
|
}
|
2020-11-27 12:28:27 +00:00
|
|
|
|
|
|
|
l.Info("call method",
|
|
|
|
zap.Int("status", lw.statusCode),
|
2022-11-09 10:07:18 +00:00
|
|
|
zap.String("host", r.Host),
|
2021-01-14 17:39:48 +00:00
|
|
|
zap.String("request_id", GetRequestID(r.Context())),
|
2020-11-27 12:28:27 +00:00
|
|
|
zap.String("method", mux.CurrentRoute(r).GetName()),
|
2022-10-24 15:28:28 +00:00
|
|
|
zap.String("bucket", reqInfo.BucketName),
|
|
|
|
zap.String("object", reqInfo.ObjectName),
|
2020-11-27 12:28:27 +00:00
|
|
|
zap.String("description", http.StatusText(lw.statusCode)))
|
2020-08-19 23:28:16 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-13 16:56:58 +00:00
|
|
|
// GetRequestID returns the request ID from the response writer or the context.
|
2020-08-11 11:30:02 +00:00
|
|
|
func GetRequestID(v interface{}) string {
|
|
|
|
switch t := v.(type) {
|
|
|
|
case context.Context:
|
|
|
|
return GetReqInfo(t).RequestID
|
|
|
|
case http.ResponseWriter:
|
|
|
|
return t.Header().Get(hdrAmzRequestID)
|
|
|
|
default:
|
|
|
|
panic("unknown type")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-13 20:25:31 +00:00
|
|
|
// Attach adds S3 API handlers from h to r for domains with m client limit using
|
|
|
|
// center authentication and log logger.
|
2020-12-10 15:13:28 +00:00
|
|
|
func Attach(r *mux.Router, domains []string, m MaxClients, h Handler, center auth.Center, log *zap.Logger) {
|
2020-07-22 13:02:32 +00:00
|
|
|
api := r.PathPrefix(SlashSeparator).Subrouter()
|
2020-08-11 11:30:02 +00:00
|
|
|
|
2020-08-19 23:28:16 +00:00
|
|
|
api.Use(
|
|
|
|
// -- prepare request
|
|
|
|
setRequestID,
|
|
|
|
|
2022-12-23 12:28:30 +00:00
|
|
|
// -- resolve bucket to set cid in context
|
|
|
|
resolveBucket(log, h.ResolveBucket),
|
|
|
|
|
2020-08-19 23:28:16 +00:00
|
|
|
// -- logging error requests
|
2020-10-24 13:09:22 +00:00
|
|
|
logErrorResponse(log),
|
2020-08-19 23:28:16 +00:00
|
|
|
)
|
2020-08-11 11:30:02 +00:00
|
|
|
|
2020-07-22 19:48:34 +00:00
|
|
|
// Attach user authentication for all S3 routes.
|
|
|
|
AttachUserAuth(api, center, log)
|
2020-07-22 13:02:32 +00:00
|
|
|
|
2020-12-10 15:13:28 +00:00
|
|
|
buckets := make([]*mux.Router, 0, len(domains)+1)
|
|
|
|
buckets = append(buckets, api.PathPrefix("/{bucket}").Subrouter())
|
2020-07-22 13:02:32 +00:00
|
|
|
|
2020-12-10 15:13:28 +00:00
|
|
|
for _, domain := range domains {
|
|
|
|
buckets = append(buckets, api.Host("{bucket:.+}."+domain).Subrouter())
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, bucket := range buckets {
|
|
|
|
// Object operations
|
|
|
|
// HeadObject
|
2021-10-04 14:32:35 +00:00
|
|
|
bucket.Use(
|
|
|
|
// -- append CORS headers to a response for
|
|
|
|
appendCORS(h),
|
|
|
|
)
|
2022-12-23 12:28:30 +00:00
|
|
|
bucket.Methods(http.MethodOptions).HandlerFunc(m.Handle(APIStats("preflight", h.Preflight))).Name("Options")
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodHead).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("headobject", h.HeadObjectHandler))).Name("HeadObject")
|
2020-12-10 15:13:28 +00:00
|
|
|
// CopyObjectPart
|
2022-12-23 12:28:30 +00:00
|
|
|
bucket.Methods(http.MethodPut).Path("/{object:.+}").Headers(hdrAmzCopySource, "").HandlerFunc(m.Handle(APIStats("uploadpartcopy", h.UploadPartCopy))).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}").
|
2021-11-25 15:05:58 +00:00
|
|
|
Name("UploadPartCopy")
|
2020-12-10 15:13:28 +00:00
|
|
|
// PutObjectPart
|
|
|
|
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("uploadpart", h.UploadPartHandler))).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}").
|
2021-11-25 15:05:58 +00:00
|
|
|
Name("UploadPart")
|
|
|
|
// ListParts
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("listobjectparts", h.ListPartsHandler))).Queries("uploadId", "{uploadId:.*}").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("ListObjectParts")
|
|
|
|
// CompleteMultipartUpload
|
|
|
|
bucket.Methods(http.MethodPost).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("completemutipartupload", h.CompleteMultipartUploadHandler))).Queries("uploadId", "{uploadId:.*}").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("CompleteMultipartUpload")
|
2021-11-25 15:05:58 +00:00
|
|
|
// CreateMultipartUpload
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodPost).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("createmultipartupload", h.CreateMultipartUploadHandler))).Queries("uploads", "").
|
2021-11-25 15:05:58 +00:00
|
|
|
Name("CreateMultipartUpload")
|
2020-12-10 15:13:28 +00:00
|
|
|
// AbortMultipartUpload
|
|
|
|
bucket.Methods(http.MethodDelete).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("abortmultipartupload", h.AbortMultipartUploadHandler))).Queries("uploadId", "{uploadId:.*}").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("AbortMultipartUpload")
|
2021-11-25 15:05:58 +00:00
|
|
|
// ListMultipartUploads
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("listmultipartuploads", h.ListMultipartUploadsHandler))).Queries("uploads", "").
|
2021-11-25 15:05:58 +00:00
|
|
|
Name("ListMultipartUploads")
|
2022-04-13 16:56:58 +00:00
|
|
|
// GetObjectACL -- this is a dummy call.
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getobjectacl", h.GetObjectACLHandler))).Queries("acl", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetObjectACL")
|
2022-04-13 16:56:58 +00:00
|
|
|
// PutObjectACL -- this is a dummy call.
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putobjectacl", h.PutObjectACLHandler))).Queries("acl", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutObjectACL")
|
|
|
|
// GetObjectTagging
|
|
|
|
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getobjecttagging", h.GetObjectTaggingHandler))).Queries("tagging", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetObjectTagging")
|
|
|
|
// PutObjectTagging
|
|
|
|
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putobjecttagging", h.PutObjectTaggingHandler))).Queries("tagging", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutObjectTagging")
|
|
|
|
// DeleteObjectTagging
|
|
|
|
bucket.Methods(http.MethodDelete).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("deleteobjecttagging", h.DeleteObjectTaggingHandler))).Queries("tagging", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("DeleteObjectTagging")
|
|
|
|
// SelectObjectContent
|
|
|
|
bucket.Methods(http.MethodPost).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("selectobjectcontent", h.SelectObjectContentHandler))).Queries("select", "").Queries("select-type", "2").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("SelectObjectContent")
|
|
|
|
// GetObjectRetention
|
|
|
|
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getobjectretention", h.GetObjectRetentionHandler))).Queries("retention", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetObjectRetention")
|
|
|
|
// GetObjectLegalHold
|
|
|
|
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getobjectlegalhold", h.GetObjectLegalHoldHandler))).Queries("legal-hold", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetObjectLegalHold")
|
2022-05-12 21:15:08 +00:00
|
|
|
// GetObjectAttributes
|
|
|
|
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getobjectattributes", h.GetObjectAttributesHandler))).Queries("attributes", "").
|
2022-05-12 21:15:08 +00:00
|
|
|
Name("GetObjectAttributes")
|
2020-12-10 15:13:28 +00:00
|
|
|
// GetObject
|
|
|
|
bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getobject", h.GetObjectHandler))).
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetObject")
|
|
|
|
// CopyObject
|
2022-12-23 12:28:30 +00:00
|
|
|
bucket.Methods(http.MethodPut).Path("/{object:.+}").Headers(hdrAmzCopySource, "").HandlerFunc(m.Handle(APIStats("copyobject", h.CopyObjectHandler))).
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("CopyObject")
|
|
|
|
// PutObjectRetention
|
|
|
|
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putobjectretention", h.PutObjectRetentionHandler))).Queries("retention", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutObjectRetention")
|
|
|
|
// PutObjectLegalHold
|
|
|
|
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putobjectlegalhold", h.PutObjectLegalHoldHandler))).Queries("legal-hold", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutObjectLegalHold")
|
|
|
|
|
|
|
|
// PutObject
|
|
|
|
bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putobject", h.PutObjectHandler))).
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutObject")
|
|
|
|
// DeleteObject
|
|
|
|
bucket.Methods(http.MethodDelete).Path("/{object:.+}").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("deleteobject", h.DeleteObjectHandler))).
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("DeleteObject")
|
|
|
|
|
|
|
|
// Bucket operations
|
|
|
|
// GetBucketLocation
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketlocation", h.GetBucketLocationHandler))).Queries("location", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketLocation")
|
|
|
|
// GetBucketPolicy
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketpolicy", h.GetBucketPolicyHandler))).Queries("policy", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketPolicy")
|
|
|
|
// GetBucketLifecycle
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketlifecycle", h.GetBucketLifecycleHandler))).Queries("lifecycle", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketLifecycle")
|
|
|
|
// GetBucketEncryption
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketencryption", h.GetBucketEncryptionHandler))).Queries("encryption", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketEncryption")
|
2021-10-04 14:32:35 +00:00
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketcors", h.GetBucketCorsHandler))).Queries("cors", "").
|
2021-10-04 14:32:35 +00:00
|
|
|
Name("GetBucketCors")
|
|
|
|
bucket.Methods(http.MethodPut).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putbucketcors", h.PutBucketCorsHandler))).Queries("cors", "").
|
2021-10-04 14:32:35 +00:00
|
|
|
Name("PutBucketCors")
|
|
|
|
bucket.Methods(http.MethodDelete).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("deletebucketcors", h.DeleteBucketCorsHandler))).Queries("cors", "").
|
2021-10-04 14:32:35 +00:00
|
|
|
Name("DeleteBucketCors")
|
2020-12-10 15:13:28 +00:00
|
|
|
// Dummy Bucket Calls
|
|
|
|
// GetBucketACL -- this is a dummy call.
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketacl", h.GetBucketACLHandler))).Queries("acl", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketACL")
|
|
|
|
// PutBucketACL -- this is a dummy call.
|
|
|
|
bucket.Methods(http.MethodPut).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putbucketacl", h.PutBucketACLHandler))).Queries("acl", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutBucketACL")
|
2022-04-13 16:56:58 +00:00
|
|
|
// GetBucketWebsiteHandler -- this is a dummy call.
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketwebsite", h.GetBucketWebsiteHandler))).Queries("website", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketWebsite")
|
2022-04-13 16:56:58 +00:00
|
|
|
// GetBucketAccelerateHandler -- this is a dummy call.
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketaccelerate", h.GetBucketAccelerateHandler))).Queries("accelerate", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketAccelerate")
|
2022-04-13 16:56:58 +00:00
|
|
|
// GetBucketRequestPaymentHandler -- this is a dummy call.
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketrequestpayment", h.GetBucketRequestPaymentHandler))).Queries("requestPayment", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketRequestPayment")
|
2022-04-13 16:56:58 +00:00
|
|
|
// GetBucketLoggingHandler -- this is a dummy call.
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketlogging", h.GetBucketLoggingHandler))).Queries("logging", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketLogging")
|
2022-04-13 16:56:58 +00:00
|
|
|
// GetBucketLifecycleHandler -- this is a dummy call.
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketlifecycle", h.GetBucketLifecycleHandler))).Queries("lifecycle", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketLifecycle")
|
2022-04-13 16:56:58 +00:00
|
|
|
// GetBucketReplicationHandler -- this is a dummy call.
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketreplication", h.GetBucketReplicationHandler))).Queries("replication", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketReplication")
|
|
|
|
// GetBucketTaggingHandler
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbuckettagging", h.GetBucketTaggingHandler))).Queries("tagging", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketTagging")
|
|
|
|
// DeleteBucketWebsiteHandler
|
|
|
|
bucket.Methods(http.MethodDelete).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("deletebucketwebsite", h.DeleteBucketWebsiteHandler))).Queries("website", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("DeleteBucketWebsite")
|
|
|
|
// DeleteBucketTaggingHandler
|
|
|
|
bucket.Methods(http.MethodDelete).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("deletebuckettagging", h.DeleteBucketTaggingHandler))).Queries("tagging", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("DeleteBucketTagging")
|
|
|
|
|
|
|
|
// GetBucketObjectLockConfig
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketobjectlockconfiguration", h.GetBucketObjectLockConfigHandler))).Queries("object-lock", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketObjectLockConfig")
|
|
|
|
// GetBucketVersioning
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketversioning", h.GetBucketVersioningHandler))).Queries("versioning", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketVersioning")
|
|
|
|
// GetBucketNotification
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("getbucketnotification", h.GetBucketNotificationHandler))).Queries("notification", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("GetBucketNotification")
|
|
|
|
// ListenBucketNotification
|
2022-12-23 12:28:30 +00:00
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(APIStats("listenbucketnotification", h.ListenBucketNotificationHandler)).Queries("events", "{events:.*}").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("ListenBucketNotification")
|
|
|
|
// ListObjectsV2M
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("listobjectsv2M", h.ListObjectsV2MHandler))).Queries("list-type", "2", "metadata", "true").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("ListObjectsV2M")
|
|
|
|
// ListObjectsV2
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("listobjectsv2", h.ListObjectsV2Handler))).Queries("list-type", "2").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("ListObjectsV2")
|
|
|
|
// ListBucketVersions
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("listbucketversions", h.ListBucketObjectVersionsHandler))).Queries("versions", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("ListBucketVersions")
|
|
|
|
// ListObjectsV1 (Legacy)
|
|
|
|
bucket.Methods(http.MethodGet).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("listobjectsv1", h.ListObjectsV1Handler))).
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("ListObjectsV1")
|
|
|
|
// PutBucketLifecycle
|
|
|
|
bucket.Methods(http.MethodPut).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putbucketlifecycle", h.PutBucketLifecycleHandler))).Queries("lifecycle", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutBucketLifecycle")
|
|
|
|
// PutBucketEncryption
|
|
|
|
bucket.Methods(http.MethodPut).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putbucketencryption", h.PutBucketEncryptionHandler))).Queries("encryption", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutBucketEncryption")
|
|
|
|
|
|
|
|
// PutBucketPolicy
|
|
|
|
bucket.Methods(http.MethodPut).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putbucketpolicy", h.PutBucketPolicyHandler))).Queries("policy", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutBucketPolicy")
|
|
|
|
|
|
|
|
// PutBucketObjectLockConfig
|
|
|
|
bucket.Methods(http.MethodPut).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putbucketobjectlockconfig", h.PutBucketObjectLockConfigHandler))).Queries("object-lock", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutBucketObjectLockConfig")
|
|
|
|
// PutBucketTaggingHandler
|
|
|
|
bucket.Methods(http.MethodPut).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putbuckettagging", h.PutBucketTaggingHandler))).Queries("tagging", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutBucketTagging")
|
|
|
|
// PutBucketVersioning
|
|
|
|
bucket.Methods(http.MethodPut).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putbucketversioning", h.PutBucketVersioningHandler))).Queries("versioning", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutBucketVersioning")
|
|
|
|
// PutBucketNotification
|
|
|
|
bucket.Methods(http.MethodPut).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("putbucketnotification", h.PutBucketNotificationHandler))).Queries("notification", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("PutBucketNotification")
|
2021-06-23 20:21:15 +00:00
|
|
|
// CreateBucket
|
2020-12-10 15:13:28 +00:00
|
|
|
bucket.Methods(http.MethodPut).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("createbucket", h.CreateBucketHandler))).
|
2021-06-23 20:21:15 +00:00
|
|
|
Name("CreateBucket")
|
2020-12-10 15:13:28 +00:00
|
|
|
// HeadBucket
|
|
|
|
bucket.Methods(http.MethodHead).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("headbucket", h.HeadBucketHandler))).
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("HeadBucket")
|
|
|
|
// PostPolicy
|
|
|
|
bucket.Methods(http.MethodPost).HeadersRegexp(hdrContentType, "multipart/form-data*").HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("postobject", h.PostObject))).
|
2021-08-30 19:44:53 +00:00
|
|
|
Name("PostObject")
|
2020-12-10 15:13:28 +00:00
|
|
|
// DeleteMultipleObjects
|
|
|
|
bucket.Methods(http.MethodPost).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("deletemultipleobjects", h.DeleteMultipleObjectsHandler))).Queries("delete", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("DeleteMultipleObjects")
|
|
|
|
// DeleteBucketPolicy
|
|
|
|
bucket.Methods(http.MethodDelete).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("deletebucketpolicy", h.DeleteBucketPolicyHandler))).Queries("policy", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("DeleteBucketPolicy")
|
|
|
|
// DeleteBucketLifecycle
|
|
|
|
bucket.Methods(http.MethodDelete).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("deletebucketlifecycle", h.DeleteBucketLifecycleHandler))).Queries("lifecycle", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("DeleteBucketLifecycle")
|
|
|
|
// DeleteBucketEncryption
|
|
|
|
bucket.Methods(http.MethodDelete).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("deletebucketencryption", h.DeleteBucketEncryptionHandler))).Queries("encryption", "").
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("DeleteBucketEncryption")
|
|
|
|
// DeleteBucket
|
|
|
|
bucket.Methods(http.MethodDelete).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("deletebucket", h.DeleteBucketHandler))).
|
2020-12-10 15:13:28 +00:00
|
|
|
Name("DeleteBucket")
|
|
|
|
}
|
2020-07-22 13:02:32 +00:00
|
|
|
// Root operation
|
|
|
|
|
|
|
|
// ListBuckets
|
|
|
|
api.Methods(http.MethodGet).Path(SlashSeparator).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("listbuckets", h.ListBucketsHandler))).
|
2020-08-11 11:30:02 +00:00
|
|
|
Name("ListBuckets")
|
2020-07-22 13:02:32 +00:00
|
|
|
|
|
|
|
// S3 browser with signature v4 adds '//' for ListBuckets request, so rather
|
|
|
|
// than failing with UnknownAPIRequest we simply handle it for now.
|
|
|
|
api.Methods(http.MethodGet).Path(SlashSeparator + SlashSeparator).HandlerFunc(
|
2022-12-23 12:28:30 +00:00
|
|
|
m.Handle(APIStats("listbuckets", h.ListBucketsHandler))).
|
2020-08-11 11:30:02 +00:00
|
|
|
Name("ListBuckets")
|
2020-07-22 13:02:32 +00:00
|
|
|
|
2022-04-13 16:56:58 +00:00
|
|
|
// If none of the routes match, add default error handler routes
|
2022-12-23 12:28:30 +00:00
|
|
|
api.NotFoundHandler = APIStats("notfound", errorResponseHandler)
|
|
|
|
api.MethodNotAllowedHandler = APIStats("methodnotallowed", errorResponseHandler)
|
2020-07-22 13:02:32 +00:00
|
|
|
}
|