mirror of
https://github.com/versity/versitygw.git
synced 2026-08-27 19:36:57 +00:00
feat: migrate Fiber to v3.3.0
Fixes #2180 Fixes #2181 Migrate the gateway from Fiber v2 to Fiber v3.3.0 and update the affected server, middleware, handler, controller, and test code for the new APIs. Replace the deprecated Fiber filesystem middleware used by the WebUI with the Fiber v3 static middleware, serving the embedded WebUI assets from an fs.Sub filesystem. Fix the request header limit handling regression by adding a temporary handler for Fiber v3/fasthttp small-buffer errors so oversized request headers return the expected regulated S3 error response. Fix the debuglogger panic by reworking the boxed key/value formatter used for debug request and response dumps. The formatter now handles long header keys and values without producing invalid wrap widths, negative padding, or out-of-range string slices.
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
package s3api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/metrics"
|
||||
|
||||
+18
-18
@@ -19,9 +19,9 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/gofiber/fiber/v3/middleware/logger"
|
||||
"github.com/gofiber/fiber/v3/middleware/recover"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
@@ -57,17 +57,15 @@ func NewAdminServer(be backend.Backend, root middlewares.RootUserConfig, region
|
||||
}
|
||||
|
||||
app := fiber.New(fiber.Config{
|
||||
AppName: "versitygw",
|
||||
ServerHeader: "VERSITYGW",
|
||||
Network: fiber.NetworkTCP,
|
||||
DisableStartupMessage: true,
|
||||
ErrorHandler: globalErrorHandler,
|
||||
Concurrency: server.maxConnections,
|
||||
AppName: "versitygw",
|
||||
ServerHeader: "VERSITYGW",
|
||||
ErrorHandler: globalErrorHandler,
|
||||
Concurrency: server.maxConnections,
|
||||
})
|
||||
|
||||
server.app = app
|
||||
|
||||
app.Use(recover.New(
|
||||
app.Use("*", recover.New(
|
||||
recover.Config{
|
||||
EnableStackTrace: true,
|
||||
StackTraceHandler: stackTraceHandler,
|
||||
@@ -75,21 +73,21 @@ func NewAdminServer(be backend.Backend, root middlewares.RootUserConfig, region
|
||||
|
||||
// Logging middlewares
|
||||
if !server.quiet {
|
||||
app.Use(logger.New(logger.Config{
|
||||
app.Use("*", logger.New(logger.Config{
|
||||
Format: "${time} | adm | ${status} | ${latency} | ${ip} | ${method} | ${path} | ${error} | ${queryParams}\n",
|
||||
}))
|
||||
}
|
||||
// initialize requestId middleware
|
||||
app.Use(middlewares.RequestIDs())
|
||||
app.Use("*", middlewares.RequestIDs())
|
||||
|
||||
// initialize total requests cap limiter middleware
|
||||
app.Use(middlewares.RateLimiter(server.maxRequests, nil, l))
|
||||
app.Use("*", middlewares.RateLimiter(server.maxRequests, nil, l))
|
||||
|
||||
app.Use(controllers.WrapMiddleware(middlewares.DecodeURL, l, nil))
|
||||
app.Use("*", controllers.WrapMiddleware(middlewares.DecodeURL, l, nil))
|
||||
|
||||
// initialize the debug logger in debug mode
|
||||
if debuglogger.IsDebugEnabled() {
|
||||
app.Use(middlewares.DebugLogger())
|
||||
app.Use("*", middlewares.DebugLogger())
|
||||
}
|
||||
|
||||
server.router.Init(app, be, iam, l, root, region, server.debug, server.corsAllowOrigin)
|
||||
@@ -151,9 +149,9 @@ func (sa *S3AdminServer) ServeMultiPort(ports []string) error {
|
||||
var err error
|
||||
|
||||
if sa.CertStorage != nil {
|
||||
ln, err = utils.NewMultiAddrTLSListener(sa.app.Config().Network, portSpec, sa.CertStorage.GetCertificate, utils.ListenerOptions{SocketPerm: sa.socketPerm})
|
||||
ln, err = utils.NewMultiAddrTLSListener(fiber.NetworkTCP, portSpec, sa.CertStorage.GetCertificate, utils.ListenerOptions{SocketPerm: sa.socketPerm})
|
||||
} else {
|
||||
ln, err = utils.NewMultiAddrListener(sa.app.Config().Network, portSpec, utils.ListenerOptions{SocketPerm: sa.socketPerm})
|
||||
ln, err = utils.NewMultiAddrListener(fiber.NetworkTCP, portSpec, utils.ListenerOptions{SocketPerm: sa.socketPerm})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -170,7 +168,9 @@ func (sa *S3AdminServer) ServeMultiPort(ports []string) error {
|
||||
// Combine all listeners
|
||||
finalListener := utils.NewMultiListener(listeners...)
|
||||
|
||||
return sa.app.Listener(finalListener)
|
||||
return sa.app.Listener(finalListener, fiber.ListenConfig{
|
||||
DisableStartupMessage: true,
|
||||
})
|
||||
}
|
||||
|
||||
// ShutDown gracefully shuts down the server with a context timeout
|
||||
|
||||
+13
-13
@@ -19,7 +19,7 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
@@ -38,9 +38,9 @@ func NewAdminController(iam auth.IAMService, be backend.Backend, l s3log.AuditLo
|
||||
return AdminController{iam: iam, be: be, l: l, s3api: s3api}
|
||||
}
|
||||
|
||||
func (c AdminController) CreateUser(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c AdminController) CreateUser(ctx fiber.Ctx) (*Response, error) {
|
||||
var usr auth.Account
|
||||
err := xml.Unmarshal(ctx.Body(), &usr)
|
||||
err := xml.Unmarshal(ctx.BodyRaw(), &usr)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{},
|
||||
@@ -71,7 +71,7 @@ func (c AdminController) CreateUser(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c AdminController) UpdateUser(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c AdminController) UpdateUser(ctx fiber.Ctx) (*Response, error) {
|
||||
access := ctx.Query("access")
|
||||
if access == "" {
|
||||
return &Response{
|
||||
@@ -80,7 +80,7 @@ func (c AdminController) UpdateUser(ctx *fiber.Ctx) (*Response, error) {
|
||||
}
|
||||
|
||||
var props auth.MutableProps
|
||||
if err := xml.Unmarshal(ctx.Body(), &props); err != nil {
|
||||
if err := xml.Unmarshal(ctx.BodyRaw(), &props); err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{},
|
||||
}, s3err.GetAPIError(s3err.ErrMalformedXML)
|
||||
@@ -109,7 +109,7 @@ func (c AdminController) UpdateUser(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c AdminController) DeleteUser(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c AdminController) DeleteUser(ctx fiber.Ctx) (*Response, error) {
|
||||
access := ctx.Query("access")
|
||||
if access == "" {
|
||||
return &Response{
|
||||
@@ -123,7 +123,7 @@ func (c AdminController) DeleteUser(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c AdminController) ListUsers(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c AdminController) ListUsers(ctx fiber.Ctx) (*Response, error) {
|
||||
accs, err := c.iam.ListUserAccounts()
|
||||
return &Response{
|
||||
Data: auth.ListUserAccountsResult{Accounts: accs},
|
||||
@@ -131,7 +131,7 @@ func (c AdminController) ListUsers(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c AdminController) ChangeBucketOwner(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c AdminController) ChangeBucketOwner(ctx fiber.Ctx) (*Response, error) {
|
||||
owner := ctx.Query("owner")
|
||||
bucket := ctx.Query("bucket")
|
||||
|
||||
@@ -147,14 +147,14 @@ func (c AdminController) ChangeBucketOwner(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, s3err.GetAPIError(s3err.ErrAdminUserNotFound)
|
||||
}
|
||||
|
||||
err = c.be.ChangeBucketOwner(ctx.Context(), bucket, owner)
|
||||
err = c.be.ChangeBucketOwner(ctx.RequestCtx(), bucket, owner)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{},
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c AdminController) ListBuckets(ctx *fiber.Ctx) (*Response, error) {
|
||||
buckets, err := c.be.ListBucketsAndOwners(ctx.Context())
|
||||
func (c AdminController) ListBuckets(ctx fiber.Ctx) (*Response, error) {
|
||||
buckets, err := c.be.ListBucketsAndOwners(ctx.RequestCtx())
|
||||
return &Response{
|
||||
Data: s3response.ListBucketsResult{
|
||||
Buckets: buckets,
|
||||
@@ -163,7 +163,7 @@ func (c AdminController) ListBuckets(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c AdminController) CreateBucket(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c AdminController) CreateBucket(ctx fiber.Ctx) (*Response, error) {
|
||||
owner := ctx.Get("x-vgw-owner")
|
||||
if owner == "" {
|
||||
return &Response{
|
||||
@@ -183,7 +183,7 @@ func (c AdminController) CreateBucket(ctx *fiber.Ctx) (*Response, error) {
|
||||
}
|
||||
|
||||
// store the owner access key id in context
|
||||
ctx.Context().SetUserValue("bucket-owner", acc)
|
||||
ctx.RequestCtx().SetUserValue("bucket-owner", acc)
|
||||
|
||||
_, err = c.s3api.CreateBucket(ctx)
|
||||
if err != nil {
|
||||
|
||||
+11
-11
@@ -21,7 +21,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
@@ -76,7 +76,7 @@ func New(be backend.Backend, iam auth.IAMService, logger s3log.AuditLogger, evs
|
||||
}
|
||||
}
|
||||
|
||||
func (c S3ApiController) getAclHeaderValue(ctx *fiber.Ctx, key string, defaultValues ...string) string {
|
||||
func (c S3ApiController) getAclHeaderValue(ctx fiber.Ctx, key string, defaultValues ...string) string {
|
||||
if c.disableACL {
|
||||
return ""
|
||||
}
|
||||
@@ -86,7 +86,7 @@ func (c S3ApiController) getAclHeaderValue(ctx *fiber.Ctx, key string, defaultVa
|
||||
|
||||
// Returns MethodNotAllowed for unmatched routes
|
||||
func (c S3ApiController) HandleErrorRoute(err error) Controller {
|
||||
return func(ctx *fiber.Ctx) (*Response, error) {
|
||||
return func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{}, err
|
||||
}
|
||||
}
|
||||
@@ -121,11 +121,11 @@ type Services struct {
|
||||
}
|
||||
|
||||
// Controller is the type definition for an s3api controller
|
||||
type Controller func(ctx *fiber.Ctx) (*Response, error)
|
||||
type Controller func(ctx fiber.Ctx) (*Response, error)
|
||||
|
||||
// ProcessHandlers groups a controller and multiple middlewares into a single fiber handler
|
||||
func ProcessHandlers(controller Controller, s3action string, svc *Services, handlers ...fiber.Handler) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
// if skip locals is set, skip to the next rout handler
|
||||
if utils.ContextKeySkip.IsSet(ctx) {
|
||||
utils.ContextKeySkip.Delete(ctx)
|
||||
@@ -135,7 +135,7 @@ func ProcessHandlers(controller Controller, s3action string, svc *Services, hand
|
||||
for _, handler := range handlers {
|
||||
err := handler(ctx)
|
||||
if err != nil {
|
||||
return ProcessController(ctx, func(ctx *fiber.Ctx) (*Response, error) {
|
||||
return ProcessController(ctx, func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{},
|
||||
}, err
|
||||
@@ -150,7 +150,7 @@ func ProcessHandlers(controller Controller, s3action string, svc *Services, hand
|
||||
// WrapMiddleware executes the given middleware and handles sending the audit logs
|
||||
// and metrics. It also handles the error parsing
|
||||
func WrapMiddleware(handler fiber.Handler, logger s3log.AuditLogger, mm metrics.Manager) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
requestID, hostID := utils.EnsureRequestIDs(ctx)
|
||||
|
||||
err := handler(ctx)
|
||||
@@ -159,7 +159,7 @@ func WrapMiddleware(handler fiber.Handler, logger s3log.AuditLogger, mm metrics.
|
||||
mm.Send(ctx, err, metrics.ActionUndetected, 0, 0)
|
||||
}
|
||||
if logger != nil {
|
||||
logger.Log(ctx, err, ctx.Body(), s3log.LogMeta{
|
||||
logger.Log(ctx, err, ctx.BodyRaw(), s3log.LogMeta{
|
||||
Action: metrics.ActionUndetected,
|
||||
})
|
||||
}
|
||||
@@ -187,7 +187,7 @@ func WrapMiddleware(handler fiber.Handler, logger s3log.AuditLogger, mm metrics.
|
||||
|
||||
// ProcessController executes the given s3api controller and handles the metrics
|
||||
// access logs and s3 events
|
||||
func ProcessController(ctx *fiber.Ctx, controller Controller, s3action string, svc *Services) error {
|
||||
func ProcessController(ctx fiber.Ctx, controller Controller, s3action string, svc *Services) error {
|
||||
response, err := controller(ctx)
|
||||
|
||||
// Set the response headers
|
||||
@@ -342,7 +342,7 @@ func ProcessController(ctx *fiber.Ctx, controller Controller, s3action string, s
|
||||
return ctx.Status(opts.Status).Send(res)
|
||||
}
|
||||
|
||||
func ensureExposeMetaHeaders(ctx *fiber.Ctx) {
|
||||
func ensureExposeMetaHeaders(ctx fiber.Ctx) {
|
||||
// Only attempt to modify expose headers when CORS is actually in use.
|
||||
if len(ctx.Response().Header.Peek("Access-Control-Allow-Origin")) == 0 {
|
||||
return
|
||||
@@ -414,7 +414,7 @@ func ensureExposeMetaHeaders(ctx *fiber.Ctx) {
|
||||
}
|
||||
|
||||
// Sets the response headers
|
||||
func SetResponseHeaders(ctx *fiber.Ctx, headers map[string]*string) {
|
||||
func SetResponseHeaders(ctx fiber.Ctx, headers map[string]*string) {
|
||||
if headers == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/valyala/fasthttp"
|
||||
"github.com/versity/versitygw/auth"
|
||||
@@ -95,7 +95,7 @@ type ctxInputs struct {
|
||||
func testController(t *testing.T, ctrl Controller, resp *Response, expectedErr error, input ctxInputs) {
|
||||
app := fiber.New()
|
||||
|
||||
app.Post("/:bucket/*", func(ctx *fiber.Ctx) error {
|
||||
app.Post("/:bucket/*", func(ctx fiber.Ctx) error {
|
||||
// set the request body
|
||||
ctx.Request().SetBody(input.body)
|
||||
// set the request locals
|
||||
@@ -259,23 +259,23 @@ func TestEnsureExposeMetaHeaders_AddsActualMetaHeaderNames(t *testing.T) {
|
||||
type mockAuditLogger struct {
|
||||
}
|
||||
|
||||
func (m *mockAuditLogger) Log(_ *fiber.Ctx, _ error, _ []byte, _ s3log.LogMeta) {}
|
||||
func (m *mockAuditLogger) HangUp() error { return nil }
|
||||
func (m *mockAuditLogger) Shutdown() error { return nil }
|
||||
func (m *mockAuditLogger) Log(_ fiber.Ctx, _ error, _ []byte, _ s3log.LogMeta) {}
|
||||
func (m *mockAuditLogger) HangUp() error { return nil }
|
||||
func (m *mockAuditLogger) Shutdown() error { return nil }
|
||||
|
||||
// mock S3 event sender
|
||||
type mockEvSender struct {
|
||||
}
|
||||
|
||||
func (m *mockEvSender) SendEvent(_ *fiber.Ctx, _ s3event.EventMeta) {}
|
||||
func (m *mockEvSender) Close() error { return nil }
|
||||
func (m *mockEvSender) SendEvent(_ fiber.Ctx, _ s3event.EventMeta) {}
|
||||
func (m *mockEvSender) Close() error { return nil }
|
||||
|
||||
// mock metrics manager
|
||||
|
||||
type mockMetricsManager struct{}
|
||||
|
||||
func (m *mockMetricsManager) Send(_ *fiber.Ctx, _ error, _ string, _ int64, _ int) {}
|
||||
func (m *mockMetricsManager) Close() {}
|
||||
func (m *mockMetricsManager) Send(_ fiber.Ctx, _ error, _ string, _ int64, _ int) {}
|
||||
func (m *mockMetricsManager) Close() {}
|
||||
|
||||
func TestProcessController(t *testing.T) {
|
||||
payload, err := xml.Marshal(s3response.Bucket{
|
||||
@@ -308,7 +308,7 @@ func TestProcessController(t *testing.T) {
|
||||
name: "no services successful response",
|
||||
args: args{
|
||||
svc: &Services{},
|
||||
controller: func(ctx *fiber.Ctx) (*Response, error) {
|
||||
controller: func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{}, nil
|
||||
},
|
||||
},
|
||||
@@ -320,7 +320,7 @@ func TestProcessController(t *testing.T) {
|
||||
name: "handle api error",
|
||||
args: args{
|
||||
svc: services,
|
||||
controller: func(ctx *fiber.Ctx) (*Response, error) {
|
||||
controller: func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{}, s3err.GetAPIError(s3err.ErrInvalidRequest)
|
||||
},
|
||||
},
|
||||
@@ -333,7 +333,7 @@ func TestProcessController(t *testing.T) {
|
||||
name: "handle custom error",
|
||||
args: args{
|
||||
svc: services,
|
||||
controller: func(ctx *fiber.Ctx) (*Response, error) {
|
||||
controller: func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{}, errors.New("custom error")
|
||||
},
|
||||
},
|
||||
@@ -346,7 +346,7 @@ func TestProcessController(t *testing.T) {
|
||||
name: "body parsing fails",
|
||||
args: args{
|
||||
svc: services,
|
||||
controller: func(ctx *fiber.Ctx) (*Response, error) {
|
||||
controller: func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{
|
||||
Data: make(chan int),
|
||||
}, nil
|
||||
@@ -361,7 +361,7 @@ func TestProcessController(t *testing.T) {
|
||||
name: "no data payload",
|
||||
args: args{
|
||||
svc: services,
|
||||
controller: func(ctx *fiber.Ctx) (*Response, error) {
|
||||
controller: func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
ObjectCount: 2,
|
||||
@@ -377,7 +377,7 @@ func TestProcessController(t *testing.T) {
|
||||
name: "should return 204 http status",
|
||||
args: args{
|
||||
svc: services,
|
||||
controller: func(ctx *fiber.Ctx) (*Response, error) {
|
||||
controller: func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
Status: http.StatusNoContent,
|
||||
@@ -393,7 +393,7 @@ func TestProcessController(t *testing.T) {
|
||||
name: "already encoded payload",
|
||||
args: args{
|
||||
svc: services,
|
||||
controller: func(ctx *fiber.Ctx) (*Response, error) {
|
||||
controller: func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{
|
||||
Data: []byte("encoded_data"),
|
||||
}, nil
|
||||
@@ -411,7 +411,7 @@ func TestProcessController(t *testing.T) {
|
||||
name: "should set response headers",
|
||||
args: args{
|
||||
svc: services,
|
||||
controller: func(ctx *fiber.Ctx) (*Response, error) {
|
||||
controller: func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{
|
||||
Headers: map[string]*string{
|
||||
"X-Amz-My-Custom-Header": utils.GetStringPtr("my_value"),
|
||||
@@ -432,7 +432,7 @@ func TestProcessController(t *testing.T) {
|
||||
name: "large payload: should return internal error",
|
||||
args: args{
|
||||
svc: services,
|
||||
controller: func(ctx *fiber.Ctx) (*Response, error) {
|
||||
controller: func(ctx fiber.Ctx) (*Response, error) {
|
||||
type Item struct {
|
||||
Value string `xml:"value"`
|
||||
}
|
||||
@@ -475,7 +475,7 @@ func TestProcessController(t *testing.T) {
|
||||
name: "not encoded payload",
|
||||
args: args{
|
||||
svc: services,
|
||||
controller: func(ctx *fiber.Ctx) (*Response, error) {
|
||||
controller: func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{
|
||||
Data: s3response.Bucket{
|
||||
Name: "something",
|
||||
@@ -553,10 +553,10 @@ func TestProcessHandlers(t *testing.T) {
|
||||
name: "handler returns error",
|
||||
args: args{
|
||||
handlers: []fiber.Handler{
|
||||
func(ctx *fiber.Ctx) error {
|
||||
func(ctx fiber.Ctx) error {
|
||||
return nil
|
||||
},
|
||||
func(ctx *fiber.Ctx) error {
|
||||
func(ctx fiber.Ctx) error {
|
||||
return s3err.GetAPIError(s3err.ErrAccessDenied)
|
||||
},
|
||||
},
|
||||
@@ -570,15 +570,15 @@ func TestProcessHandlers(t *testing.T) {
|
||||
name: "should process the controller",
|
||||
args: args{
|
||||
handlers: []fiber.Handler{
|
||||
func(ctx *fiber.Ctx) error {
|
||||
func(ctx fiber.Ctx) error {
|
||||
return nil
|
||||
},
|
||||
func(ctx *fiber.Ctx) error {
|
||||
func(ctx fiber.Ctx) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
svc: &Services{},
|
||||
controller: func(ctx *fiber.Ctx) (*Response, error) {
|
||||
controller: func(ctx fiber.Ctx) (*Response, error) {
|
||||
return &Response{
|
||||
Data: s3response.Checksum{
|
||||
CRC32: utils.GetStringPtr("crc32"),
|
||||
@@ -597,7 +597,7 @@ func TestProcessHandlers(t *testing.T) {
|
||||
|
||||
app := fiber.New()
|
||||
|
||||
app.Post("/:bucket/*", func(ctx *fiber.Ctx) error {
|
||||
app.Post("/:bucket/*", func(ctx fiber.Ctx) error {
|
||||
utils.ContextKeyRequestID.Set(ctx, testRequestID)
|
||||
utils.ContextKeyHostID.Set(ctx, testHostID)
|
||||
|
||||
@@ -620,7 +620,7 @@ func TestProcessHandlers(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
app.All("*", func(ctx *fiber.Ctx) error {
|
||||
app.All("*", func(ctx fiber.Ctx) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -649,7 +649,7 @@ func TestWrapMiddleware(t *testing.T) {
|
||||
{
|
||||
name: "handler returns no error",
|
||||
args: args{
|
||||
handler: func(ctx *fiber.Ctx) error {
|
||||
handler: func(ctx fiber.Ctx) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@@ -657,7 +657,7 @@ func TestWrapMiddleware(t *testing.T) {
|
||||
{
|
||||
name: "handler returns api error",
|
||||
args: args{
|
||||
handler: func(ctx *fiber.Ctx) error {
|
||||
handler: func(ctx fiber.Ctx) error {
|
||||
return s3err.GetAPIError(s3err.ErrAclNotSupported)
|
||||
},
|
||||
mm: &mockMetricsManager{},
|
||||
@@ -670,7 +670,7 @@ func TestWrapMiddleware(t *testing.T) {
|
||||
{
|
||||
name: "handler returns custom error",
|
||||
args: args{
|
||||
handler: func(ctx *fiber.Ctx) error {
|
||||
handler: func(ctx fiber.Ctx) error {
|
||||
return errors.New("custom error")
|
||||
},
|
||||
},
|
||||
@@ -684,7 +684,7 @@ func TestWrapMiddleware(t *testing.T) {
|
||||
mdlwr := WrapMiddleware(tt.args.handler, tt.args.logger, tt.args.mm)
|
||||
app := fiber.New()
|
||||
|
||||
app.Post("/:bucket/*", func(ctx *fiber.Ctx) error {
|
||||
app.Post("/:bucket/*", func(ctx fiber.Ctx) error {
|
||||
utils.ContextKeyRequestID.Set(ctx, testRequestID)
|
||||
utils.ContextKeyHostID.Set(ctx, testHostID)
|
||||
|
||||
@@ -700,7 +700,7 @@ func TestWrapMiddleware(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
app.All("*", func(ctx *fiber.Ctx) error {
|
||||
app.All("*", func(ctx fiber.Ctx) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
|
||||
@@ -17,19 +17,19 @@ package controllers
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
)
|
||||
|
||||
func (c S3ApiController) DeleteBucketTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) DeleteBucketTagging(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
IsBucketPublic := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -49,7 +49,7 @@ func (c S3ApiController) DeleteBucketTagging(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.DeleteBucketTagging(ctx.Context(), bucket)
|
||||
err = c.be.DeleteBucketTagging(ctx.RequestCtx(), bucket)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -58,13 +58,13 @@ func (c S3ApiController) DeleteBucketTagging(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) DeleteBucketOwnershipControls(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) DeleteBucketOwnershipControls(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -83,7 +83,7 @@ func (c S3ApiController) DeleteBucketOwnershipControls(ctx *fiber.Ctx) (*Respons
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.DeleteBucketOwnershipControls(ctx.Context(), bucket)
|
||||
err = c.be.DeleteBucketOwnershipControls(ctx.RequestCtx(), bucket)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -92,13 +92,13 @@ func (c S3ApiController) DeleteBucketOwnershipControls(ctx *fiber.Ctx) (*Respons
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) DeleteBucketPolicy(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) DeleteBucketPolicy(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -117,7 +117,7 @@ func (c S3ApiController) DeleteBucketPolicy(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.DeleteBucketPolicy(ctx.Context(), bucket)
|
||||
err = c.be.DeleteBucketPolicy(ctx.RequestCtx(), bucket)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -126,14 +126,14 @@ func (c S3ApiController) DeleteBucketPolicy(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) DeleteBucketCors(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) DeleteBucketCors(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
IsBucketPublic := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -153,7 +153,7 @@ func (c S3ApiController) DeleteBucketCors(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.DeleteBucketCors(ctx.Context(), bucket)
|
||||
err = c.be.DeleteBucketCors(ctx.RequestCtx(), bucket)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -162,14 +162,14 @@ func (c S3ApiController) DeleteBucketCors(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) DeleteBucketWebsite(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) DeleteBucketWebsite(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
IsBucketPublic := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -189,7 +189,7 @@ func (c S3ApiController) DeleteBucketWebsite(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.DeleteBucketWebsite(ctx.Context(), bucket)
|
||||
err = c.be.DeleteBucketWebsite(ctx.RequestCtx(), bucket)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -198,14 +198,14 @@ func (c S3ApiController) DeleteBucketWebsite(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) DeleteBucket(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) DeleteBucket(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
IsBucketPublic := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -225,7 +225,7 @@ func (c S3ApiController) DeleteBucket(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.DeleteBucket(ctx.Context(), bucket)
|
||||
err = c.be.DeleteBucket(ctx.RequestCtx(), bucket)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
|
||||
@@ -19,20 +19,20 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3response"
|
||||
)
|
||||
|
||||
func (c S3ApiController) GetBucketTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetBucketTagging(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -51,7 +51,7 @@ func (c S3ApiController) GetBucketTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
tags, err := c.be.GetBucketTagging(ctx.Context(), bucket)
|
||||
tags, err := c.be.GetBucketTagging(ctx.RequestCtx(), bucket)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -78,14 +78,14 @@ func (c S3ApiController) GetBucketTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetBucketOwnershipControls(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetBucketOwnershipControls(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -104,7 +104,7 @@ func (c S3ApiController) GetBucketOwnershipControls(ctx *fiber.Ctx) (*Response,
|
||||
}, err
|
||||
}
|
||||
|
||||
data, err := c.be.GetBucketOwnershipControls(ctx.Context(), bucket)
|
||||
data, err := c.be.GetBucketOwnershipControls(ctx.RequestCtx(), bucket)
|
||||
return &Response{
|
||||
Data: s3response.OwnershipControls{
|
||||
Rules: []types.OwnershipControlsRule{
|
||||
@@ -119,14 +119,14 @@ func (c S3ApiController) GetBucketOwnershipControls(ctx *fiber.Ctx) (*Response,
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetBucketVersioning(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetBucketVersioning(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -153,7 +153,7 @@ func (c S3ApiController) GetBucketVersioning(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
data, err := c.be.GetBucketVersioning(ctx.Context(), bucket)
|
||||
data, err := c.be.GetBucketVersioning(ctx.RequestCtx(), bucket)
|
||||
return &Response{
|
||||
Data: data,
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -162,14 +162,14 @@ func (c S3ApiController) GetBucketVersioning(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetBucketCors(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetBucketCors(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -188,7 +188,7 @@ func (c S3ApiController) GetBucketCors(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
data, err := c.be.GetBucketCors(ctx.Context(), bucket)
|
||||
data, err := c.be.GetBucketCors(ctx.RequestCtx(), bucket)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -206,14 +206,14 @@ func (c S3ApiController) GetBucketCors(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetBucketWebsite(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetBucketWebsite(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -232,7 +232,7 @@ func (c S3ApiController) GetBucketWebsite(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
data, err := c.be.GetBucketWebsite(ctx.Context(), bucket)
|
||||
data, err := c.be.GetBucketWebsite(ctx.RequestCtx(), bucket)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -250,14 +250,14 @@ func (c S3ApiController) GetBucketWebsite(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetBucketPolicy(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetBucketPolicy(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -276,7 +276,7 @@ func (c S3ApiController) GetBucketPolicy(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
data, err := c.be.GetBucketPolicy(ctx.Context(), bucket)
|
||||
data, err := c.be.GetBucketPolicy(ctx.RequestCtx(), bucket)
|
||||
return &Response{
|
||||
Data: data,
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -285,14 +285,14 @@ func (c S3ApiController) GetBucketPolicy(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetBucketPolicyStatus(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetBucketPolicyStatus(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -311,7 +311,7 @@ func (c S3ApiController) GetBucketPolicyStatus(ctx *fiber.Ctx) (*Response, error
|
||||
}, err
|
||||
}
|
||||
|
||||
policyRaw, err := c.be.GetBucketPolicy(ctx.Context(), bucket)
|
||||
policyRaw, err := c.be.GetBucketPolicy(ctx.RequestCtx(), bucket)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -340,7 +340,7 @@ func (c S3ApiController) GetBucketPolicyStatus(ctx *fiber.Ctx) (*Response, error
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c S3ApiController) ListObjectVersions(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) ListObjectVersions(ctx fiber.Ctx) (*Response, error) {
|
||||
// url values
|
||||
bucket := ctx.Params("bucket")
|
||||
prefix := ctx.Query("prefix")
|
||||
@@ -354,7 +354,7 @@ func (c S3ApiController) ListObjectVersions(ctx *fiber.Ctx) (*Response, error) {
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -382,7 +382,7 @@ func (c S3ApiController) ListObjectVersions(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
data, err := c.be.ListObjectVersions(ctx.Context(),
|
||||
data, err := c.be.ListObjectVersions(ctx.RequestCtx(),
|
||||
&s3.ListObjectVersionsInput{
|
||||
Bucket: &bucket,
|
||||
Delimiter: &delimiter,
|
||||
@@ -399,7 +399,7 @@ func (c S3ApiController) ListObjectVersions(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetObjectLockConfiguration(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetObjectLockConfiguration(ctx fiber.Ctx) (*Response, error) {
|
||||
// url values
|
||||
bucket := ctx.Params("bucket")
|
||||
// context keys
|
||||
@@ -408,7 +408,7 @@ func (c S3ApiController) GetObjectLockConfiguration(ctx *fiber.Ctx) (*Response,
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -427,7 +427,7 @@ func (c S3ApiController) GetObjectLockConfiguration(ctx *fiber.Ctx) (*Response,
|
||||
}, err
|
||||
}
|
||||
|
||||
data, err := c.be.GetObjectLockConfiguration(ctx.Context(), bucket)
|
||||
data, err := c.be.GetObjectLockConfiguration(ctx.RequestCtx(), bucket)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -445,7 +445,7 @@ func (c S3ApiController) GetObjectLockConfiguration(ctx *fiber.Ctx) (*Response,
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetBucketAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetBucketAcl(ctx fiber.Ctx) (*Response, error) {
|
||||
// url values
|
||||
bucket := ctx.Params("bucket")
|
||||
// context keys
|
||||
@@ -454,7 +454,7 @@ func (c S3ApiController) GetBucketAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionReadAcp,
|
||||
@@ -473,7 +473,7 @@ func (c S3ApiController) GetBucketAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
data, err := c.be.GetBucketAcl(ctx.Context(),
|
||||
data, err := c.be.GetBucketAcl(ctx.RequestCtx(),
|
||||
&s3.GetBucketAclInput{Bucket: &bucket})
|
||||
if err != nil {
|
||||
return &Response{
|
||||
@@ -492,7 +492,7 @@ func (c S3ApiController) GetBucketAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) ListMultipartUploads(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) ListMultipartUploads(ctx fiber.Ctx) (*Response, error) {
|
||||
// url values
|
||||
bucket := ctx.Params("bucket")
|
||||
prefix := ctx.Query("prefix")
|
||||
@@ -506,7 +506,7 @@ func (c S3ApiController) ListMultipartUploads(ctx *fiber.Ctx) (*Response, error)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -532,7 +532,7 @@ func (c S3ApiController) ListMultipartUploads(ctx *fiber.Ctx) (*Response, error)
|
||||
},
|
||||
}, err
|
||||
}
|
||||
res, err := c.be.ListMultipartUploads(ctx.Context(),
|
||||
res, err := c.be.ListMultipartUploads(ctx.RequestCtx(),
|
||||
&s3.ListMultipartUploadsInput{
|
||||
Bucket: &bucket,
|
||||
Delimiter: &delimiter,
|
||||
@@ -549,7 +549,7 @@ func (c S3ApiController) ListMultipartUploads(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) ListObjectsV2(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) ListObjectsV2(ctx fiber.Ctx) (*Response, error) {
|
||||
// url values
|
||||
bucket := ctx.Params("bucket")
|
||||
prefix := ctx.Query("prefix")
|
||||
@@ -568,7 +568,7 @@ func (c S3ApiController) ListObjectsV2(ctx *fiber.Ctx) (*Response, error) {
|
||||
region = defaultRegion
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -595,7 +595,7 @@ func (c S3ApiController) ListObjectsV2(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := c.be.ListObjectsV2(ctx.Context(),
|
||||
res, err := c.be.ListObjectsV2(ctx.RequestCtx(),
|
||||
&s3.ListObjectsV2Input{
|
||||
Bucket: &bucket,
|
||||
Prefix: &prefix,
|
||||
@@ -624,7 +624,7 @@ func (c S3ApiController) ListObjectsV2(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c S3ApiController) ListObjects(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) ListObjects(ctx fiber.Ctx) (*Response, error) {
|
||||
// url values
|
||||
bucket := ctx.Params("bucket")
|
||||
prefix := ctx.Query("prefix")
|
||||
@@ -641,7 +641,7 @@ func (c S3ApiController) ListObjects(ctx *fiber.Ctx) (*Response, error) {
|
||||
region = defaultRegion
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -669,7 +669,7 @@ func (c S3ApiController) ListObjects(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := c.be.ListObjects(ctx.Context(),
|
||||
res, err := c.be.ListObjects(ctx.RequestCtx(),
|
||||
&s3.ListObjectsInput{
|
||||
Bucket: &bucket,
|
||||
Prefix: &prefix,
|
||||
@@ -697,14 +697,14 @@ func (c S3ApiController) ListObjects(ctx *fiber.Ctx) (*Response, error) {
|
||||
}
|
||||
|
||||
// GetBucketLocation handles GET /:bucket?location
|
||||
func (c S3ApiController) GetBucketLocation(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetBucketLocation(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -724,7 +724,7 @@ func (c S3ApiController) GetBucketLocation(ctx *fiber.Ctx) (*Response, error) {
|
||||
}
|
||||
|
||||
// verify bucket existence/access via backend HeadBucket
|
||||
_, err = c.be.HeadBucket(ctx.Context(), &s3.HeadBucketInput{Bucket: &bucket})
|
||||
_, err = c.be.HeadBucket(ctx.RequestCtx(), &s3.HeadBucketInput{Bucket: &bucket})
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
|
||||
@@ -18,13 +18,13 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
)
|
||||
|
||||
func (c S3ApiController) HeadBucket(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) HeadBucket(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
@@ -32,7 +32,7 @@ func (c S3ApiController) HeadBucket(ctx *fiber.Ctx) (*Response, error) {
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -55,7 +55,7 @@ func (c S3ApiController) HeadBucket(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
_, err = c.be.HeadBucket(ctx.Context(),
|
||||
_, err = c.be.HeadBucket(ctx.RequestCtx(),
|
||||
&s3.HeadBucketInput{
|
||||
Bucket: &bucket,
|
||||
})
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3response"
|
||||
)
|
||||
|
||||
func (c S3ApiController) ListBuckets(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) ListBuckets(ctx fiber.Ctx) (*Response, error) {
|
||||
cToken := ctx.Query("continuation-token")
|
||||
prefix := ctx.Query("prefix")
|
||||
maxBucketsStr := ctx.Query("max-buckets")
|
||||
@@ -38,7 +38,7 @@ func (c S3ApiController) ListBuckets(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := c.be.ListBuckets(ctx.Context(),
|
||||
res, err := c.be.ListBuckets(ctx.RequestCtx(),
|
||||
s3response.ListBucketsInput{
|
||||
Owner: acct.Access,
|
||||
IsAdmin: acct.Role == auth.RoleAdmin,
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
"github.com/versity/versitygw/s3api/middlewares"
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
"github.com/versity/versitygw/s3response"
|
||||
)
|
||||
|
||||
func (c S3ApiController) DeleteObjects(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) DeleteObjects(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
bypass := strings.EqualFold(ctx.Get("X-Amz-Bypass-Governance-Retention"), "true")
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
@@ -40,7 +40,7 @@ func (c S3ApiController) DeleteObjects(ctx *fiber.Ctx) (*Response, error) {
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
IsBucketPublic := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -61,7 +61,7 @@ func (c S3ApiController) DeleteObjects(ctx *fiber.Ctx) (*Response, error) {
|
||||
}
|
||||
|
||||
var dObj s3response.DeleteObjects
|
||||
err = xml.Unmarshal(ctx.Body(), &dObj)
|
||||
err = xml.Unmarshal(ctx.BodyRaw(), &dObj)
|
||||
if err != nil {
|
||||
debuglogger.Logf("error unmarshalling delete objects: %v", err)
|
||||
return &Response{
|
||||
@@ -71,7 +71,7 @@ func (c S3ApiController) DeleteObjects(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, s3err.GetAPIError(s3err.ErrInvalidRequest)
|
||||
}
|
||||
|
||||
err = auth.CheckObjectAccess(ctx.Context(), bucket, acct.Access, dObj.Objects, bypass, IsBucketPublic, c.be, false)
|
||||
err = auth.CheckObjectAccess(ctx.RequestCtx(), bucket, acct.Access, dObj.Objects, bypass, IsBucketPublic, c.be, false)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -80,7 +80,7 @@ func (c S3ApiController) DeleteObjects(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := c.be.DeleteObjects(ctx.Context(),
|
||||
res, err := c.be.DeleteObjects(ctx.RequestCtx(),
|
||||
&s3.DeleteObjectsInput{
|
||||
Bucket: &bucket,
|
||||
Delete: &types.Delete{
|
||||
@@ -97,7 +97,7 @@ func (c S3ApiController) DeleteObjects(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) POSTObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) POSTObject(ctx fiber.Ctx) (*Response, error) {
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
@@ -115,7 +115,7 @@ func (c S3ApiController) POSTObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
|
||||
key := parsed.Fields["key"]
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -206,7 +206,7 @@ func (c S3ApiController) POSTObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := c.be.PutObject(ctx.Context(), s3response.PutObjectInput{
|
||||
res, err := c.be.PutObject(ctx.RequestCtx(), s3response.PutObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
ContentType: &contentType,
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
@@ -30,14 +30,14 @@ import (
|
||||
"github.com/versity/versitygw/s3response"
|
||||
)
|
||||
|
||||
func (c S3ApiController) PutBucketTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutBucketTagging(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -56,7 +56,7 @@ func (c S3ApiController) PutBucketTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
tagging, err := utils.ParseTagging(ctx.Body(), utils.TagLimitBucket)
|
||||
tagging, err := utils.ParseTagging(ctx.BodyRaw(), utils.TagLimitBucket)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -65,7 +65,7 @@ func (c S3ApiController) PutBucketTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.PutBucketTagging(ctx.Context(), bucket, tagging)
|
||||
err = c.be.PutBucketTagging(ctx.RequestCtx(), bucket, tagging)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -74,13 +74,13 @@ func (c S3ApiController) PutBucketTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) PutBucketOwnershipControls(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutBucketOwnershipControls(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
|
||||
if err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
if err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -98,7 +98,7 @@ func (c S3ApiController) PutBucketOwnershipControls(ctx *fiber.Ctx) (*Response,
|
||||
}
|
||||
|
||||
var ownershipControls s3response.OwnershipControls
|
||||
if err := xml.Unmarshal(ctx.Body(), &ownershipControls); err != nil {
|
||||
if err := xml.Unmarshal(ctx.BodyRaw(), &ownershipControls); err != nil {
|
||||
debuglogger.Logf("failed to unmarshal request body: %v", err)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -125,7 +125,7 @@ func (c S3ApiController) PutBucketOwnershipControls(ctx *fiber.Ctx) (*Response,
|
||||
}, s3err.GetAPIError(s3err.ErrMalformedXML)
|
||||
}
|
||||
|
||||
err := c.be.PutBucketOwnershipControls(ctx.Context(), bucket, ownershipControls.Rules[0].ObjectOwnership)
|
||||
err := c.be.PutBucketOwnershipControls(ctx.RequestCtx(), bucket, ownershipControls.Rules[0].ObjectOwnership)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -133,14 +133,14 @@ func (c S3ApiController) PutBucketOwnershipControls(ctx *fiber.Ctx) (*Response,
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) PutBucketVersioning(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutBucketVersioning(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -160,7 +160,7 @@ func (c S3ApiController) PutBucketVersioning(ctx *fiber.Ctx) (*Response, error)
|
||||
}
|
||||
|
||||
var versioningConf types.VersioningConfiguration
|
||||
err = xml.Unmarshal(ctx.Body(), &versioningConf)
|
||||
err = xml.Unmarshal(ctx.BodyRaw(), &versioningConf)
|
||||
if err != nil {
|
||||
debuglogger.Logf("error unmarshalling versioning configuration: %v", err)
|
||||
return &Response{
|
||||
@@ -180,7 +180,7 @@ func (c S3ApiController) PutBucketVersioning(ctx *fiber.Ctx) (*Response, error)
|
||||
}, s3err.GetAPIError(s3err.ErrMalformedXML)
|
||||
}
|
||||
|
||||
err = c.be.PutBucketVersioning(ctx.Context(), bucket, versioningConf.Status)
|
||||
err = c.be.PutBucketVersioning(ctx.RequestCtx(), bucket, versioningConf.Status)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -188,14 +188,14 @@ func (c S3ApiController) PutBucketVersioning(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) PutObjectLockConfiguration(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutObjectLockConfiguration(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
if err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
if err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -213,7 +213,7 @@ func (c S3ApiController) PutObjectLockConfiguration(ctx *fiber.Ctx) (*Response,
|
||||
}, err
|
||||
}
|
||||
|
||||
config, err := auth.ParseBucketLockConfigurationInput(ctx.Body())
|
||||
config, err := auth.ParseBucketLockConfigurationInput(ctx.BodyRaw())
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -222,7 +222,7 @@ func (c S3ApiController) PutObjectLockConfiguration(ctx *fiber.Ctx) (*Response,
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.PutObjectLockConfiguration(ctx.Context(), bucket, config)
|
||||
err = c.be.PutObjectLockConfiguration(ctx.RequestCtx(), bucket, config)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -230,14 +230,14 @@ func (c S3ApiController) PutObjectLockConfiguration(ctx *fiber.Ctx) (*Response,
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) PutBucketCors(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutBucketCors(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -256,7 +256,7 @@ func (c S3ApiController) PutBucketCors(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
body := ctx.Body()
|
||||
body := ctx.BodyRaw()
|
||||
|
||||
var corsConfig auth.CORSConfiguration
|
||||
err = xml.Unmarshal(body, &corsConfig)
|
||||
@@ -279,7 +279,7 @@ func (c S3ApiController) PutBucketCors(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.PutBucketCors(ctx.Context(), bucket, body)
|
||||
err = c.be.PutBucketCors(ctx.RequestCtx(), bucket, body)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -287,14 +287,14 @@ func (c S3ApiController) PutBucketCors(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) PutBucketWebsite(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutBucketWebsite(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -313,7 +313,7 @@ func (c S3ApiController) PutBucketWebsite(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
body := ctx.Body()
|
||||
body := ctx.BodyRaw()
|
||||
if len(body) > maxWebsiteConfigurationBytes {
|
||||
debuglogger.Logf("the request size exceeded the 128KB limit: %d", len(body))
|
||||
return &Response{
|
||||
@@ -343,7 +343,7 @@ func (c S3ApiController) PutBucketWebsite(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.PutBucketWebsite(ctx.Context(), bucket, body)
|
||||
err = c.be.PutBucketWebsite(ctx.RequestCtx(), bucket, body)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -351,13 +351,13 @@ func (c S3ApiController) PutBucketWebsite(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) PutBucketPolicy(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutBucketPolicy(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -375,7 +375,7 @@ func (c S3ApiController) PutBucketPolicy(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = auth.ValidatePolicyDocument(ctx.Body(), bucket, c.iam)
|
||||
err = auth.ValidatePolicyDocument(ctx.BodyRaw(), bucket, c.iam)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -384,7 +384,7 @@ func (c S3ApiController) PutBucketPolicy(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.PutBucketPolicy(ctx.Context(), bucket, ctx.Body())
|
||||
err = c.be.PutBucketPolicy(ctx.RequestCtx(), bucket, ctx.BodyRaw())
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -393,7 +393,7 @@ func (c S3ApiController) PutBucketPolicy(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) PutBucketAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutBucketAcl(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acl := types.BucketCannedACL(ctx.Get("X-Amz-Acl"))
|
||||
grantFullControl := ctx.Get("X-Amz-Grant-Full-Control")
|
||||
@@ -409,7 +409,7 @@ func (c S3ApiController) PutBucketAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
grants := grantFullControl + grantRead + grantReadACP + grantWrite + grantWriteACP
|
||||
var input *auth.PutBucketAclInput
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -446,7 +446,7 @@ func (c S3ApiController) PutBucketAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
ownership, err := c.be.GetBucketOwnershipControls(ctx.Context(), bucket)
|
||||
ownership, err := c.be.GetBucketOwnershipControls(ctx.RequestCtx(), bucket)
|
||||
if err != nil && !errors.Is(err, s3err.GetAPIError(s3err.ErrOwnershipControlsNotFound)) {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -463,9 +463,9 @@ func (c S3ApiController) PutBucketAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, s3err.GetAPIError(s3err.ErrAclNotSupported)
|
||||
}
|
||||
|
||||
if len(ctx.Body()) > 0 {
|
||||
if len(ctx.BodyRaw()) > 0 {
|
||||
var accessControlPolicy auth.AccessControlPolicy
|
||||
err := xml.Unmarshal(ctx.Body(), &accessControlPolicy)
|
||||
err := xml.Unmarshal(ctx.BodyRaw(), &accessControlPolicy)
|
||||
if err != nil {
|
||||
debuglogger.Logf("error unmarshalling access control policy: %v", err)
|
||||
return &Response{
|
||||
@@ -554,7 +554,7 @@ func (c S3ApiController) PutBucketAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.PutBucketAcl(ctx.Context(), bucket, updAcl)
|
||||
err = c.be.PutBucketAcl(ctx.RequestCtx(), bucket, updAcl)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -562,7 +562,7 @@ func (c S3ApiController) PutBucketAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) CreateBucket(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) CreateBucket(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
acl := types.BucketCannedACL(c.getAclHeaderValue(ctx, "X-Amz-Acl"))
|
||||
grantFullControl := c.getAclHeaderValue(ctx, "X-Amz-Grant-Full-Control")
|
||||
@@ -654,9 +654,9 @@ func (c S3ApiController) CreateBucket(ctx *fiber.Ctx) (*Response, error) {
|
||||
}
|
||||
|
||||
var body s3response.CreateBucketConfiguration
|
||||
if len(ctx.Body()) != 0 {
|
||||
if len(ctx.BodyRaw()) != 0 {
|
||||
// request body is optional for CreateBucket
|
||||
err := xml.Unmarshal(ctx.Body(), &body)
|
||||
err := xml.Unmarshal(ctx.BodyRaw(), &body)
|
||||
if err != nil {
|
||||
debuglogger.Logf("failed to parse the request body: %v", err)
|
||||
return &Response{
|
||||
@@ -704,7 +704,7 @@ func (c S3ApiController) CreateBucket(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.CreateBucket(ctx.Context(), &s3.CreateBucketInput{
|
||||
err = c.be.CreateBucket(ctx.RequestCtx(), &s3.CreateBucketInput{
|
||||
Bucket: &bucket,
|
||||
ObjectOwnership: objectOwnership,
|
||||
ObjectLockEnabledForBucket: &lockEnabled,
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/s3api/middlewares"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
)
|
||||
@@ -36,7 +36,7 @@ func TestApplyBucketCORS_FallbackOrigin_NoBucketCors_NoRequestOrigin(t *testing.
|
||||
app := fiber.New()
|
||||
app.Get("/:bucket/test",
|
||||
middlewares.ApplyBucketCORS(mockedBackend, middlewares.BucketFromPath, origin),
|
||||
func(c *fiber.Ctx) error {
|
||||
func(c fiber.Ctx) error {
|
||||
return c.SendStatus(http.StatusOK)
|
||||
},
|
||||
)
|
||||
@@ -72,7 +72,7 @@ func TestApplyBucketCORS_FallbackOrigin_NotAppliedWhenBucketCorsExists(t *testin
|
||||
app := fiber.New()
|
||||
app.Get("/:bucket/test",
|
||||
middlewares.ApplyBucketCORS(mockedBackend, middlewares.BucketFromPath, origin),
|
||||
func(c *fiber.Ctx) error {
|
||||
func(c fiber.Ctx) error {
|
||||
return c.SendStatus(http.StatusOK)
|
||||
},
|
||||
)
|
||||
|
||||
@@ -21,13 +21,13 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3event"
|
||||
)
|
||||
|
||||
func (c S3ApiController) DeleteObjectTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) DeleteObjectTagging(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
versionId := ctx.Query("versionId")
|
||||
@@ -41,7 +41,7 @@ func (c S3ApiController) DeleteObjectTagging(ctx *fiber.Ctx) (*Response, error)
|
||||
action = auth.DeleteObjectVersionTaggingAction
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -62,7 +62,7 @@ func (c S3ApiController) DeleteObjectTagging(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.DeleteObjectTagging(ctx.Context(), bucket, key, versionId)
|
||||
err = c.be.DeleteObjectTagging(ctx.RequestCtx(), bucket, key, versionId)
|
||||
return &Response{
|
||||
Headers: map[string]*string{
|
||||
"x-amz-version-id": &versionId,
|
||||
@@ -75,7 +75,7 @@ func (c S3ApiController) DeleteObjectTagging(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) AbortMultipartUpload(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) AbortMultipartUpload(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
uploadId := ctx.Query("uploadId")
|
||||
@@ -85,7 +85,7 @@ func (c S3ApiController) AbortMultipartUpload(ctx *fiber.Ctx) (*Response, error)
|
||||
isBucketPublic := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -106,7 +106,7 @@ func (c S3ApiController) AbortMultipartUpload(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.AbortMultipartUpload(ctx.Context(),
|
||||
err = c.be.AbortMultipartUpload(ctx.RequestCtx(),
|
||||
&s3.AbortMultipartUploadInput{
|
||||
UploadId: &uploadId,
|
||||
Bucket: &bucket,
|
||||
@@ -121,12 +121,12 @@ func (c S3ApiController) AbortMultipartUpload(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) DeleteObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) DeleteObject(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
versionId := ctx.Query("versionId")
|
||||
bypass := strings.EqualFold(ctx.Get("X-Amz-Bypass-Governance-Retention"), "true")
|
||||
ifMatch := utils.GetStringPtr(utils.TrimQuotes(ctx.Get("If-Match")))
|
||||
ifMatch := utils.GetStringPtr(strings.Trim(ctx.Get("If-Match"), `"`))
|
||||
ifMatchLastModTime := utils.ParsePreconditionDateHeader(ctx.Get("X-Amz-If-Match-Last-Modified-Time"))
|
||||
ifMatchSize := utils.ParseIfMatchSize(ctx)
|
||||
// context locals
|
||||
@@ -140,7 +140,7 @@ func (c S3ApiController) DeleteObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
action = auth.DeleteObjectVersionAction
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -162,7 +162,7 @@ func (c S3ApiController) DeleteObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
}
|
||||
|
||||
err = auth.CheckObjectAccess(
|
||||
ctx.Context(),
|
||||
ctx.RequestCtx(),
|
||||
bucket,
|
||||
acct.Access,
|
||||
[]types.ObjectIdentifier{
|
||||
@@ -184,7 +184,7 @@ func (c S3ApiController) DeleteObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := c.be.DeleteObject(ctx.Context(),
|
||||
res, err := c.be.DeleteObject(ctx.RequestCtx(),
|
||||
&s3.DeleteObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"github.com/versity/versitygw/s3response"
|
||||
)
|
||||
|
||||
func (c S3ApiController) GetObjectTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetObjectTagging(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
versionId := ctx.Query("versionId")
|
||||
@@ -45,7 +45,7 @@ func (c S3ApiController) GetObjectTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
action = auth.GetObjectVersionTaggingAction
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -65,7 +65,7 @@ func (c S3ApiController) GetObjectTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
data, err := c.be.GetObjectTagging(ctx.Context(), bucket, key, versionId)
|
||||
data, err := c.be.GetObjectTagging(ctx.RequestCtx(), bucket, key, versionId)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -93,7 +93,7 @@ func (c S3ApiController) GetObjectTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetObjectRetention(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetObjectRetention(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
versionId := ctx.Query("versionId")
|
||||
@@ -103,7 +103,7 @@ func (c S3ApiController) GetObjectRetention(ctx *fiber.Ctx) (*Response, error) {
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -123,7 +123,7 @@ func (c S3ApiController) GetObjectRetention(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
data, err := c.be.GetObjectRetention(ctx.Context(), bucket, key, versionId)
|
||||
data, err := c.be.GetObjectRetention(ctx.RequestCtx(), bucket, key, versionId)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -141,7 +141,7 @@ func (c S3ApiController) GetObjectRetention(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetObjectLegalHold(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetObjectLegalHold(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
versionId := ctx.Query("versionId")
|
||||
@@ -151,7 +151,7 @@ func (c S3ApiController) GetObjectLegalHold(ctx *fiber.Ctx) (*Response, error) {
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -171,7 +171,7 @@ func (c S3ApiController) GetObjectLegalHold(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
data, err := c.be.GetObjectLegalHold(ctx.Context(), bucket, key, versionId)
|
||||
data, err := c.be.GetObjectLegalHold(ctx.RequestCtx(), bucket, key, versionId)
|
||||
return &Response{
|
||||
Data: auth.ParseObjectLegalHoldOutput(data),
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -180,7 +180,7 @@ func (c S3ApiController) GetObjectLegalHold(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetObjectAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetObjectAcl(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
// context locals
|
||||
@@ -189,7 +189,7 @@ func (c S3ApiController) GetObjectAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionReadAcp,
|
||||
@@ -208,7 +208,7 @@ func (c S3ApiController) GetObjectAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
},
|
||||
}, err
|
||||
}
|
||||
res, err := c.be.GetObjectAcl(ctx.Context(), &s3.GetObjectAclInput{
|
||||
res, err := c.be.GetObjectAcl(ctx.RequestCtx(), &s3.GetObjectAclInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
})
|
||||
@@ -220,7 +220,7 @@ func (c S3ApiController) GetObjectAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) ListParts(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) ListParts(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
uploadId := ctx.Query("uploadId")
|
||||
@@ -232,7 +232,7 @@ func (c S3ApiController) ListParts(ctx *fiber.Ctx) (*Response, error) {
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -272,7 +272,7 @@ func (c S3ApiController) ListParts(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := c.be.ListParts(ctx.Context(), &s3.ListPartsInput{
|
||||
res, err := c.be.ListParts(ctx.RequestCtx(), &s3.ListPartsInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
UploadId: &uploadId,
|
||||
@@ -287,7 +287,7 @@ func (c S3ApiController) ListParts(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetObjectAttributes(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetObjectAttributes(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
versionId := ctx.Query("versionId")
|
||||
@@ -304,7 +304,7 @@ func (c S3ApiController) GetObjectAttributes(ctx *fiber.Ctx) (*Response, error)
|
||||
action = auth.GetObjectVersionAttributesAction
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -341,7 +341,7 @@ func (c S3ApiController) GetObjectAttributes(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := c.be.GetObjectAttributes(ctx.Context(),
|
||||
res, err := c.be.GetObjectAttributes(ctx.RequestCtx(),
|
||||
&s3.GetObjectAttributesInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
@@ -381,13 +381,13 @@ func (c S3ApiController) GetObjectAttributes(ctx *fiber.Ctx) (*Response, error)
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) GetObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) GetObject(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
versionId := ctx.Query("versionId")
|
||||
acceptRange := ctx.Get("Range")
|
||||
checksumMode := types.ChecksumMode(strings.ToUpper(ctx.Get("x-amz-checksum-mode")))
|
||||
partNumberQuery := int32(ctx.QueryInt("partNumber", -1))
|
||||
partNumberQuery := int32(fiber.Query[int](ctx, "partNumber", -1))
|
||||
|
||||
// Extract response override query parameters
|
||||
responseOverrides := map[string]*string{
|
||||
@@ -429,7 +429,7 @@ func (c S3ApiController) GetObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
action = auth.GetObjectVersionAction
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionRead,
|
||||
@@ -484,7 +484,7 @@ func (c S3ApiController) GetObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
|
||||
conditionalHeaders := utils.ParsePreconditionHeaders(ctx)
|
||||
|
||||
res, err := c.be.GetObject(ctx.Context(), &s3.GetObjectInput{
|
||||
res, err := c.be.GetObject(ctx.RequestCtx(), &s3.GetObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
Range: &acceptRange,
|
||||
|
||||
@@ -22,14 +22,14 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
)
|
||||
|
||||
func (c S3ApiController) HeadObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) HeadObject(ctx fiber.Ctx) (*Response, error) {
|
||||
// context locals
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
@@ -37,7 +37,7 @@ func (c S3ApiController) HeadObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
isPublicBucket := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
// url values
|
||||
bucket := ctx.Params("bucket")
|
||||
partNumberQuery := int32(ctx.QueryInt("partNumber", -1))
|
||||
partNumberQuery := int32(fiber.Query(ctx, "partNumber", -1))
|
||||
versionId := ctx.Query("versionId")
|
||||
objRange := ctx.Get("Range")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
@@ -76,7 +76,7 @@ func (c S3ApiController) HeadObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
action = auth.GetObjectVersionAction
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -132,7 +132,7 @@ func (c S3ApiController) HeadObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
|
||||
conditionalHeaders := utils.ParsePreconditionHeaders(ctx)
|
||||
|
||||
res, err := c.be.HeadObject(ctx.Context(),
|
||||
res, err := c.be.HeadObject(ctx.RequestCtx(),
|
||||
&s3.HeadObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"github.com/versity/versitygw/s3response"
|
||||
)
|
||||
|
||||
func (c S3ApiController) RestoreObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) RestoreObject(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
@@ -39,7 +39,7 @@ func (c S3ApiController) RestoreObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
isBucketPublic := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -61,7 +61,7 @@ func (c S3ApiController) RestoreObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
}
|
||||
|
||||
var restoreRequest types.RestoreRequest
|
||||
if err := xml.Unmarshal(ctx.Body(), &restoreRequest); err != nil {
|
||||
if err := xml.Unmarshal(ctx.BodyRaw(), &restoreRequest); err != nil {
|
||||
debuglogger.Logf("failed to parse the request body: %v", err)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -70,7 +70,7 @@ func (c S3ApiController) RestoreObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, s3err.GetAPIError(s3err.ErrMalformedXML)
|
||||
}
|
||||
|
||||
err = c.be.RestoreObject(ctx.Context(), &s3.RestoreObjectInput{
|
||||
err = c.be.RestoreObject(ctx.RequestCtx(), &s3.RestoreObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
RestoreRequest: &restoreRequest,
|
||||
@@ -83,7 +83,7 @@ func (c S3ApiController) RestoreObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) SelectObjectContent(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) SelectObjectContent(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
@@ -91,7 +91,7 @@ func (c S3ApiController) SelectObjectContent(ctx *fiber.Ctx) (*Response, error)
|
||||
isBucketPublic := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -113,7 +113,7 @@ func (c S3ApiController) SelectObjectContent(ctx *fiber.Ctx) (*Response, error)
|
||||
}
|
||||
|
||||
var payload s3response.SelectObjectContentPayload
|
||||
err = xml.Unmarshal(ctx.Body(), &payload)
|
||||
err = xml.Unmarshal(ctx.BodyRaw(), &payload)
|
||||
if err != nil {
|
||||
debuglogger.Logf("error unmarshalling select object content: %v", err)
|
||||
return &Response{
|
||||
@@ -123,7 +123,7 @@ func (c S3ApiController) SelectObjectContent(ctx *fiber.Ctx) (*Response, error)
|
||||
}, s3err.GetAPIError(s3err.ErrMalformedXML)
|
||||
}
|
||||
|
||||
sw := c.be.SelectObjectContent(ctx.Context(),
|
||||
sw := c.be.SelectObjectContent(ctx.RequestCtx(),
|
||||
&s3.SelectObjectContentInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
@@ -135,7 +135,7 @@ func (c S3ApiController) SelectObjectContent(ctx *fiber.Ctx) (*Response, error)
|
||||
ScanRange: payload.ScanRange,
|
||||
})
|
||||
|
||||
ctx.Context().SetBodyStreamWriter(sw)
|
||||
ctx.RequestCtx().SetBodyStreamWriter(sw)
|
||||
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -144,7 +144,7 @@ func (c S3ApiController) SelectObjectContent(ctx *fiber.Ctx) (*Response, error)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c S3ApiController) CreateMultipartUpload(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) CreateMultipartUpload(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
contentType := ctx.Get("Content-Type", defaultContentType)
|
||||
@@ -175,7 +175,7 @@ func (c S3ApiController) CreateMultipartUpload(ctx *fiber.Ctx) (*Response, error
|
||||
actions = append(actions, auth.PutObjectRetentionAction)
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -231,7 +231,7 @@ func (c S3ApiController) CreateMultipartUpload(ctx *fiber.Ctx) (*Response, error
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := c.be.CreateMultipartUpload(ctx.Context(),
|
||||
res, err := c.be.CreateMultipartUpload(ctx.RequestCtx(),
|
||||
s3response.CreateMultipartUploadInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
@@ -266,7 +266,7 @@ func (c S3ApiController) CreateMultipartUpload(ctx *fiber.Ctx) (*Response, error
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) CompleteMultipartUpload(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) CompleteMultipartUpload(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
uploadId := ctx.Query("uploadId")
|
||||
@@ -278,7 +278,7 @@ func (c S3ApiController) CompleteMultipartUpload(ctx *fiber.Ctx) (*Response, err
|
||||
isBucketPublic := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -300,7 +300,7 @@ func (c S3ApiController) CompleteMultipartUpload(ctx *fiber.Ctx) (*Response, err
|
||||
}
|
||||
|
||||
var body s3response.CompleteMultipartUploadRequestBody
|
||||
err = xml.Unmarshal(ctx.Body(), &body)
|
||||
err = xml.Unmarshal(ctx.BodyRaw(), &body)
|
||||
if err != nil {
|
||||
debuglogger.Logf("error unmarshalling complete multipart upload: %v", err)
|
||||
return &Response{
|
||||
@@ -363,7 +363,7 @@ func (c S3ApiController) CompleteMultipartUpload(ctx *fiber.Ctx) (*Response, err
|
||||
|
||||
ifMatch, ifNoneMatch := utils.ParsePreconditionMatchHeaders(ctx)
|
||||
|
||||
err = auth.CheckObjectAccess(ctx.Context(), bucket, acct.Access, []types.ObjectIdentifier{{Key: &key}}, true, isBucketPublic, c.be, true)
|
||||
err = auth.CheckObjectAccess(ctx.RequestCtx(), bucket, acct.Access, []types.ObjectIdentifier{{Key: &key}}, true, isBucketPublic, c.be, true)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -372,7 +372,7 @@ func (c S3ApiController) CompleteMultipartUpload(ctx *fiber.Ctx) (*Response, err
|
||||
}, err
|
||||
}
|
||||
|
||||
res, versid, err := c.be.CompleteMultipartUpload(ctx.Context(),
|
||||
res, versid, err := c.be.CompleteMultipartUpload(ctx.RequestCtx(),
|
||||
&s3.CompleteMultipartUploadInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
@@ -33,7 +33,7 @@ import (
|
||||
"github.com/versity/versitygw/s3response"
|
||||
)
|
||||
|
||||
func (c S3ApiController) PutObjectTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutObjectTagging(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
versionId := ctx.Query("versionId")
|
||||
@@ -47,7 +47,7 @@ func (c S3ApiController) PutObjectTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
action = auth.PutObjectVersionTaggingAction
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -67,7 +67,7 @@ func (c S3ApiController) PutObjectTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
tagging, err := utils.ParseTagging(ctx.Body(), utils.TagLimitObject)
|
||||
tagging, err := utils.ParseTagging(ctx.BodyRaw(), utils.TagLimitObject)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -76,7 +76,7 @@ func (c S3ApiController) PutObjectTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.PutObjectTagging(ctx.Context(), bucket, key, versionId, tagging)
|
||||
err = c.be.PutObjectTagging(ctx.RequestCtx(), bucket, key, versionId, tagging)
|
||||
return &Response{
|
||||
Headers: map[string]*string{
|
||||
"x-amz-version-id": &versionId,
|
||||
@@ -88,7 +88,7 @@ func (c S3ApiController) PutObjectTagging(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) PutObjectRetention(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutObjectRetention(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
versionId := ctx.Query("versionId")
|
||||
@@ -98,7 +98,7 @@ func (c S3ApiController) PutObjectRetention(ctx *fiber.Ctx) (*Response, error) {
|
||||
IsBucketPublic := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -119,7 +119,7 @@ func (c S3ApiController) PutObjectRetention(ctx *fiber.Ctx) (*Response, error) {
|
||||
}
|
||||
|
||||
// parse the request body bytes into a go struct and validate
|
||||
retention, err := auth.ParseObjectLockRetentionInput(ctx.Body())
|
||||
retention, err := auth.ParseObjectLockRetentionInput(ctx.BodyRaw())
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -129,7 +129,7 @@ func (c S3ApiController) PutObjectRetention(ctx *fiber.Ctx) (*Response, error) {
|
||||
}
|
||||
|
||||
// check if the operation is allowed
|
||||
err = auth.IsObjectLockRetentionPutAllowed(ctx.Context(), c.be, bucket, key, versionId, acct.Access, retention, bypass)
|
||||
err = auth.IsObjectLockRetentionPutAllowed(ctx.RequestCtx(), c.be, bucket, key, versionId, acct.Access, retention, bypass)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -148,7 +148,7 @@ func (c S3ApiController) PutObjectRetention(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.PutObjectRetention(ctx.Context(), bucket, key, versionId, data)
|
||||
err = c.be.PutObjectRetention(ctx.RequestCtx(), bucket, key, versionId, data)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -156,7 +156,7 @@ func (c S3ApiController) PutObjectRetention(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) PutObjectLegalHold(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutObjectLegalHold(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
versionId := ctx.Query("versionId")
|
||||
@@ -165,7 +165,7 @@ func (c S3ApiController) PutObjectLegalHold(ctx *fiber.Ctx) (*Response, error) {
|
||||
IsBucketPublic := utils.ContextKeyPublicBucket.IsSet(ctx)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be, auth.AccessOptions{
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -186,7 +186,7 @@ func (c S3ApiController) PutObjectLegalHold(ctx *fiber.Ctx) (*Response, error) {
|
||||
}
|
||||
|
||||
var legalHold types.ObjectLockLegalHold
|
||||
if err := xml.Unmarshal(ctx.Body(), &legalHold); err != nil {
|
||||
if err := xml.Unmarshal(ctx.BodyRaw(), &legalHold); err != nil {
|
||||
debuglogger.Logf("failed to parse request body: %v", err)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -204,7 +204,7 @@ func (c S3ApiController) PutObjectLegalHold(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, s3err.GetAPIError(s3err.ErrMalformedXML)
|
||||
}
|
||||
|
||||
err = c.be.PutObjectLegalHold(ctx.Context(), bucket, key, versionId, legalHold.Status == types.ObjectLockLegalHoldStatusOn)
|
||||
err = c.be.PutObjectLegalHold(ctx.RequestCtx(), bucket, key, versionId, legalHold.Status == types.ObjectLockLegalHoldStatusOn)
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: parsedAcl.Owner,
|
||||
@@ -212,10 +212,10 @@ func (c S3ApiController) PutObjectLegalHold(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) UploadPart(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) UploadPart(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
partNumber := int32(ctx.QueryInt("partNumber", -1))
|
||||
partNumber := int32(fiber.Query(ctx, "partNumber", -1))
|
||||
uploadId := ctx.Query("uploadId")
|
||||
// context locals
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
@@ -234,7 +234,7 @@ func (c S3ApiController) UploadPart(ctx *fiber.Ctx) (*Response, error) {
|
||||
contentLengthStr = decodedLength
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -292,7 +292,7 @@ func (c S3ApiController) UploadPart(ctx *fiber.Ctx) (*Response, error) {
|
||||
body = bytes.NewReader([]byte{})
|
||||
}
|
||||
|
||||
res, err := c.be.UploadPart(ctx.Context(),
|
||||
res, err := c.be.UploadPart(ctx.RequestCtx(),
|
||||
&s3.UploadPartInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
@@ -338,13 +338,13 @@ func (c S3ApiController) UploadPart(ctx *fiber.Ctx) (*Response, error) {
|
||||
|
||||
}
|
||||
|
||||
func (c S3ApiController) UploadPartCopy(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) UploadPartCopy(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
copySource := strings.TrimPrefix(ctx.Get("X-Amz-Copy-Source"), "/")
|
||||
copySrcRange := ctx.Get("X-Amz-Copy-Source-Range")
|
||||
expectedSrcBucketOwnerUPC := ctx.Get("X-Amz-Source-Expected-Bucket-Owner")
|
||||
partNumber := int32(ctx.QueryInt("partNumber", -1))
|
||||
partNumber := int32(fiber.Query(ctx, "partNumber", -1))
|
||||
uploadId := ctx.Query("uploadId")
|
||||
// context locals
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
@@ -361,7 +361,7 @@ func (c S3ApiController) UploadPartCopy(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = auth.VerifyObjectCopyAccess(ctx.Context(), c.be, copySource,
|
||||
err = auth.VerifyObjectCopyAccess(ctx.RequestCtx(), c.be, copySource,
|
||||
auth.AccessOptions{
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -401,7 +401,7 @@ func (c S3ApiController) UploadPartCopy(ctx *fiber.Ctx) (*Response, error) {
|
||||
|
||||
preconditionHdrs := utils.ParsePreconditionHeaders(ctx, utils.WithCopySource())
|
||||
|
||||
resp, err := c.be.UploadPartCopy(ctx.Context(),
|
||||
resp, err := c.be.UploadPartCopy(ctx.RequestCtx(),
|
||||
&s3.UploadPartCopyInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
@@ -430,7 +430,7 @@ func (c S3ApiController) UploadPartCopy(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) PutObjectAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutObjectAcl(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
acl := ctx.Get("X-Amz-Acl")
|
||||
@@ -444,7 +444,7 @@ func (c S3ApiController) PutObjectAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
isRoot := utils.ContextKeyIsRoot.Get(ctx).(bool)
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -463,7 +463,7 @@ func (c S3ApiController) PutObjectAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = c.be.PutObjectAcl(ctx.Context(), &s3.PutObjectAclInput{
|
||||
err = c.be.PutObjectAcl(ctx.RequestCtx(), &s3.PutObjectAclInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
GrantFullControl: &grantFullControl,
|
||||
@@ -481,7 +481,7 @@ func (c S3ApiController) PutObjectAcl(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) CopyObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) CopyObject(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
copySource := strings.TrimPrefix(ctx.Get("X-Amz-Copy-Source"), "/")
|
||||
@@ -525,7 +525,7 @@ func (c S3ApiController) CopyObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
actions = append(actions, auth.PutObjectRetentionAction)
|
||||
}
|
||||
|
||||
err = auth.VerifyObjectCopyAccess(ctx.Context(), c.be, copySource,
|
||||
err = auth.VerifyObjectCopyAccess(ctx.RequestCtx(), c.be, copySource,
|
||||
auth.AccessOptions{
|
||||
Acl: parsedAcl,
|
||||
AclPermission: auth.PermissionWrite,
|
||||
@@ -609,7 +609,7 @@ func (c S3ApiController) CopyObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
|
||||
preconditionHdrs := utils.ParsePreconditionHeaders(ctx, utils.WithCopySource())
|
||||
|
||||
err = auth.CheckObjectAccess(ctx.Context(), bucket, acct.Access, []types.ObjectIdentifier{{Key: &key}}, true, false, c.be, true)
|
||||
err = auth.CheckObjectAccess(ctx.RequestCtx(), bucket, acct.Access, []types.ObjectIdentifier{{Key: &key}}, true, false, c.be, true)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -618,7 +618,7 @@ func (c S3ApiController) CopyObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := c.be.CopyObject(ctx.Context(),
|
||||
res, err := c.be.CopyObject(ctx.RequestCtx(),
|
||||
s3response.CopyObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
@@ -667,7 +667,7 @@ func (c S3ApiController) CopyObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
func (c S3ApiController) PutObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (c S3ApiController) PutObject(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket))
|
||||
contentType := ctx.Get("Content-Type", defaultContentType)
|
||||
@@ -710,7 +710,7 @@ func (c S3ApiController) PutObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
actions = append(actions, auth.PutObjectRetentionAction)
|
||||
}
|
||||
|
||||
err := auth.VerifyAccess(ctx.Context(), c.be,
|
||||
err := auth.VerifyAccess(ctx.RequestCtx(), c.be,
|
||||
auth.AccessOptions{
|
||||
Readonly: c.readonly,
|
||||
Acl: parsedAcl,
|
||||
@@ -750,7 +750,7 @@ func (c S3ApiController) PutObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
err = auth.CheckObjectAccess(ctx.Context(), bucket, acct.Access, []types.ObjectIdentifier{{Key: &key}}, true, IsBucketPublic, c.be, true)
|
||||
err = auth.CheckObjectAccess(ctx.RequestCtx(), bucket, acct.Access, []types.ObjectIdentifier{{Key: &key}}, true, IsBucketPublic, c.be, true)
|
||||
if err != nil {
|
||||
return &Response{
|
||||
MetaOpts: &MetaOptions{
|
||||
@@ -797,7 +797,7 @@ func (c S3ApiController) PutObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
|
||||
ifMatch, ifNoneMatch := utils.ParsePreconditionMatchHeaders(ctx)
|
||||
|
||||
res, err := c.be.PutObject(ctx.Context(),
|
||||
res, err := c.be.PutObject(ctx.RequestCtx(),
|
||||
s3response.PutObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
"github.com/versity/versitygw/s3api/middlewares"
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
"github.com/versity/versitygw/s3err"
|
||||
)
|
||||
|
||||
func (s S3ApiController) CORSOptions(ctx *fiber.Ctx) (*Response, error) {
|
||||
func (s S3ApiController) CORSOptions(ctx fiber.Ctx) (*Response, error) {
|
||||
bucket := ctx.Params("bucket")
|
||||
parsedAcl := utils.ContextKeyParsedAcl.Get(ctx).(auth.ACL)
|
||||
// get headers
|
||||
@@ -65,7 +65,7 @@ func (s S3ApiController) CORSOptions(ctx *fiber.Ctx) (*Response, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
cors, err := s.be.GetBucketCors(ctx.Context(), bucket)
|
||||
cors, err := s.be.GetBucketCors(ctx.RequestCtx(), bucket)
|
||||
if err != nil {
|
||||
debuglogger.Logf("failed to get bucket cors: %v", err)
|
||||
if errors.Is(err, s3err.GetAPIError(s3err.ErrNoSuchCORSConfiguration)) {
|
||||
|
||||
@@ -16,7 +16,7 @@ package middlewares
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
@@ -26,9 +26,9 @@ import (
|
||||
// ParseAcl retreives the bucket acl and stores in the context locals
|
||||
// if no bucket is found, it returns 'NoSuchBucket'
|
||||
func ParseAcl(be backend.Backend) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
bucket := ctx.Params("bucket")
|
||||
data, err := be.GetBucketAcl(ctx.Context(), &s3.GetBucketAclInput{Bucket: &bucket})
|
||||
data, err := be.GetBucketAcl(ctx.RequestCtx(), &s3.GetBucketAclInput{Bucket: &bucket})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
// IsAdmin is a middleware that restricts access to admin APIs, allowing only admin users
|
||||
func IsAdmin(action string) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
|
||||
if acct.Role != auth.RoleAdmin {
|
||||
return s3err.GetAPIError(s3err.ErrAdminAccessDenied)
|
||||
|
||||
@@ -17,7 +17,7 @@ package middlewares
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
)
|
||||
@@ -36,12 +36,12 @@ import (
|
||||
func ApplyBucketCORSPreflightFallback(be backend.Backend, fallbackOrigin string) fiber.Handler {
|
||||
fallbackOrigin = strings.TrimSpace(fallbackOrigin)
|
||||
if fallbackOrigin == "" {
|
||||
return func(ctx *fiber.Ctx) error { return ctx.Next() }
|
||||
return func(ctx fiber.Ctx) error { return ctx.Next() }
|
||||
}
|
||||
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
bucket := ctx.Params("bucket")
|
||||
_, err := be.GetBucketCors(ctx.Context(), bucket)
|
||||
_, err := be.GetBucketCors(ctx.RequestCtx(), bucket)
|
||||
if err != nil {
|
||||
if s3Err, ok := err.(s3err.S3Error); ok && (s3Err.BaseError().Code == "NoSuchCORSConfiguration" || s3Err.BaseError().Code == "NoSuchBucket") {
|
||||
if len(ctx.Response().Header.Peek("Access-Control-Allow-Origin")) == 0 {
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
)
|
||||
@@ -43,7 +43,7 @@ func TestApplyBucketCORSPreflightFallback_NoBucketCors_Responds204(t *testing.T)
|
||||
app := fiber.New()
|
||||
app.Options("/:bucket",
|
||||
ApplyBucketCORSPreflightFallback(be, "https://example.com"),
|
||||
func(c *fiber.Ctx) error {
|
||||
func(c fiber.Ctx) error {
|
||||
// Should not be reached if fallback triggers
|
||||
return c.SendStatus(http.StatusTeapot)
|
||||
},
|
||||
@@ -87,7 +87,7 @@ func TestApplyBucketCORSPreflightFallback_NoSuchBucket_Responds204(t *testing.T)
|
||||
app := fiber.New()
|
||||
app.Options("/:bucket",
|
||||
ApplyBucketCORSPreflightFallback(be, "https://example.com"),
|
||||
func(c *fiber.Ctx) error {
|
||||
func(c fiber.Ctx) error {
|
||||
return c.SendStatus(http.StatusTeapot)
|
||||
},
|
||||
)
|
||||
@@ -127,7 +127,7 @@ func TestApplyBucketCORSPreflightFallback_BucketHasCors_CallsNext(t *testing.T)
|
||||
app := fiber.New()
|
||||
app.Options("/:bucket",
|
||||
ApplyBucketCORSPreflightFallback(be, "https://example.com"),
|
||||
func(c *fiber.Ctx) error {
|
||||
func(c fiber.Ctx) error {
|
||||
return c.SendStatus(http.StatusOK)
|
||||
},
|
||||
)
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
@@ -28,9 +28,9 @@ import (
|
||||
// Vary http response header is always the same below
|
||||
var VaryHdr = "Origin, Access-Control-Request-Headers, Access-Control-Request-Method"
|
||||
|
||||
type BucketResolver func(ctx *fiber.Ctx) (string, error)
|
||||
type BucketResolver func(ctx fiber.Ctx) (string, error)
|
||||
|
||||
func BucketFromPath(ctx *fiber.Ctx) (string, error) {
|
||||
func BucketFromPath(ctx fiber.Ctx) (string, error) {
|
||||
return ctx.Params("bucket"), nil
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ func BucketFromPath(ctx *fiber.Ctx) (string, error) {
|
||||
func ApplyBucketCORS(be backend.Backend, resolveBucket BucketResolver, fallbackOrigin string) fiber.Handler {
|
||||
fallbackOrigin = strings.TrimSpace(fallbackOrigin)
|
||||
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
origin := ctx.Get("Origin")
|
||||
// If neither Origin is present nor a fallback is configured, skip CORS entirely.
|
||||
if origin == "" && fallbackOrigin == "" {
|
||||
@@ -54,7 +54,7 @@ func ApplyBucketCORS(be backend.Backend, resolveBucket BucketResolver, fallbackO
|
||||
}
|
||||
|
||||
// if bucket cors is not set, skip the check
|
||||
data, err := be.GetBucketCors(ctx.Context(), bucket)
|
||||
data, err := be.GetBucketCors(ctx.RequestCtx(), bucket)
|
||||
if err != nil {
|
||||
// If CORS is not configured, S3Error will have code NoSuchCORSConfiguration.
|
||||
// In this case, we can safely continue. For any other error, we should log it.
|
||||
|
||||
@@ -17,7 +17,7 @@ package middlewares
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
// ApplyDefaultCORSPreflight responds to CORS preflight (OPTIONS) requests for routes
|
||||
@@ -29,10 +29,10 @@ import (
|
||||
func ApplyDefaultCORSPreflight(fallbackOrigin string) fiber.Handler {
|
||||
fallbackOrigin = strings.TrimSpace(fallbackOrigin)
|
||||
if fallbackOrigin == "" {
|
||||
return func(ctx *fiber.Ctx) error { return nil }
|
||||
return func(ctx fiber.Ctx) error { return nil }
|
||||
}
|
||||
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
if len(ctx.Response().Header.Peek("Access-Control-Allow-Origin")) == 0 {
|
||||
ctx.Response().Header.Add("Access-Control-Allow-Origin", fallbackOrigin)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
func TestApplyDefaultCORSPreflight_OptionsSetsPreflightHeaders(t *testing.T) {
|
||||
@@ -28,7 +28,7 @@ func TestApplyDefaultCORSPreflight_OptionsSetsPreflightHeaders(t *testing.T) {
|
||||
app.Options("/admin",
|
||||
ApplyDefaultCORSPreflight(origin),
|
||||
ApplyDefaultCORS(origin),
|
||||
func(c *fiber.Ctx) error { return nil },
|
||||
func(c fiber.Ctx) error { return nil },
|
||||
)
|
||||
|
||||
req, err := http.NewRequest(http.MethodOptions, "/admin", nil)
|
||||
|
||||
@@ -17,10 +17,10 @@ package middlewares
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
func ensureExposeETag(ctx *fiber.Ctx) {
|
||||
func ensureExposeETag(ctx fiber.Ctx) {
|
||||
existing := strings.TrimSpace(string(ctx.Response().Header.Peek("Access-Control-Expose-Headers")))
|
||||
defaults := []string{"ETag", "x-amz-storage-class"}
|
||||
if existing == "" {
|
||||
@@ -57,10 +57,10 @@ func ensureExposeETag(ctx *fiber.Ctx) {
|
||||
func ApplyDefaultCORS(fallbackOrigin string) fiber.Handler {
|
||||
fallbackOrigin = strings.TrimSpace(fallbackOrigin)
|
||||
if fallbackOrigin == "" {
|
||||
return func(ctx *fiber.Ctx) error { return nil }
|
||||
return func(ctx fiber.Ctx) error { return nil }
|
||||
}
|
||||
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
if len(ctx.Response().Header.Peek("Access-Control-Allow-Origin")) == 0 {
|
||||
ctx.Response().Header.Add("Access-Control-Allow-Origin", fallbackOrigin)
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
func TestApplyDefaultCORS_AddsHeaderWhenOriginSet(t *testing.T) {
|
||||
origin := "https://example.com"
|
||||
|
||||
app := fiber.New()
|
||||
app.Get("/admin", ApplyDefaultCORS(origin), func(c *fiber.Ctx) error {
|
||||
app.Get("/admin", ApplyDefaultCORS(origin), func(c fiber.Ctx) error {
|
||||
return c.SendStatus(http.StatusOK)
|
||||
})
|
||||
|
||||
@@ -52,10 +52,10 @@ func TestApplyDefaultCORS_DoesNotOverrideExistingHeader(t *testing.T) {
|
||||
origin := "https://example.com"
|
||||
|
||||
app := fiber.New()
|
||||
app.Get("/admin", func(c *fiber.Ctx) error {
|
||||
app.Get("/admin", func(c fiber.Ctx) error {
|
||||
c.Response().Header.Add("Access-Control-Allow-Origin", "https://already-set.com")
|
||||
return nil
|
||||
}, ApplyDefaultCORS(origin), func(c *fiber.Ctx) error {
|
||||
}, ApplyDefaultCORS(origin), func(c fiber.Ctx) error {
|
||||
return c.SendStatus(http.StatusOK)
|
||||
})
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
@@ -41,7 +41,7 @@ type RootUserConfig struct {
|
||||
func VerifyV4Signature(root RootUserConfig, iam auth.IAMService, region string, streamBody, requireContentSha256, allowDefaultRegion bool) fiber.Handler {
|
||||
acct := accounts{root: root, iam: iam}
|
||||
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
// The bucket is public, no need to check this signature
|
||||
if utils.ContextKeyPublicBucket.IsSet(ctx) {
|
||||
return nil
|
||||
@@ -178,7 +178,7 @@ func VerifyV4Signature(root RootUserConfig, iam auth.IAMService, region string,
|
||||
|
||||
if !utils.IsSpecialPayload(hashPayload) {
|
||||
// Calculate the hash of the request payload
|
||||
hashedPayload := sha256.Sum256(ctx.Body())
|
||||
hashedPayload := sha256.Sum256(ctx.BodyRaw())
|
||||
hexPayload := hex.EncodeToString(hashedPayload[:])
|
||||
|
||||
// Compare the calculated hash with the hash provided
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
)
|
||||
|
||||
@@ -85,7 +85,7 @@ func (rr *MockChecksumReader) Checksum() string {
|
||||
|
||||
var _ ChecksumReader = &MockChecksumReader{}
|
||||
|
||||
func wrapBodyReader(ctx *fiber.Ctx, wr func(io.Reader) io.Reader) {
|
||||
func wrapBodyReader(ctx fiber.Ctx, wr func(io.Reader) io.Reader) {
|
||||
rdr, ok := utils.ContextKeyBodyReader.Get(ctx).(io.Reader)
|
||||
if !ok {
|
||||
rdr = ctx.Request().BodyStream()
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
)
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
// BucketObjectNameValidator extracts and validates
|
||||
// the bucket and object names from the request URI.
|
||||
func BucketObjectNameValidator() fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
bucket, object := parsePath(ctx.Path())
|
||||
|
||||
// check if the provided bucket name is valid
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
)
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
// it wraps the body reader to handle Content-MD5:
|
||||
// the x-amz-checksum-* headers are explicitly processed by the backend.
|
||||
func VerifyChecksums(streamBody bool, requireBody bool, requireChecksum bool) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
md5sum := ctx.Get("Content-Md5")
|
||||
|
||||
if streamBody {
|
||||
@@ -58,7 +58,7 @@ func VerifyChecksums(streamBody bool, requireBody bool, requireChecksum bool) fi
|
||||
return nil
|
||||
}
|
||||
|
||||
body := ctx.Body()
|
||||
body := ctx.BodyRaw()
|
||||
if requireBody && len(body) == 0 {
|
||||
return s3err.GetAPIError(s3err.ErrMissingRequestBody)
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
// HostStyleParser is a middleware which parses the bucket name
|
||||
// from the 'Host' header and appends in the request URL path
|
||||
func HostStyleParser(virtualDomain string) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
host := string(ctx.Request().Host())
|
||||
// the host should match this pattern: '<bucket_name>.<virtual_domain>'
|
||||
bucket, _, found := strings.Cut(host, "."+virtualDomain)
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
)
|
||||
|
||||
func DebugLogger() fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
debuglogger.LogFiberRequestDetails(ctx)
|
||||
err := ctx.Next()
|
||||
debuglogger.LogFiberResponseDetails(ctx)
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
@@ -49,7 +49,7 @@ type PostObjectResult struct {
|
||||
func AuthorizePostObject(root RootUserConfig, iam auth.IAMService, region string) fiber.Handler {
|
||||
acct := accounts{root: root, iam: iam}
|
||||
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
contentLengthStr := ctx.Get("Content-Length")
|
||||
reqContentLength, err := strconv.ParseInt(contentLengthStr, 10, 64)
|
||||
if err != nil {
|
||||
@@ -71,7 +71,7 @@ func AuthorizePostObject(root RootUserConfig, iam auth.IAMService, region string
|
||||
|
||||
bodyRdr := ctx.Request().BodyStream()
|
||||
if bodyRdr == nil {
|
||||
bodyRdr = bytes.NewReader(ctx.Body())
|
||||
bodyRdr = bytes.NewReader(ctx.BodyRaw())
|
||||
}
|
||||
|
||||
mpParser, err := utils.NewMultipartParser(bodyRdr, boundary, reqContentLength)
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
@@ -37,7 +37,7 @@ import (
|
||||
// versitygw middlewares) returns nil without calling c.Next(), so they must
|
||||
// be chained explicitly rather than relying on fiber's c.Next() mechanism.
|
||||
func chainHandlers(handlers ...fiber.Handler) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
return func(c fiber.Ctx) error {
|
||||
for _, h := range handlers {
|
||||
if err := h(c); err != nil {
|
||||
return err
|
||||
@@ -51,7 +51,7 @@ func chainHandlers(handlers ...fiber.Handler) fiber.Handler {
|
||||
// the provided follow-up handler on POST /:bucket.
|
||||
func postObjectTestApp(root RootUserConfig, region string, next fiber.Handler) *fiber.App {
|
||||
app := fiber.New(fiber.Config{
|
||||
ErrorHandler: func(c *fiber.Ctx, err error) error {
|
||||
ErrorHandler: func(c fiber.Ctx, err error) error {
|
||||
if s3Err, ok := err.(s3err.S3Error); ok {
|
||||
return c.Status(s3Err.StatusCode()).Send(s3Err.XMLBody("", ""))
|
||||
}
|
||||
@@ -124,7 +124,7 @@ func TestAuthorizePostObject_AnonymousRequest(t *testing.T) {
|
||||
app := postObjectTestApp(
|
||||
RootUserConfig{Access: "root", Secret: "rootsecret"},
|
||||
"us-east-1",
|
||||
func(c *fiber.Ctx) error {
|
||||
func(c fiber.Ctx) error {
|
||||
gotResult = utils.ContextKeyObjectPostResult.Get(c).(PostObjectResult)
|
||||
gotAuthenticated = utils.ContextKeyAuthenticated.IsSet(c)
|
||||
return c.SendStatus(http.StatusOK)
|
||||
@@ -150,7 +150,7 @@ func TestAuthorizePostObject_AnonymousRequest_SetsPostObjectResult(t *testing.T)
|
||||
app := postObjectTestApp(
|
||||
RootUserConfig{Access: "root", Secret: "rootsecret"},
|
||||
"us-east-1",
|
||||
func(c *fiber.Ctx) error {
|
||||
func(c fiber.Ctx) error {
|
||||
gotResult = utils.ContextKeyObjectPostResult.Get(c).(PostObjectResult)
|
||||
return c.SendStatus(http.StatusOK)
|
||||
},
|
||||
@@ -194,7 +194,7 @@ func TestAuthorizePostObject_SignedRequest(t *testing.T) {
|
||||
app := postObjectTestApp(
|
||||
RootUserConfig{Access: accessKey, Secret: secretKey},
|
||||
region,
|
||||
func(c *fiber.Ctx) error {
|
||||
func(c fiber.Ctx) error {
|
||||
gotAuthenticated = utils.ContextKeyAuthenticated.IsSet(c)
|
||||
return c.SendStatus(http.StatusOK)
|
||||
},
|
||||
@@ -236,7 +236,7 @@ func TestAuthorizePostObject_SignedRequest_WrongSignature(t *testing.T) {
|
||||
app := postObjectTestApp(
|
||||
RootUserConfig{Access: accessKey, Secret: secretKey},
|
||||
region,
|
||||
func(c *fiber.Ctx) error { return c.SendStatus(http.StatusOK) },
|
||||
func(c fiber.Ctx) error { return c.SendStatus(http.StatusOK) },
|
||||
)
|
||||
|
||||
body, boundary := buildMultipartBody(t, map[string]string{
|
||||
@@ -259,7 +259,7 @@ func TestAuthorizePostObject_PartialAuthFields_ReturnsError(t *testing.T) {
|
||||
app := postObjectTestApp(
|
||||
RootUserConfig{Access: "root", Secret: "rootsecret"},
|
||||
"us-east-1",
|
||||
func(c *fiber.Ctx) error { return c.SendStatus(http.StatusOK) },
|
||||
func(c fiber.Ctx) error { return c.SendStatus(http.StatusOK) },
|
||||
)
|
||||
|
||||
// Only algorithm is provided — credential, date, policy, signature absent.
|
||||
@@ -279,7 +279,7 @@ func TestAuthorizePostObject_InvalidContentType_ReturnsError(t *testing.T) {
|
||||
app := postObjectTestApp(
|
||||
RootUserConfig{Access: "root", Secret: "rootsecret"},
|
||||
"us-east-1",
|
||||
func(c *fiber.Ctx) error { return c.SendStatus(http.StatusOK) },
|
||||
func(c fiber.Ctx) error { return c.SendStatus(http.StatusOK) },
|
||||
)
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, "/mybucket", strings.NewReader("body"))
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
func VerifyPresignedV4Signature(root RootUserConfig, iam auth.IAMService, region string, streamBody bool) fiber.Handler {
|
||||
acct := accounts{root: root, iam: iam}
|
||||
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
// The bucket is public, no need to check this signature
|
||||
if utils.ContextKeyPublicBucket.IsSet(ctx) {
|
||||
return nil
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/metrics"
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
// AuthorizePublicBucketAccess checks if the bucket grants public
|
||||
// access to anonymous requesters
|
||||
func AuthorizePublicBucketAccess(be backend.Backend, s3action string, policyPermission auth.Action, permission auth.Permission, region string, streamBody bool) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
// skip for authenticated requests
|
||||
if utils.IsPresignedURLAuth(ctx) || ctx.Get("Authorization") != "" || utils.ContextKeyAuthenticated.IsSet(ctx) {
|
||||
return nil
|
||||
@@ -57,7 +57,7 @@ func AuthorizePublicBucketAccess(be backend.Backend, s3action string, policyPerm
|
||||
}
|
||||
|
||||
bucket, object := parsePath(ctx.Path())
|
||||
err := auth.VerifyPublicAccess(ctx.Context(), be, policyPermission, permission, bucket, object)
|
||||
err := auth.VerifyPublicAccess(ctx.RequestCtx(), be, policyPermission, permission, bucket, object)
|
||||
if err != nil {
|
||||
if s3action == metrics.ActionHeadBucket {
|
||||
// add the bucket region header for HeadBucket
|
||||
@@ -114,7 +114,7 @@ func AuthorizePublicBucketAccess(be backend.Backend, s3action string, policyPerm
|
||||
|
||||
if payloadHash != "" {
|
||||
// Calculate the hash of the request payload
|
||||
hashedPayload := sha256.Sum256(ctx.Body())
|
||||
hashedPayload := sha256.Sum256(ctx.BodyRaw())
|
||||
hexPayload := hex.EncodeToString(hashedPayload[:])
|
||||
|
||||
// Compare the calculated hash with the hash provided
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/metrics"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
func RateLimiter(limit int, mm metrics.Manager, logger s3log.AuditLogger) fiber.Handler {
|
||||
sem := semaphore.NewWeighted(int64(limit))
|
||||
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
requestID, hostID := utils.EnsureRequestIDs(ctx)
|
||||
|
||||
if !sem.TryAcquire(1) {
|
||||
@@ -39,7 +39,7 @@ func RateLimiter(limit int, mm metrics.Manager, logger s3log.AuditLogger) fiber.
|
||||
mm.Send(ctx, err, metrics.ActionUndetected, 0, 0)
|
||||
}
|
||||
if logger != nil {
|
||||
logger.Log(ctx, err, ctx.Body(), s3log.LogMeta{
|
||||
logger.Log(ctx, err, ctx.BodyRaw(), s3log.LogMeta{
|
||||
Action: metrics.ActionUndetected,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
)
|
||||
|
||||
// RequestIDs sets requestID and hostID in context locals
|
||||
func RequestIDs() fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
utils.EnsureRequestIDs(ctx)
|
||||
return ctx.Next()
|
||||
}
|
||||
|
||||
@@ -20,15 +20,15 @@ import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
)
|
||||
|
||||
func TestRequestIDs(t *testing.T) {
|
||||
app := fiber.New()
|
||||
app.Use(RequestIDs())
|
||||
app.Get("/", func(ctx *fiber.Ctx) error {
|
||||
app.Use("*", RequestIDs())
|
||||
app.Get("/", func(ctx fiber.Ctx) error {
|
||||
assert.NotEmpty(t, utils.RequestID(ctx))
|
||||
assert.NotEmpty(t, utils.HostID(ctx))
|
||||
return ctx.SendStatus(http.StatusNoContent)
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
)
|
||||
|
||||
// Evaluates/Matches the provided requst query params
|
||||
func MatchQueryArgs(args ...string) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
if utils.ContextKeySkip.IsSet(ctx) {
|
||||
return ctx.Next()
|
||||
}
|
||||
@@ -37,7 +37,7 @@ func MatchQueryArgs(args ...string) fiber.Handler {
|
||||
|
||||
// Evaluates/Matches the requst header
|
||||
func MatchHeader(key string) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
if utils.ContextKeySkip.IsSet(ctx) {
|
||||
return ctx.Next()
|
||||
}
|
||||
@@ -53,7 +53,7 @@ func MatchHeader(key string) fiber.Handler {
|
||||
|
||||
// Evaluates/Matches the requst query param and value
|
||||
func MatchQueryArgWithValue(key, val string) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
if utils.ContextKeySkip.IsSet(ctx) {
|
||||
return ctx.Next()
|
||||
}
|
||||
|
||||
@@ -17,13 +17,13 @@ package middlewares
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/s3api/utils"
|
||||
)
|
||||
|
||||
func SetDefaultValues(root RootUserConfig, region string) fiber.Handler {
|
||||
return func(ctx *fiber.Ctx) error {
|
||||
return func(ctx fiber.Ctx) error {
|
||||
// These are necessary for the server access logs
|
||||
utils.ContextKeyRegion.Set(ctx, region)
|
||||
utils.ContextKeyStartTime.Set(ctx, time.Now())
|
||||
|
||||
@@ -17,12 +17,12 @@ package middlewares
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
// DecodeURL url path unescapes the request url for the gateway
|
||||
// to handle some special characters
|
||||
func DecodeURL(ctx *fiber.Ctx) error {
|
||||
func DecodeURL(ctx fiber.Ctx) error {
|
||||
unescp, err := url.PathUnescape(string(ctx.Request().URI().PathOriginal()))
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
+12
-12
@@ -17,7 +17,7 @@ package s3api
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/metrics"
|
||||
@@ -56,7 +56,7 @@ func (sa *S3ApiRouter) Init() {
|
||||
|
||||
// initialize global host-style parser middleware if virtual domain is specified
|
||||
if sa.virtualDomain != "" {
|
||||
sa.app.Use(middlewares.HostStyleParser(sa.virtualDomain))
|
||||
sa.app.Use("*", middlewares.HostStyleParser(sa.virtualDomain))
|
||||
}
|
||||
|
||||
if sa.WithAdmSrv {
|
||||
@@ -158,7 +158,7 @@ func (sa *S3ApiRouter) Init() {
|
||||
// copy source is not allowed on '/'
|
||||
sa.app.Get("/", middlewares.MatchHeader("X-Amz-Copy-Source"),
|
||||
controllers.ProcessHandlers(
|
||||
func(ctx *fiber.Ctx) (*controllers.Response, error) {
|
||||
func(ctx fiber.Ctx) (*controllers.Response, error) {
|
||||
return &controllers.Response{}, s3err.GetInvalidArgumentErr(s3err.InvalidArgCopySource, ctx.Get("X-Amz-Copy-Source"))
|
||||
},
|
||||
metrics.ActionUndetected,
|
||||
@@ -475,7 +475,7 @@ func (sa *S3ApiRouter) Init() {
|
||||
// copy source is not allowed on bucket HEAD operation
|
||||
bucketRouter.Head("/", middlewares.MatchHeader("X-Amz-Copy-Source"),
|
||||
controllers.ProcessHandlers(
|
||||
func(ctx *fiber.Ctx) (*controllers.Response, error) {
|
||||
func(ctx fiber.Ctx) (*controllers.Response, error) {
|
||||
return &controllers.Response{}, s3err.GetInvalidArgumentErr(s3err.InvalidArgCopySource, ctx.Get("X-Amz-Copy-Source"))
|
||||
},
|
||||
metrics.ActionUndetected,
|
||||
@@ -501,7 +501,7 @@ func (sa *S3ApiRouter) Init() {
|
||||
// copy source is not allowed on bucket DELETE operation
|
||||
bucketRouter.Delete("/", middlewares.MatchHeader("X-Amz-Copy-Source"),
|
||||
controllers.ProcessHandlers(
|
||||
func(ctx *fiber.Ctx) (*controllers.Response, error) {
|
||||
func(ctx fiber.Ctx) (*controllers.Response, error) {
|
||||
return &controllers.Response{}, s3err.GetInvalidArgumentErr(s3err.InvalidArgCopySource, ctx.Get("X-Amz-Copy-Source"))
|
||||
},
|
||||
metrics.ActionUndetected,
|
||||
@@ -697,7 +697,7 @@ func (sa *S3ApiRouter) Init() {
|
||||
// copy source is not allowed on bucket GET operation
|
||||
bucketRouter.Get("/", middlewares.MatchHeader("X-Amz-Copy-Source"),
|
||||
controllers.ProcessHandlers(
|
||||
func(ctx *fiber.Ctx) (*controllers.Response, error) {
|
||||
func(ctx fiber.Ctx) (*controllers.Response, error) {
|
||||
return &controllers.Response{}, s3err.GetInvalidArgumentErr(s3err.InvalidArgCopySource, ctx.Get("X-Amz-Copy-Source"))
|
||||
},
|
||||
metrics.ActionUndetected,
|
||||
@@ -1102,7 +1102,7 @@ func (sa *S3ApiRouter) Init() {
|
||||
middlewares.MatchHeader("X-Amz-Copy-Source"),
|
||||
middlewares.MatchQueryArgs("uploadId"),
|
||||
controllers.ProcessHandlers(
|
||||
func(ctx *fiber.Ctx) (*controllers.Response, error) {
|
||||
func(ctx fiber.Ctx) (*controllers.Response, error) {
|
||||
return &controllers.Response{}, s3err.GetInvalidArgumentErr(s3err.InvalidArgCopySource, ctx.Get("X-Amz-Copy-Source"))
|
||||
},
|
||||
metrics.ActionUndetected,
|
||||
@@ -1142,7 +1142,7 @@ func (sa *S3ApiRouter) Init() {
|
||||
objectRouter.Head("/",
|
||||
middlewares.MatchHeader("X-Amz-Copy-Source"),
|
||||
controllers.ProcessHandlers(
|
||||
func(ctx *fiber.Ctx) (*controllers.Response, error) {
|
||||
func(ctx fiber.Ctx) (*controllers.Response, error) {
|
||||
return &controllers.Response{}, s3err.GetInvalidArgumentErr(s3err.InvalidArgCopySource, ctx.Get("X-Amz-Copy-Source"))
|
||||
},
|
||||
metrics.ActionUndetected,
|
||||
@@ -1182,7 +1182,7 @@ func (sa *S3ApiRouter) Init() {
|
||||
objectRouter.Get("/",
|
||||
middlewares.MatchHeader("X-Amz-Copy-Source"),
|
||||
controllers.ProcessHandlers(
|
||||
func(ctx *fiber.Ctx) (*controllers.Response, error) {
|
||||
func(ctx fiber.Ctx) (*controllers.Response, error) {
|
||||
return &controllers.Response{}, s3err.GetInvalidArgumentErr(s3err.InvalidArgCopySource, ctx.Get("X-Amz-Copy-Source"))
|
||||
},
|
||||
metrics.ActionUndetected,
|
||||
@@ -1287,7 +1287,7 @@ func (sa *S3ApiRouter) Init() {
|
||||
objectRouter.Delete("/",
|
||||
middlewares.MatchHeader("X-Amz-Copy-Source"),
|
||||
controllers.ProcessHandlers(
|
||||
func(ctx *fiber.Ctx) (*controllers.Response, error) {
|
||||
func(ctx fiber.Ctx) (*controllers.Response, error) {
|
||||
return &controllers.Response{}, s3err.GetInvalidArgumentErr(s3err.InvalidArgCopySource, ctx.Get("X-Amz-Copy-Source"))
|
||||
},
|
||||
metrics.ActionUndetected,
|
||||
@@ -1341,7 +1341,7 @@ func (sa *S3ApiRouter) Init() {
|
||||
middlewares.MatchHeader("X-Amz-Copy-Source"),
|
||||
middlewares.MatchQueryArgs("uploadId"),
|
||||
controllers.ProcessHandlers(
|
||||
func(ctx *fiber.Ctx) (*controllers.Response, error) {
|
||||
func(ctx fiber.Ctx) (*controllers.Response, error) {
|
||||
return &controllers.Response{}, s3err.GetInvalidArgumentErr(s3err.InvalidArgCopySource, ctx.Get("X-Amz-Copy-Source"))
|
||||
},
|
||||
metrics.ActionUndetected,
|
||||
@@ -1561,7 +1561,7 @@ func (sa *S3ApiRouter) Init() {
|
||||
)
|
||||
|
||||
// Return MethodNotAllowed for all the unmatched routes
|
||||
sa.app.All("*", controllers.ProcessHandlers(func(ctx *fiber.Ctx) (*controllers.Response, error) {
|
||||
sa.app.All("*", controllers.ProcessHandlers(func(ctx fiber.Ctx) (*controllers.Response, error) {
|
||||
return &controllers.Response{}, s3err.GetMethodNotAllowedErr(ctx.Method(), s3err.ResourceTypeService, nil)
|
||||
}, metrics.ActionUndetected, services))
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
|
||||
@@ -17,7 +17,7 @@ package s3api
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
)
|
||||
|
||||
+71
-30
@@ -23,9 +23,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/gofiber/fiber/v3/middleware/logger"
|
||||
"github.com/gofiber/fiber/v3/middleware/recover"
|
||||
"github.com/valyala/fasthttp"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
@@ -40,7 +41,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
shutDownDuration = time.Second * 10
|
||||
shutDownDuration = time.Second * 10
|
||||
requestHeaderMaxSize = 8 * 1024
|
||||
)
|
||||
|
||||
type S3ApiServer struct {
|
||||
@@ -102,25 +104,24 @@ func New(
|
||||
}
|
||||
|
||||
app := fiber.New(fiber.Config{
|
||||
AppName: "versitygw",
|
||||
ServerHeader: "VERSITYGW",
|
||||
StreamRequestBody: true,
|
||||
DisableKeepalive: !server.keepAlive,
|
||||
Network: fiber.NetworkTCP,
|
||||
DisableStartupMessage: true,
|
||||
ErrorHandler: globalErrorHandler,
|
||||
Concurrency: server.maxConnections,
|
||||
AppName: "versitygw",
|
||||
ServerHeader: "VERSITYGW",
|
||||
StreamRequestBody: true,
|
||||
DisableKeepalive: !server.keepAlive,
|
||||
ErrorHandler: globalErrorHandler,
|
||||
Concurrency: server.maxConnections,
|
||||
// Sets buffer limit to read/parse incoming requests
|
||||
// if the limit is reached, fiber/fasthttp will throw an error
|
||||
// in the global error handler
|
||||
ReadBufferSize: 8 * 1024, // 8 KB
|
||||
ReadBufferSize: requestHeaderMaxSize,
|
||||
})
|
||||
installRequestHeaderLimitErrorHandler(app)
|
||||
|
||||
server.app = app
|
||||
server.Router.app = app
|
||||
|
||||
// initialize the panic recovery middleware
|
||||
app.Use(recover.New(
|
||||
app.Use("*", recover.New(
|
||||
recover.Config{
|
||||
EnableStackTrace: true,
|
||||
StackTraceHandler: stackTraceHandler,
|
||||
@@ -128,35 +129,41 @@ func New(
|
||||
|
||||
// Logging middlewares
|
||||
if !server.quiet {
|
||||
app.Use(logger.New(logger.Config{
|
||||
app.Use("*", logger.New(logger.Config{
|
||||
Format: "${time} | vgw | ${status} | ${latency} | ${ip} | ${method} | ${path} | ${error} | ${queryParams}\n",
|
||||
}))
|
||||
}
|
||||
|
||||
// initialize requestId middleware
|
||||
app.Use(middlewares.RequestIDs())
|
||||
app.Use("*", middlewares.RequestIDs())
|
||||
|
||||
// Set up health endpoint if specified
|
||||
if server.health != "" {
|
||||
app.Get(server.health, func(ctx *fiber.Ctx) error {
|
||||
app.Get(server.health, func(ctx fiber.Ctx) error {
|
||||
return ctx.SendStatus(http.StatusOK)
|
||||
})
|
||||
}
|
||||
|
||||
// Set up WebUI on the S3 port if configured
|
||||
if server.webuiSrvCfg != nil {
|
||||
webui.MountOn(app, server.webuiMountPrefix, server.webuiSrvCfg)
|
||||
if err := webui.MountOn(app, server.webuiMountPrefix, server.webuiSrvCfg); err != nil {
|
||||
return nil, fmt.Errorf("mount webui: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// initialize total requests cap limiter middleware
|
||||
app.Use(middlewares.RateLimiter(server.maxRequests, mm, l))
|
||||
app.Use("*", middlewares.RateLimiter(server.maxRequests, mm, l))
|
||||
|
||||
for _, route := range server.routes {
|
||||
method, err := validateRouteMount(route)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app.Add(method, route.path, route.handlers...)
|
||||
handlers := make([]any, len(route.handlers)-1)
|
||||
for i := range handlers {
|
||||
handlers[i] = route.handlers[i+1]
|
||||
}
|
||||
app.Add([]string{method}, route.path, route.handlers[0], handlers...)
|
||||
}
|
||||
|
||||
for _, mount := range server.middlewares {
|
||||
@@ -167,15 +174,15 @@ func New(
|
||||
}
|
||||
|
||||
// initilaze the default value setter middleware
|
||||
app.Use(middlewares.SetDefaultValues(root, region))
|
||||
app.Use("*", middlewares.SetDefaultValues(root, region))
|
||||
|
||||
// initialize the 'DecodeURL' middleware which
|
||||
// path unescapes the url
|
||||
app.Use(controllers.WrapMiddleware(middlewares.DecodeURL, l, mm))
|
||||
app.Use("*", controllers.WrapMiddleware(middlewares.DecodeURL, l, mm))
|
||||
|
||||
// initialize the debug logger in debug mode
|
||||
if debuglogger.IsDebugEnabled() {
|
||||
app.Use(middlewares.DebugLogger())
|
||||
app.Use("*", middlewares.DebugLogger())
|
||||
}
|
||||
|
||||
server.Router.Init()
|
||||
@@ -357,9 +364,9 @@ func (sa *S3ApiServer) ServeMultiPort(ports []string) error {
|
||||
var err error
|
||||
|
||||
if sa.CertStorage != nil {
|
||||
ln, err = utils.NewMultiAddrTLSListener(sa.app.Config().Network, portSpec, sa.CertStorage.GetCertificate, utils.ListenerOptions{SocketPerm: sa.socketPerm})
|
||||
ln, err = utils.NewMultiAddrTLSListener(fiber.NetworkTCP, portSpec, sa.CertStorage.GetCertificate, utils.ListenerOptions{SocketPerm: sa.socketPerm})
|
||||
} else {
|
||||
ln, err = utils.NewMultiAddrListener(sa.app.Config().Network, portSpec, utils.ListenerOptions{SocketPerm: sa.socketPerm})
|
||||
ln, err = utils.NewMultiAddrListener(fiber.NetworkTCP, portSpec, utils.ListenerOptions{SocketPerm: sa.socketPerm})
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to bind s3 listener %s: %w", portSpec, err)
|
||||
@@ -383,7 +390,9 @@ func (sa *S3ApiServer) ServeMultiPort(ports []string) error {
|
||||
})
|
||||
}
|
||||
|
||||
return sa.app.Listener(finalListener)
|
||||
return sa.app.Listener(finalListener, fiber.ListenConfig{
|
||||
DisableStartupMessage: true,
|
||||
})
|
||||
}
|
||||
|
||||
// ShutDown gracefully shuts down the server with a context timeout
|
||||
@@ -393,13 +402,45 @@ func (sa *S3ApiServer) ShutDown() error {
|
||||
|
||||
// stackTraceHandler stores the system panics
|
||||
// in the context locals
|
||||
func stackTraceHandler(ctx *fiber.Ctx, e any) {
|
||||
func stackTraceHandler(ctx fiber.Ctx, e any) {
|
||||
utils.ContextKeyStack.Set(ctx, e)
|
||||
}
|
||||
|
||||
// installRequestHeaderLimitErrorHandler converts fasthttp small-buffer errors
|
||||
// into the S3 RequestHeaderSectionTooLarge response.
|
||||
//
|
||||
// This is a temporary solution until Fiber handles request header limit errors
|
||||
// before response writes correctly. See:
|
||||
// https://github.com/gofiber/fiber/issues/4423
|
||||
func installRequestHeaderLimitErrorHandler(app *fiber.App) {
|
||||
server := app.Server()
|
||||
fiberErrorHandler := server.ErrorHandler
|
||||
server.ErrorHandler = func(ctx *fasthttp.RequestCtx, err error) {
|
||||
var smallBufferErr *fasthttp.ErrSmallBuffer
|
||||
if errors.As(err, &smallBufferErr) {
|
||||
debuglogger.Logf("total request headers size exceeds the allowed 8KB")
|
||||
|
||||
requestID := utils.NewS3RequestID()
|
||||
hostID := utils.NewS3HostID()
|
||||
apiErr := s3err.GetRequestHeaderSectionTooLargeErr(requestHeaderMaxSize)
|
||||
|
||||
ctx.Response.Reset()
|
||||
ctx.Response.Header.SetContentType(fiber.MIMEApplicationXML)
|
||||
ctx.Response.Header.Set(utils.HeaderAmzRequestID, requestID)
|
||||
ctx.Response.Header.Set(utils.HeaderAmzID2, hostID)
|
||||
ctx.SetStatusCode(apiErr.StatusCode())
|
||||
ctx.SetConnectionClose()
|
||||
ctx.SetBody(apiErr.XMLBody(requestID, hostID))
|
||||
return
|
||||
}
|
||||
|
||||
fiberErrorHandler(ctx, err)
|
||||
}
|
||||
}
|
||||
|
||||
// globalErrorHandler catches the errors before reaching to
|
||||
// the handlers and any system panics
|
||||
func globalErrorHandler(ctx *fiber.Ctx, er error) error {
|
||||
func globalErrorHandler(ctx fiber.Ctx, er error) error {
|
||||
requestID, hostID := utils.EnsureRequestIDs(ctx)
|
||||
|
||||
// set content type to application/xml
|
||||
@@ -416,8 +457,8 @@ func globalErrorHandler(ctx *fiber.Ctx, er error) error {
|
||||
if errors.As(er, &fiberErr) {
|
||||
if errors.Is(fiberErr, fiber.ErrRequestHeaderFieldsTooLarge) {
|
||||
debuglogger.Logf("total request headers size exceeds the allowed 8KB")
|
||||
ctx.Status(http.StatusBadRequest)
|
||||
return nil
|
||||
err := s3err.GetRequestHeaderSectionTooLargeErr(requestHeaderMaxSize)
|
||||
return ctx.Status(err.StatusCode()).Send(err.XMLBody(requestID, hostID))
|
||||
}
|
||||
if strings.Contains(fiberErr.Message, "cannot parse Content-Length") {
|
||||
debuglogger.Logf("failed to parse Content-Length")
|
||||
|
||||
@@ -20,8 +20,9 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/auth"
|
||||
"github.com/versity/versitygw/backend"
|
||||
"github.com/versity/versitygw/s3api/middlewares"
|
||||
@@ -87,10 +88,10 @@ func TestWithRouteRegistersBeforeMiddleware(t *testing.T) {
|
||||
|
||||
middlewareCalled := false
|
||||
server, err := newTestS3ApiServer(
|
||||
WithRoute(http.MethodGet, routePath, func(ctx *fiber.Ctx) error {
|
||||
WithRoute(http.MethodGet, routePath, func(ctx fiber.Ctx) error {
|
||||
return ctx.SendStatus(http.StatusNoContent)
|
||||
}),
|
||||
WithMiddleware("/", func(ctx *fiber.Ctx) error {
|
||||
WithMiddleware("/", func(ctx fiber.Ctx) error {
|
||||
middlewareCalled = true
|
||||
return ctx.SendStatus(http.StatusMisdirectedRequest)
|
||||
}),
|
||||
@@ -126,7 +127,7 @@ func TestWithRouteRegistersAfterRateLimiter(t *testing.T) {
|
||||
|
||||
server, err := newTestS3ApiServer(
|
||||
WithConcurrencyLimiter(10, 1),
|
||||
WithRoute(http.MethodGet, routePath, func(ctx *fiber.Ctx) error {
|
||||
WithRoute(http.MethodGet, routePath, func(ctx fiber.Ctx) error {
|
||||
once.Do(func() {
|
||||
close(started)
|
||||
})
|
||||
@@ -139,7 +140,7 @@ func TestWithRouteRegistersAfterRateLimiter(t *testing.T) {
|
||||
}
|
||||
|
||||
go func() {
|
||||
resp, err := server.app.Test(httptest.NewRequest(http.MethodGet, routePath, nil), -1)
|
||||
resp, err := server.app.Test(httptest.NewRequest(http.MethodGet, routePath, nil), fiber.TestConfig{Timeout: 0, FailOnTimeout: false})
|
||||
if err != nil {
|
||||
firstDone <- err
|
||||
return
|
||||
@@ -154,7 +155,7 @@ func TestWithRouteRegistersAfterRateLimiter(t *testing.T) {
|
||||
|
||||
<-started
|
||||
|
||||
resp, err := server.app.Test(httptest.NewRequest(http.MethodGet, routePath, nil), 100)
|
||||
resp, err := server.app.Test(httptest.NewRequest(http.MethodGet, routePath, nil), fiber.TestConfig{Timeout: time.Duration(100) * time.Millisecond})
|
||||
if err != nil {
|
||||
close(release)
|
||||
t.Fatalf("second app.Test() error = %v", err)
|
||||
@@ -172,7 +173,7 @@ func TestWithRouteRegistersAfterRateLimiter(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCustomMountValidation(t *testing.T) {
|
||||
validHandler := func(ctx *fiber.Ctx) error {
|
||||
validHandler := func(ctx fiber.Ctx) error {
|
||||
return ctx.SendStatus(http.StatusNoContent)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/smithy-go/logging"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
v4 "github.com/versity/versitygw/aws/signer/v4"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
@@ -53,7 +53,7 @@ const (
|
||||
)
|
||||
|
||||
// CheckValidSignature validates the ctx v4 auth signature
|
||||
func CheckValidSignature(ctx *fiber.Ctx, auth AuthData, secret, checksum string, tdate time.Time, contentLen int64) (string, error) {
|
||||
func CheckValidSignature(ctx fiber.Ctx, auth AuthData, secret, checksum string, tdate time.Time, contentLen int64) (string, error) {
|
||||
signedHdrs := strings.Split(auth.SignedHeaders, ";")
|
||||
|
||||
// Create a new http request instance from fasthttp request
|
||||
|
||||
@@ -20,7 +20,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/valyala/fasthttp"
|
||||
"github.com/valyala/fasthttp/fasthttputil"
|
||||
v4 "github.com/versity/versitygw/aws/signer/v4"
|
||||
)
|
||||
@@ -84,14 +85,14 @@ func Test_Client_UserAgent(t *testing.T) {
|
||||
expectedSig := "37a35d96998d786113ad420c57c22c5433f6aca74f88f26566caa047fc3601c6"
|
||||
dateStr := "20240206T210328Z"
|
||||
|
||||
app := fiber.New(fiber.Config{DisableStartupMessage: true})
|
||||
app := fiber.New(fiber.Config{})
|
||||
|
||||
tdate, err := time.Parse(iso8601Format, dateStr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
app.Get("/", func(c *fiber.Ctx) error {
|
||||
app.Get("/", func(c fiber.Ctx) error {
|
||||
req, err := createHttpRequestFromCtx(c, signedHdrs, int64(c.Request().Header.ContentLength()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -135,10 +136,18 @@ func Test_Client_UserAgent(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
|
||||
c := fiber.AcquireClient()
|
||||
c.UserAgent = agent
|
||||
a := c.Get("http://example.com")
|
||||
a.HostClient.Dial = func(_ string) (net.Conn, error) { return ln.Dial() }
|
||||
a.String()
|
||||
fiber.ReleaseClient(c)
|
||||
client := fasthttp.Client{
|
||||
Dial: func(_ string) (net.Conn, error) { return ln.Dial() },
|
||||
}
|
||||
|
||||
req := fasthttp.AcquireRequest()
|
||||
resp := fasthttp.AcquireResponse()
|
||||
defer fasthttp.ReleaseRequest(req)
|
||||
defer fasthttp.ReleaseResponse(resp)
|
||||
|
||||
req.SetRequestURI("http://example.com")
|
||||
req.Header.SetUserAgent(agent)
|
||||
if err := client.Do(req, resp); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
)
|
||||
@@ -100,7 +100,7 @@ func (c checksumType) isValid() bool {
|
||||
}
|
||||
|
||||
// Extracts and validates the checksum type from the 'X-Amz-Trailer' header
|
||||
func ExtractChecksumType(ctx *fiber.Ctx) (checksumType, error) {
|
||||
func ExtractChecksumType(ctx fiber.Ctx) (checksumType, error) {
|
||||
trailer := ctx.Get("X-Amz-Trailer")
|
||||
chType := checksumType(strings.ToLower(trailer))
|
||||
if chType != "" && !chType.isValid() {
|
||||
@@ -172,7 +172,7 @@ func IsStreamingPayload(str string) bool {
|
||||
|
||||
// ParseDecodedContentLength extracts and validates the
|
||||
// 'x-amz-decoded-content-length' from fiber context
|
||||
func ParseDecodedContentLength(ctx *fiber.Ctx) (int64, error) {
|
||||
func ParseDecodedContentLength(ctx fiber.Ctx) (int64, error) {
|
||||
decContLengthStr := ctx.Get("X-Amz-Decoded-Content-Length")
|
||||
if decContLengthStr == "" {
|
||||
debuglogger.Logf("missing required header 'X-Amz-Decoded-Content-Length'")
|
||||
@@ -192,7 +192,7 @@ func ParseDecodedContentLength(ctx *fiber.Ctx) (int64, error) {
|
||||
return decContLength, nil
|
||||
}
|
||||
|
||||
func NewChunkReader(ctx *fiber.Ctx, r io.Reader, authdata AuthData, canonicalString, secret string, date time.Time) (io.Reader, error) {
|
||||
func NewChunkReader(ctx fiber.Ctx, r io.Reader, authdata AuthData, canonicalString, secret string, date time.Time) (io.Reader, error) {
|
||||
cLength, err := ParseDecodedContentLength(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
// Region, StartTime, IsRoot, Account, AccessKey context locals
|
||||
@@ -43,19 +43,19 @@ const (
|
||||
ContextKeyWebsiteConfig ContextKey = "website-config"
|
||||
)
|
||||
|
||||
func (ck ContextKey) Set(ctx *fiber.Ctx, val any) {
|
||||
func (ck ContextKey) Set(ctx fiber.Ctx, val any) {
|
||||
ctx.Locals(string(ck), val)
|
||||
}
|
||||
|
||||
func (ck ContextKey) IsSet(ctx *fiber.Ctx) bool {
|
||||
func (ck ContextKey) IsSet(ctx fiber.Ctx) bool {
|
||||
val := ctx.Locals(string(ck))
|
||||
return val != nil
|
||||
}
|
||||
|
||||
func (ck ContextKey) Delete(ctx *fiber.Ctx) {
|
||||
func (ck ContextKey) Delete(ctx fiber.Ctx) {
|
||||
ctx.Locals(string(ck), nil)
|
||||
}
|
||||
|
||||
func (ck ContextKey) Get(ctx *fiber.Ctx) any {
|
||||
func (ck ContextKey) Get(ctx fiber.Ctx) any {
|
||||
return ctx.Locals(string(ck))
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
)
|
||||
|
||||
@@ -45,7 +45,7 @@ func WithCopySource() preconditionOpt {
|
||||
// - If-None-Match
|
||||
// - If-Modified-Since
|
||||
// - If-Unmodified-Since
|
||||
func ParsePreconditionHeaders(ctx *fiber.Ctx, opts ...preconditionOpt) ConditionalHeaders {
|
||||
func ParsePreconditionHeaders(ctx fiber.Ctx, opts ...preconditionOpt) ConditionalHeaders {
|
||||
ifMatch, ifNoneMatch := ParsePreconditionMatchHeaders(ctx, opts...)
|
||||
ifModSince, ifUnmodeSince := ParsePreconditionDateHeaders(ctx, opts...)
|
||||
|
||||
@@ -58,7 +58,7 @@ func ParsePreconditionHeaders(ctx *fiber.Ctx, opts ...preconditionOpt) Condition
|
||||
}
|
||||
|
||||
// ParsePreconditionMatchHeaders extracts "If-Match" and "If-None-Match" headers from fiber Ctx
|
||||
func ParsePreconditionMatchHeaders(ctx *fiber.Ctx, opts ...preconditionOpt) (*string, *string) {
|
||||
func ParsePreconditionMatchHeaders(ctx fiber.Ctx, opts ...preconditionOpt) (*string, *string) {
|
||||
cfg := new(precondtionCfg)
|
||||
for _, opt := range opts {
|
||||
opt(cfg)
|
||||
@@ -75,7 +75,7 @@ func ParsePreconditionMatchHeaders(ctx *fiber.Ctx, opts ...preconditionOpt) (*st
|
||||
|
||||
// ParsePreconditionDateHeaders parses the "If-Modified-Since" and "If-Unmodified-Since"
|
||||
// headers from fiber context to *time.Time
|
||||
func ParsePreconditionDateHeaders(ctx *fiber.Ctx, opts ...preconditionOpt) (*time.Time, *time.Time) {
|
||||
func ParsePreconditionDateHeaders(ctx fiber.Ctx, opts ...preconditionOpt) (*time.Time, *time.Time) {
|
||||
cfg := new(precondtionCfg)
|
||||
for _, opt := range opts {
|
||||
opt(cfg)
|
||||
@@ -129,7 +129,7 @@ func ParsePreconditionDateHeader(date string) *time.Time {
|
||||
|
||||
// ParseIfMatchSize parses the 'x-amz-if-match-size' to *int64
|
||||
// if parsing fails, returns nil
|
||||
func ParseIfMatchSize(ctx *fiber.Ctx) *int64 {
|
||||
func ParseIfMatchSize(ctx fiber.Ctx) *int64 {
|
||||
ifMatchSizeHdr := ctx.Get("x-amz-if-match-size")
|
||||
if ifMatchSizeHdr == "" {
|
||||
return nil
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/smithy-go/logging"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
v4 "github.com/versity/versitygw/aws/signer/v4"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
"github.com/versity/versitygw/s3err"
|
||||
@@ -38,7 +38,7 @@ const (
|
||||
)
|
||||
|
||||
// CheckPresignedSignature validates presigned request signature
|
||||
func CheckPresignedSignature(ctx *fiber.Ctx, auth AuthData, secret string) error {
|
||||
func CheckPresignedSignature(ctx fiber.Ctx, auth AuthData, secret string) error {
|
||||
signedHdrs := strings.Split(auth.SignedHeaders, ";")
|
||||
|
||||
var contentLength int64
|
||||
@@ -60,7 +60,7 @@ func CheckPresignedSignature(ctx *fiber.Ctx, auth AuthData, secret string) error
|
||||
date, _ := time.Parse(iso8601Format, auth.Date)
|
||||
|
||||
signer := v4.NewSigner()
|
||||
uri, _, signMeta, signErr := signer.PresignHTTP(ctx.Context(), aws.Credentials{
|
||||
uri, _, signMeta, signErr := signer.PresignHTTP(ctx.RequestCtx(), aws.Credentials{
|
||||
AccessKeyID: auth.Access,
|
||||
SecretAccessKey: secret,
|
||||
}, req, unsignedPayload, service, auth.Region, date, signedHdrs, func(options *v4.SignerOptions) {
|
||||
@@ -104,7 +104,7 @@ func CheckPresignedSignature(ctx *fiber.Ctx, auth AuthData, secret string) error
|
||||
// &X-Amz-Expires=86400
|
||||
// &X-Amz-SignedHeaders=host
|
||||
// &X-Amz-Signature=1e68ad45c1db540284a4a1eca3884c293ba1a0ff63ab9db9a15b5b29dfa02cd8
|
||||
func ParsePresignedURIParts(ctx *fiber.Ctx, region string) (AuthData, error) {
|
||||
func ParsePresignedURIParts(ctx fiber.Ctx, region string) (AuthData, error) {
|
||||
a := AuthData{}
|
||||
|
||||
// Get and verify algorithm query parameter
|
||||
@@ -218,7 +218,7 @@ func validateAlgorithm(algo string) error {
|
||||
|
||||
// IsPresignedURLAuth determines if the request is presigned:
|
||||
// which is authorization with query params
|
||||
func IsPresignedURLAuth(ctx *fiber.Ctx) bool {
|
||||
func IsPresignedURLAuth(ctx fiber.Ctx) bool {
|
||||
algo := ctx.Query("X-Amz-Algorithm")
|
||||
creds := ctx.Query("X-Amz-Credential")
|
||||
signature := ctx.Query("X-Amz-Signature")
|
||||
@@ -230,7 +230,7 @@ func IsPresignedURLAuth(ctx *fiber.Ctx) bool {
|
||||
|
||||
// IsPresignedURLAuthV2 determines if the request is
|
||||
// query-string signed with aws v2 signer
|
||||
func IsPresignedURLAuthV2(ctx *fiber.Ctx) bool {
|
||||
func IsPresignedURLAuthV2(ctx fiber.Ctx) bool {
|
||||
expires := ctx.Query("Expires")
|
||||
access := ctx.Query("AWSAccessKeyId")
|
||||
signature := ctx.Query("Signature")
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
)
|
||||
|
||||
@@ -70,7 +70,7 @@ func NewS3HostID() string {
|
||||
// EnsureRequestIDs makes sure the request-local IDs exist and are present
|
||||
// in the response headers. Existing local values are reused so headers and XML
|
||||
// bodies stay consistent throughout the request.
|
||||
func EnsureRequestIDs(ctx *fiber.Ctx) (requestID, hostID string) {
|
||||
func EnsureRequestIDs(ctx fiber.Ctx) (requestID, hostID string) {
|
||||
requestID = RequestID(ctx)
|
||||
if requestID == "" {
|
||||
requestID = NewS3RequestID()
|
||||
@@ -89,7 +89,7 @@ func EnsureRequestIDs(ctx *fiber.Ctx) (requestID, hostID string) {
|
||||
return requestID, hostID
|
||||
}
|
||||
|
||||
func RequestID(ctx *fiber.Ctx) string {
|
||||
func RequestID(ctx fiber.Ctx) string {
|
||||
requestID, _ := ContextKeyRequestID.Get(ctx).(string)
|
||||
if requestID != "" {
|
||||
return requestID
|
||||
@@ -98,7 +98,7 @@ func RequestID(ctx *fiber.Ctx) string {
|
||||
return string(ctx.Response().Header.Peek(HeaderAmzRequestID))
|
||||
}
|
||||
|
||||
func HostID(ctx *fiber.Ctx) string {
|
||||
func HostID(ctx fiber.Ctx) string {
|
||||
hostID, _ := ContextKeyHostID.Get(ctx).(string)
|
||||
if hostID != "" {
|
||||
return hostID
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/valyala/fasthttp"
|
||||
v4 "github.com/versity/versitygw/aws/signer/v4"
|
||||
@@ -151,7 +151,7 @@ func buildPresignedURL(t *testing.T, headers http.Header) string {
|
||||
return signedURL
|
||||
}
|
||||
|
||||
func signedHeaderAuthCtx(t *testing.T, signedHeaders, extraHeaders http.Header) (*fiber.Ctx, AuthData, time.Time) {
|
||||
func signedHeaderAuthCtx(t *testing.T, signedHeaders, extraHeaders http.Header) (fiber.Ctx, AuthData, time.Time) {
|
||||
t.Helper()
|
||||
|
||||
signingTime := time.Now().UTC()
|
||||
@@ -192,7 +192,7 @@ func signedHeaderAuthCtx(t *testing.T, signedHeaders, extraHeaders http.Header)
|
||||
return ctx, authData, signingTime
|
||||
}
|
||||
|
||||
func fiberCtxFromURL(t *testing.T, method, rawURL string, headers http.Header) *fiber.Ctx {
|
||||
func fiberCtxFromURL(t *testing.T, method, rawURL string, headers http.Header) fiber.Ctx {
|
||||
t.Helper()
|
||||
|
||||
parsedURL, err := url.Parse(rawURL)
|
||||
|
||||
+19
-19
@@ -32,7 +32,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/valyala/fasthttp"
|
||||
signerV4 "github.com/versity/versitygw/aws/signer/v4"
|
||||
"github.com/versity/versitygw/debuglogger"
|
||||
@@ -135,7 +135,7 @@ func ExtractMetadataFromFields(fields map[string]string) (map[string]string, err
|
||||
return metadata, nil
|
||||
}
|
||||
|
||||
func createHttpRequestFromCtx(ctx *fiber.Ctx, signedHdrs []string, contentLength int64) (*http.Request, error) {
|
||||
func createHttpRequestFromCtx(ctx fiber.Ctx, signedHdrs []string, contentLength int64) (*http.Request, error) {
|
||||
req := ctx.Request()
|
||||
|
||||
uri := ctx.OriginalURL()
|
||||
@@ -180,7 +180,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func createPresignedHttpRequestFromCtx(ctx *fiber.Ctx, signedHdrs []string, contentLength int64) (*http.Request, error) {
|
||||
func createPresignedHttpRequestFromCtx(ctx fiber.Ctx, signedHdrs []string, contentLength int64) (*http.Request, error) {
|
||||
req := ctx.Request()
|
||||
|
||||
uri, _, _ := strings.Cut(ctx.OriginalURL(), "?")
|
||||
@@ -221,7 +221,7 @@ func createPresignedHttpRequestFromCtx(ctx *fiber.Ctx, signedHdrs []string, cont
|
||||
return httpReq, nil
|
||||
}
|
||||
|
||||
func SetMetaHeaders(ctx *fiber.Ctx, meta map[string]string) {
|
||||
func SetMetaHeaders(ctx fiber.Ctx, meta map[string]string) {
|
||||
ctx.Response().Header.DisableNormalizing()
|
||||
for key, val := range meta {
|
||||
ctx.Response().Header.Set(fmt.Sprintf("x-amz-meta-%s", key), val)
|
||||
@@ -311,17 +311,17 @@ type CustomHeader struct {
|
||||
Value string
|
||||
}
|
||||
|
||||
func SetResponseHeaders(ctx *fiber.Ctx, headers []CustomHeader) {
|
||||
func SetResponseHeaders(ctx fiber.Ctx, headers []CustomHeader) {
|
||||
for _, header := range headers {
|
||||
ctx.Set(header.Key, header.Value)
|
||||
}
|
||||
}
|
||||
|
||||
// Streams the response body by chunks
|
||||
func StreamResponseBody(ctx *fiber.Ctx, rdr io.ReadCloser, bodysize int) {
|
||||
func StreamResponseBody(ctx fiber.Ctx, rdr io.ReadCloser, bodysize int) {
|
||||
// SetBodyStream will call Close() on the reader when the stream is done
|
||||
// since rdr is a ReadCloser
|
||||
ctx.Context().SetBodyStream(rdr, bodysize)
|
||||
ctx.RequestCtx().SetBodyStream(rdr, bodysize)
|
||||
}
|
||||
|
||||
func IsValidBucketName(bucket string) bool {
|
||||
@@ -353,7 +353,7 @@ func includeHeader(hdr string, signedHdrs []string) bool {
|
||||
})
|
||||
}
|
||||
|
||||
func addRequestHeadersFromCtx(ctx *fiber.Ctx, httpReq *http.Request, signedHdrs []string) error {
|
||||
func addRequestHeadersFromCtx(ctx fiber.Ctx, httpReq *http.Request, signedHdrs []string) error {
|
||||
headersNotSigned := []string{}
|
||||
for key, value := range ctx.Request().Header.All() {
|
||||
keyStr := string(key)
|
||||
@@ -424,7 +424,7 @@ func FilterObjectAttributes(attrs map[s3response.ObjectAttributes]struct{}, outp
|
||||
return output
|
||||
}
|
||||
|
||||
func ParseObjectAttributes(ctx *fiber.Ctx) (map[s3response.ObjectAttributes]struct{}, error) {
|
||||
func ParseObjectAttributes(ctx fiber.Ctx) (map[s3response.ObjectAttributes]struct{}, error) {
|
||||
attrs := map[s3response.ObjectAttributes]struct{}{}
|
||||
var err error
|
||||
for key, value := range ctx.Request().Header.All() {
|
||||
@@ -463,7 +463,7 @@ type objLockCfg struct {
|
||||
LegalHoldStatus types.ObjectLockLegalHoldStatus
|
||||
}
|
||||
|
||||
func ParsObjectLockHdrs(ctx *fiber.Ctx) (*objLockCfg, error) {
|
||||
func ParsObjectLockHdrs(ctx fiber.Ctx) (*objLockCfg, error) {
|
||||
legalHoldHdr := ctx.Get("X-Amz-Object-Lock-Legal-Hold")
|
||||
objLockModeHdr := ctx.Get("X-Amz-Object-Lock-Mode")
|
||||
objLockDate := ctx.Get("X-Amz-Object-Lock-Retain-Until-Date")
|
||||
@@ -549,7 +549,7 @@ func (cv ChecksumValues) Headers() string {
|
||||
|
||||
// ParseCalculatedChecksumHeaders parses and validates x-amz-checksum-x header keys
|
||||
// e.g x-amz-checksum-crc32, x-amz-checksum-sha256 ...
|
||||
func ParseCalculatedChecksumHeaders(ctx *fiber.Ctx) (ChecksumValues, error) {
|
||||
func ParseCalculatedChecksumHeaders(ctx fiber.Ctx) (ChecksumValues, error) {
|
||||
checksums := ChecksumValues{}
|
||||
|
||||
var hdrErr error
|
||||
@@ -639,7 +639,7 @@ func ParseCalculatedChecksumFields(fields map[string]string) (ChecksumValues, er
|
||||
// ParseCompleteMpChecksumHeaders parses and validates
|
||||
// the 'CompleteMultipartUpload' x-amz-checksum-x headers
|
||||
// by supporting both 'checksum' and 'checksum-<part_length>' formats
|
||||
func ParseCompleteMpChecksumHeaders(ctx *fiber.Ctx) (ChecksumValues, error) {
|
||||
func ParseCompleteMpChecksumHeaders(ctx fiber.Ctx) (ChecksumValues, error) {
|
||||
// first parse/validate 'x-amz-checksum-x' headers
|
||||
checksums, err := ParseCalculatedChecksumHeaders(ctx)
|
||||
if err != nil {
|
||||
@@ -673,7 +673,7 @@ func ParseCompleteMpChecksumHeaders(ctx *fiber.Ctx) (ChecksumValues, error) {
|
||||
|
||||
// ParseChecksumHeadersAndSdkAlgo parses/validates 'x-amz-sdk-checksum-algorithm' and
|
||||
// 'x-amz-checksum-x' precalculated request headers
|
||||
func ParseChecksumHeadersAndSdkAlgo(ctx *fiber.Ctx) (types.ChecksumAlgorithm, ChecksumValues, error) {
|
||||
func ParseChecksumHeadersAndSdkAlgo(ctx fiber.Ctx) (types.ChecksumAlgorithm, ChecksumValues, error) {
|
||||
sdkAlgorithm := types.ChecksumAlgorithm(strings.ToUpper(ctx.Get("X-Amz-Sdk-Checksum-Algorithm")))
|
||||
err := IsChecksumAlgorithmValid(sdkAlgorithm)
|
||||
if err != nil {
|
||||
@@ -862,7 +862,7 @@ func checkChecksumTypeAndAlgo(algo types.ChecksumAlgorithm, t types.ChecksumType
|
||||
}
|
||||
|
||||
// Parses and validates the x-amz-checksum-algorithm and x-amz-checksum-type headers
|
||||
func ParseCreateMpChecksumHeaders(ctx *fiber.Ctx) (types.ChecksumAlgorithm, types.ChecksumType, error) {
|
||||
func ParseCreateMpChecksumHeaders(ctx fiber.Ctx) (types.ChecksumAlgorithm, types.ChecksumType, error) {
|
||||
algo := types.ChecksumAlgorithm(strings.ToUpper(ctx.Get("x-amz-checksum-algorithm")))
|
||||
if err := IsChecksumAlgorithmValid(algo); err != nil {
|
||||
return "", "", err
|
||||
@@ -1071,7 +1071,7 @@ func ValidateCopySource(input string) error {
|
||||
}
|
||||
|
||||
// GetQueryParam returns a pointer to the query parameter value if it exists
|
||||
func GetQueryParam(ctx *fiber.Ctx, key string) *string {
|
||||
func GetQueryParam(ctx fiber.Ctx, key string) *string {
|
||||
value := ctx.Query(key)
|
||||
if value == "" {
|
||||
return nil
|
||||
@@ -1089,9 +1089,9 @@ func ApplyOverride(original, override *string) *string {
|
||||
|
||||
// GenerateObjectLocation generates the object location path-styled or host-styled
|
||||
// depending on the gateway configuration
|
||||
func GenerateObjectLocation(ctx *fiber.Ctx, virtualDomain, bucket, object string) string {
|
||||
scheme := ctx.Protocol()
|
||||
host := ctx.Hostname()
|
||||
func GenerateObjectLocation(ctx fiber.Ctx, virtualDomain, bucket, object string) string {
|
||||
scheme := ctx.Scheme()
|
||||
host := ctx.Host()
|
||||
|
||||
// escape the object name
|
||||
obj := url.PathEscape(object)
|
||||
@@ -1146,7 +1146,7 @@ func NewTLSListener(network string, address string, getCertificateFunc func(*tls
|
||||
return tls.NewListener(ln, config), nil
|
||||
}
|
||||
|
||||
func DetectResourceType(ctx *fiber.Ctx) s3err.ResourceType {
|
||||
func DetectResourceType(ctx fiber.Ctx) s3err.ResourceType {
|
||||
path := ctx.Path()
|
||||
if path == "" || path == "/" {
|
||||
return s3err.ResourceTypeService
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/valyala/fasthttp"
|
||||
"github.com/versity/versitygw/backend"
|
||||
@@ -38,7 +38,7 @@ import (
|
||||
|
||||
func TestCreateHttpRequestFromCtx(t *testing.T) {
|
||||
type args struct {
|
||||
ctx *fiber.Ctx
|
||||
ctx fiber.Ctx
|
||||
}
|
||||
|
||||
app := fiber.New()
|
||||
|
||||
Reference in New Issue
Block a user