diff --git a/cmd/versitygw/main.go b/cmd/versitygw/main.go index 2015c6ae..fc840f46 100644 --- a/cmd/versitygw/main.go +++ b/cmd/versitygw/main.go @@ -959,12 +959,15 @@ func runGateway(ctx context.Context, be backend.Backend) error { webOpts = append(webOpts, webui.WithQuiet()) } - webSrv = webui.NewServer(&webui.ServerConfig{ + webSrv, err = webui.NewServer(&webui.ServerConfig{ ListenAddr: webuiAddr, Gateways: gateways, AdminGateways: adminGateways, Region: region, }, webOpts...) + if err != nil { + return fmt.Errorf("initialize webui: %w", err) + } } if !quiet { diff --git a/debuglogger/logger.go b/debuglogger/logger.go index ab33d71d..ad8b8220 100644 --- a/debuglogger/logger.go +++ b/debuglogger/logger.go @@ -22,7 +22,7 @@ import ( "strings" "sync/atomic" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" ) type Color string @@ -60,7 +60,7 @@ func printError(prefix prefix, er error) { } // Logs http request details: headers, body, params, query args -func LogFiberRequestDetails(ctx *fiber.Ctx) { +func LogFiberRequestDetails(ctx fiber.Ctx) { // Log the full request url fullURL := ctx.Protocol() + "://" + ctx.Hostname() + ctx.OriginalURL() fmt.Printf("%s[URL]: %s%s\n", green, fullURL, reset) @@ -90,7 +90,7 @@ func LogFiberRequestDetails(ctx *fiber.Ctx) { } // Logs http response details: body, headers -func LogFiberResponseDetails(ctx *fiber.Ctx) { +func LogFiberResponseDetails(ctx fiber.Ctx) { wrapInBox(green, "RESPONSE HEADERS", boxWidth, func() { for key, value := range ctx.Response().Header.All() { printWrappedLine(yellow, string(key), string(value)) @@ -265,7 +265,7 @@ func wrapText(text string, width int) []string { // TODO: remove this and use utils.IsBidDataAction after refactoring // and creating 'internal' package -func isLargeDataAction(ctx *fiber.Ctx) bool { +func isLargeDataAction(ctx fiber.Ctx) bool { if ctx.Method() == http.MethodPut && len(strings.Split(ctx.Path(), "/")) >= 3 { if !ctx.Request().URI().QueryArgs().Has("tagging") && ctx.Get("X-Amz-Copy-Source") == "" && !ctx.Request().URI().QueryArgs().Has("acl") { return true diff --git a/go.mod b/go.mod index a9e965e4..379d25fb 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/aws/smithy-go v1.24.0 github.com/davecgh/go-spew v1.1.1 github.com/go-ldap/ldap/v3 v3.4.12 - github.com/gofiber/fiber/v2 v2.52.11 + github.com/gofiber/fiber/v3 v3.0.0 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/hashicorp/vault-client-go v0.4.3 @@ -33,6 +33,11 @@ require ( golang.org/x/sys v0.40.0 ) +require ( + github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/x448/float16 v0.8.4 // indirect +) + require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect github.com/Azure/go-ntlmssp v0.1.0 // indirect @@ -56,10 +61,10 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect - github.com/clipperhouse/stringish v0.1.1 // indirect - github.com/clipperhouse/uax29/v2 v2.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect + github.com/gofiber/schema v1.6.0 // indirect + github.com/gofiber/utils/v2 v2.0.0 // indirect github.com/golang-jwt/jwt/v5 v5.3.1 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.8 // indirect @@ -70,14 +75,15 @@ require ( github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.19 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/nats-io/nuid v1.0.1 // indirect + github.com/philhofer/fwd v1.2.0 // indirect github.com/pierrec/lz4/v4 v4.1.25 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect + github.com/tinylib/msgp v1.6.3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect golang.org/x/crypto v0.47.0 // indirect diff --git a/go.sum b/go.sum index e5c9d40d..b8318075 100644 --- a/go.sum +++ b/go.sum @@ -65,10 +65,6 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/ github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ= github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= -github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= -github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= -github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U= -github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -76,12 +72,18 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-ldap/ldap/v3 v3.4.12 h1:1b81mv7MagXZ7+1r7cLTWmyuTqVqdwbtJSjC0DAp9s4= github.com/go-ldap/ldap/v3 v3.4.12/go.mod h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo= -github.com/gofiber/fiber/v2 v2.52.11 h1:5f4yzKLcBcF8ha1GQTWB+mpblWz3Vz6nSAbTL31HkWs= -github.com/gofiber/fiber/v2 v2.52.11/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/gofiber/fiber/v3 v3.0.0 h1:GPeCG8X60L42wLKrzgeewDHBr6pE6veAvwaXsqD3Xjk= +github.com/gofiber/fiber/v3 v3.0.0/go.mod h1:kVZiO/AwyT5Pq6PgC8qRCJ+j/BHrMy5jNw1O9yH38aY= +github.com/gofiber/schema v1.6.0 h1:rAgVDFwhndtC+hgV7Vu5ItQCn7eC2mBA4Eu1/ZTiEYY= +github.com/gofiber/schema v1.6.0/go.mod h1:WNZWpQx8LlPSK7ZaX0OqOh+nQo/eW2OevsXs1VZfs/s= +github.com/gofiber/utils/v2 v2.0.0 h1:SCC3rpsEDWupFSHtc0RKxg/BKgV0s1qKfZg9Jv6D0sM= +github.com/gofiber/utils/v2 v2.0.0/go.mod h1:xF9v89FfmbrYqI/bQUGN7gR8ZtXot2jxnZvmAUtiavE= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= @@ -131,8 +133,6 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= -github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI= github.com/minio/crc64nvme v1.1.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -146,6 +146,8 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s= github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= +github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= +github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pierrec/lz4/v4 v4.1.25 h1:kocOqRffaIbU5djlIBr7Wh+cx82C0vtFb0fOurZHqD0= github.com/pierrec/lz4/v4 v4.1.25/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -165,6 +167,8 @@ github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkB github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/segmentio/kafka-go v0.4.50 h1:mcyC3tT5WeyWzrFbd6O374t+hmcu1NKt2Pu1L3QaXmc= github.com/segmentio/kafka-go v0.4.50/go.mod h1:Y1gn60kzLEEaW28YshXyk2+VCUKbJ3Qr6DrnT3i4+9E= +github.com/shamaton/msgpack/v3 v3.0.0 h1:xl40uxWkSpwBCSTvS5wyXvJRsC6AcVcYeox9PspKiZg= +github.com/shamaton/msgpack/v3 v3.0.0/go.mod h1:DcQG8jrdrQCIxr3HlMYkiXdMhK+KfN2CitkyzsQV4uc= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smira/go-statsd v1.3.4 h1:kBYWcLSGT+qC6JVbvfz48kX7mQys32fjDOPrfmsSx2c= github.com/smira/go-statsd v1.3.4/go.mod h1:RjdsESPgDODtg1VpVVf9MJrEW2Hw0wtRNbmB1CAhu6A= @@ -179,6 +183,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/tinylib/msgp v1.6.3 h1:bCSxiTz386UTgyT1i0MSCvdbWjVW+8sG3PjkGsZQt4s= +github.com/tinylib/msgp v1.6.3/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU= github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -187,6 +193,8 @@ github.com/valyala/fasthttp v1.69.0 h1:fNLLESD2SooWeh2cidsuFtOcrEi4uB4m1mPrkJMZy github.com/valyala/fasthttp v1.69.0/go.mod h1:4wA4PfAraPlAsJ5jMSqCE2ug5tqUPwKXxVj8oNECGcw= github.com/versity/scoutfs-go v0.0.0-20240625221833-95fd765b760b h1:kuqsuYRMG1c6YXBAQvWO7CiurlpYtjDJWI6oZ2K/ZZE= github.com/versity/scoutfs-go v0.0.0-20240625221833-95fd765b760b/go.mod h1:gJsq73k+4685y+rbDIpPY8i/5GbsiwP6JFoFyUDB1fQ= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= diff --git a/metrics/metrics.go b/metrics/metrics.go index 753b4057..d7c9386f 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -23,7 +23,7 @@ import ( "strings" "sync" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" "github.com/versity/versitygw/s3err" ) @@ -43,7 +43,7 @@ type Tag struct { // Manager is the interface definition for metrics manager type Manager interface { - Send(ctx *fiber.Ctx, err error, action string, count int64, status int) + Send(ctx fiber.Ctx, err error, action string, count int64, status int) Close() } @@ -118,7 +118,7 @@ func NewManager(ctx context.Context, conf Config) (Manager, error) { return mgr, nil } -func (m *manager) Send(ctx *fiber.Ctx, err error, action string, count int64, status int) { +func (m *manager) Send(ctx fiber.Ctx, err error, action string, count int64, status int) { // In case of Authentication failures, url parsing ... if action == "" { action = ActionUndetected diff --git a/s3api/admin-router.go b/s3api/admin-router.go index 40727f02..9ecf5e3b 100644 --- a/s3api/admin-router.go +++ b/s3api/admin-router.go @@ -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" diff --git a/s3api/admin-server.go b/s3api/admin-server.go index e314e071..5e8967c7 100644 --- a/s3api/admin-server.go +++ b/s3api/admin-server.go @@ -15,9 +15,9 @@ package s3api import ( - "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" @@ -52,16 +52,14 @@ func NewAdminServer(be backend.Backend, root middlewares.RootUserConfig, port, r } app := fiber.New(fiber.Config{ - AppName: "versitygw", - ServerHeader: "VERSITYGW", - Network: fiber.NetworkTCP, - DisableStartupMessage: true, - ErrorHandler: globalErrorHandler, + AppName: "versitygw", + ServerHeader: "VERSITYGW", + ErrorHandler: globalErrorHandler, }) server.app = app - app.Use(recover.New( + app.Use("*", recover.New( recover.Config{ EnableStackTrace: true, StackTraceHandler: stackTraceHandler, @@ -69,15 +67,15 @@ func NewAdminServer(be backend.Backend, root middlewares.RootUserConfig, port, r // 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", })) } - 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) @@ -109,14 +107,22 @@ func WithAdminCORSAllowOrigin(origin string) AdminOpt { func (sa *S3AdminServer) Serve() (err error) { if sa.CertStorage != nil { - ln, err := utils.NewTLSListener(sa.app.Config().Network, sa.port, sa.CertStorage.GetCertificate) + ln, err := utils.NewTLSListener(fiber.NetworkTCP, sa.port, sa.CertStorage.GetCertificate) if err != nil { return err } - return sa.app.Listener(ln) + return sa.app.Listener(ln, + fiber.ListenConfig{ + ListenerNetwork: fiber.NetworkTCP, + DisableStartupMessage: true, + }) } - return sa.app.Listen(sa.port) + return sa.app.Listen(sa.port, + fiber.ListenConfig{ + ListenerNetwork: fiber.NetworkTCP, + DisableStartupMessage: true, + }) } // ShutDown gracefully shuts down the server with a context timeout diff --git a/s3api/controllers/admin.go b/s3api/controllers/admin.go index 4f86b7d6..089a4719 100644 --- a/s3api/controllers/admin.go +++ b/s3api/controllers/admin.go @@ -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 { diff --git a/s3api/controllers/base.go b/s3api/controllers/base.go index 62c69110..5127fa47 100644 --- a/s3api/controllers/base.go +++ b/s3api/controllers/base.go @@ -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" @@ -72,7 +72,7 @@ func New(be backend.Backend, iam auth.IAMService, logger s3log.AuditLogger, evs // 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 } } @@ -107,11 +107,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) @@ -121,7 +121,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 @@ -136,14 +136,14 @@ 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 { err := handler(ctx) if err != nil { if mm != nil { 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, }) } @@ -168,7 +168,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 @@ -316,7 +316,7 @@ func ProcessController(ctx *fiber.Ctx, controller Controller, s3action string, s return ctx.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 @@ -388,7 +388,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 } diff --git a/s3api/controllers/base_test.go b/s3api/controllers/base_test.go index 4b7a583a..1699fdbf 100644 --- a/s3api/controllers/base_test.go +++ b/s3api/controllers/base_test.go @@ -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" @@ -92,7 +92,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 @@ -256,23 +256,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{ @@ -305,7 +305,7 @@ func TestProcessController(t *testing.T) { name: "no services successfull response", args: args{ svc: &Services{}, - controller: func(ctx *fiber.Ctx) (*Response, error) { + controller: func(ctx fiber.Ctx) (*Response, error) { return &Response{}, nil }, }, @@ -317,7 +317,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) }, }, @@ -330,7 +330,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") }, }, @@ -343,7 +343,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 @@ -358,7 +358,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, @@ -374,7 +374,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, @@ -390,7 +390,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 @@ -408,7 +408,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"), @@ -429,7 +429,7 @@ func TestProcessController(t *testing.T) { name: "large paylod: 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"` } @@ -472,7 +472,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", @@ -546,10 +546,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) }, }, @@ -563,15 +563,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"), @@ -590,7 +590,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 { // set the request locals if tt.args.locals != nil { for key, val := range tt.args.locals { @@ -610,7 +610,7 @@ func TestProcessHandlers(t *testing.T) { return nil }) - app.All("*", func(ctx *fiber.Ctx) error { + app.All("*", func(ctx fiber.Ctx) error { return nil }) @@ -639,7 +639,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 }, }, @@ -647,7 +647,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{}, @@ -660,7 +660,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") }, }, @@ -674,7 +674,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 { // call the controller by passing the ctx err := mdlwr(ctx) assert.NoError(t, err) @@ -687,7 +687,7 @@ func TestWrapMiddleware(t *testing.T) { return nil }) - app.All("*", func(ctx *fiber.Ctx) error { + app.All("*", func(ctx fiber.Ctx) error { return nil }) diff --git a/s3api/controllers/bucket-delete.go b/s3api/controllers/bucket-delete.go index 7b062b0a..ed28b76c 100644 --- a/s3api/controllers/bucket-delete.go +++ b/s3api/controllers/bucket-delete.go @@ -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, @@ -48,7 +48,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, @@ -57,13 +57,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, @@ -81,7 +81,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, @@ -90,13 +90,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, @@ -114,7 +114,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, @@ -123,14 +123,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, @@ -149,7 +149,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, @@ -158,14 +158,14 @@ func (c S3ApiController) DeleteBucketCors(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, @@ -184,7 +184,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, diff --git a/s3api/controllers/bucket-get.go b/s3api/controllers/bucket-get.go index aa5194a7..5a497cb7 100644 --- a/s3api/controllers/bucket-get.go +++ b/s3api/controllers/bucket-get.go @@ -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, @@ -50,7 +50,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{ @@ -77,14 +77,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, @@ -102,7 +102,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{ @@ -117,14 +117,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, @@ -150,7 +150,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{ @@ -159,14 +159,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, @@ -184,7 +184,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{ @@ -202,14 +202,14 @@ func (c S3ApiController) GetBucketCors(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, @@ -227,7 +227,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{ @@ -236,14 +236,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, @@ -261,7 +261,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{ @@ -290,7 +290,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") @@ -304,7 +304,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, @@ -331,7 +331,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, @@ -348,7 +348,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 @@ -357,7 +357,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, @@ -375,7 +375,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{ @@ -393,7 +393,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 @@ -402,7 +402,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, @@ -420,7 +420,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{ @@ -439,7 +439,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") @@ -453,7 +453,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, @@ -478,7 +478,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, @@ -495,7 +495,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") @@ -510,7 +510,7 @@ func (c S3ApiController) ListObjectsV2(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, @@ -536,7 +536,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, @@ -554,7 +554,7 @@ func (c S3ApiController) ListObjectsV2(ctx *fiber.Ctx) (*Response, error) { }, err } -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") @@ -567,7 +567,7 @@ func (c S3ApiController) ListObjects(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, @@ -594,7 +594,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, @@ -611,14 +611,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, @@ -637,7 +637,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{ diff --git a/s3api/controllers/bucket-head.go b/s3api/controllers/bucket-head.go index ed6696f8..f9515724 100644 --- a/s3api/controllers/bucket-head.go +++ b/s3api/controllers/bucket-head.go @@ -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, @@ -54,7 +54,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, }) diff --git a/s3api/controllers/bucket-list.go b/s3api/controllers/bucket-list.go index 0f7663be..edac2d63 100644 --- a/s3api/controllers/bucket-list.go +++ b/s3api/controllers/bucket-list.go @@ -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, diff --git a/s3api/controllers/bucket-post.go b/s3api/controllers/bucket-post.go index be3d3bd3..ac9f588c 100644 --- a/s3api/controllers/bucket-post.go +++ b/s3api/controllers/bucket-post.go @@ -20,7 +20,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" @@ -29,7 +29,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) @@ -37,7 +37,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, @@ -57,7 +57,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{ @@ -67,7 +67,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{ @@ -76,7 +76,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{ diff --git a/s3api/controllers/bucket-put.go b/s3api/controllers/bucket-put.go index 3d1d262f..fa20b6e7 100644 --- a/s3api/controllers/bucket-put.go +++ b/s3api/controllers/bucket-put.go @@ -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,14 +31,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, @@ -97,7 +97,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{ @@ -119,7 +119,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, @@ -127,14 +127,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, @@ -153,7 +153,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{ @@ -173,7 +173,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, @@ -181,14 +181,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, @@ -205,7 +205,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{ @@ -214,7 +214,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, @@ -222,14 +222,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, @@ -247,7 +247,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) @@ -270,7 +270,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, @@ -278,13 +278,13 @@ func (c S3ApiController) PutBucketCors(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, @@ -301,7 +301,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{ @@ -310,7 +310,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, @@ -319,7 +319,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 := ctx.Get("X-Amz-Acl") grantFullControl := ctx.Get("X-Amz-Grant-Full-Control") @@ -335,7 +335,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, @@ -362,7 +362,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{ @@ -379,9 +379,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{ @@ -470,7 +470,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, @@ -478,7 +478,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 := ctx.Get("X-Amz-Acl") grantFullControl := ctx.Get("X-Amz-Grant-Full-Control") @@ -561,9 +561,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{ @@ -611,7 +611,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, diff --git a/s3api/controllers/cors_default_origin_test.go b/s3api/controllers/cors_default_origin_test.go index 4d198399..fdfcdc44 100644 --- a/s3api/controllers/cors_default_origin_test.go +++ b/s3api/controllers/cors_default_origin_test.go @@ -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, origin), - func(c *fiber.Ctx) error { + func(c fiber.Ctx) error { return c.SendStatus(http.StatusOK) }, ) @@ -71,7 +71,7 @@ func TestApplyBucketCORS_FallbackOrigin_NotAppliedWhenBucketCorsExists(t *testin app := fiber.New() app.Get("/:bucket/test", middlewares.ApplyBucketCORS(mockedBackend, origin), - func(c *fiber.Ctx) error { + func(c fiber.Ctx) error { return c.SendStatus(http.StatusOK) }, ) diff --git a/s3api/controllers/object-delete.go b/s3api/controllers/object-delete.go index bac9d456..53eeff2a 100644 --- a/s3api/controllers/object-delete.go +++ b/s3api/controllers/object-delete.go @@ -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, @@ -70,7 +70,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, @@ -83,7 +83,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") @@ -93,7 +93,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, @@ -113,7 +113,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, @@ -128,7 +128,7 @@ 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") @@ -147,7 +147,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, @@ -177,7 +177,7 @@ func (c S3ApiController) DeleteObject(ctx *fiber.Ctx) (*Response, error) { } err = auth.CheckObjectAccess( - ctx.Context(), + ctx.RequestCtx(), bucket, acct.Access, []types.ObjectIdentifier{ @@ -199,7 +199,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, diff --git a/s3api/controllers/object-get.go b/s3api/controllers/object-get.go index 828f085c..e55e9586 100644 --- a/s3api/controllers/object-get.go +++ b/s3api/controllers/object-get.go @@ -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, @@ -73,7 +73,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{ @@ -101,7 +101,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") @@ -111,7 +111,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, @@ -139,7 +139,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{ @@ -157,7 +157,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") @@ -167,7 +167,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, @@ -195,7 +195,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{ @@ -204,7 +204,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 @@ -213,7 +213,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, @@ -231,7 +231,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, }) @@ -243,7 +243,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") @@ -255,7 +255,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, @@ -294,7 +294,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, @@ -309,7 +309,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") @@ -326,7 +326,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, @@ -371,7 +371,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, @@ -411,13 +411,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{ @@ -459,7 +459,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, @@ -513,7 +513,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, diff --git a/s3api/controllers/object-head.go b/s3api/controllers/object-head.go index 87e6e22c..ed654ae2 100644 --- a/s3api/controllers/object-head.go +++ b/s3api/controllers/object-head.go @@ -21,14 +21,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) @@ -36,7 +36,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[int](ctx, "partNumber", -1)) versionId := ctx.Query("versionId") objRange := ctx.Get("Range") key := strings.TrimPrefix(ctx.Path(), fmt.Sprintf("/%s/", bucket)) @@ -46,7 +46,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, @@ -101,7 +101,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, diff --git a/s3api/controllers/object-post.go b/s3api/controllers/object-post.go index 844d4479..34a0a52f 100644 --- a/s3api/controllers/object-post.go +++ b/s3api/controllers/object-post.go @@ -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, @@ -60,7 +60,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{ @@ -69,7 +69,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, @@ -82,7 +82,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) @@ -90,7 +90,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, @@ -111,7 +111,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{ @@ -121,7 +121,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, @@ -133,7 +133,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{ @@ -142,7 +142,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") @@ -167,7 +167,7 @@ func (c S3ApiController) CreateMultipartUpload(ctx *fiber.Ctx) (*Response, error }, err } - err = auth.VerifyAccess(ctx.Context(), c.be, + err = auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{ Readonly: c.readonly, Acl: parsedAcl, @@ -204,7 +204,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, @@ -238,7 +238,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") @@ -250,7 +250,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, @@ -271,7 +271,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{ @@ -334,7 +334,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{ @@ -343,7 +343,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, diff --git a/s3api/controllers/object-put.go b/s3api/controllers/object-put.go index ce46580c..81a0ac75 100644 --- a/s3api/controllers/object-put.go +++ b/s3api/controllers/object-put.go @@ -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, @@ -75,7 +75,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{ @@ -84,7 +84,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, @@ -96,7 +96,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") @@ -106,7 +106,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, @@ -135,7 +135,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{ @@ -145,7 +145,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{ @@ -164,7 +164,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, @@ -172,7 +172,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") @@ -181,7 +181,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, @@ -210,7 +210,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{ @@ -228,7 +228,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, @@ -236,10 +236,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[int](ctx, "partNumber", -1)) uploadId := ctx.Query("uploadId") // context locals acct := utils.ContextKeyAccount.Get(ctx).(auth.Account) @@ -258,7 +258,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, @@ -315,7 +315,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, @@ -351,12 +351,12 @@ 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") - partNumber := int32(ctx.QueryInt("partNumber", -1)) + partNumber := int32(fiber.Query[int](ctx, "partNumber", -1)) uploadId := ctx.Query("uploadId") // context locals acct := utils.ContextKeyAccount.Get(ctx).(auth.Account) @@ -373,7 +373,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, @@ -412,7 +412,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, @@ -440,7 +440,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") @@ -454,7 +454,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, @@ -473,7 +473,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, @@ -491,7 +491,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"), "/") @@ -528,7 +528,7 @@ func (c S3ApiController) CopyObject(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, @@ -596,7 +596,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{ @@ -605,7 +605,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, @@ -652,7 +652,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") @@ -692,7 +692,7 @@ func (c S3ApiController) PutObject(ctx *fiber.Ctx) (*Response, error) { // load the meta headers metadata := utils.GetUserMetaData(&ctx.Request().Header) - err = auth.VerifyAccess(ctx.Context(), c.be, + err = auth.VerifyAccess(ctx.RequestCtx(), c.be, auth.AccessOptions{ Readonly: c.readonly, Acl: parsedAcl, @@ -712,7 +712,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{ @@ -759,7 +759,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, diff --git a/s3api/controllers/options.go b/s3api/controllers/options.go index a50ae701..1792d0e7 100644 --- a/s3api/controllers/options.go +++ b/s3api/controllers/options.go @@ -17,7 +17,7 @@ package controllers import ( "errors" - "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" @@ -25,7 +25,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 @@ -63,7 +63,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)) { diff --git a/s3api/middlewares/acl-parser.go b/s3api/middlewares/acl-parser.go index e138a11f..7bc7ccee 100644 --- a/s3api/middlewares/acl-parser.go +++ b/s3api/middlewares/acl-parser.go @@ -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 } diff --git a/s3api/middlewares/admin.go b/s3api/middlewares/admin.go index b8626dff..647df992 100644 --- a/s3api/middlewares/admin.go +++ b/s3api/middlewares/admin.go @@ -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) diff --git a/s3api/middlewares/apply-bucket-cors-preflight.go b/s3api/middlewares/apply-bucket-cors-preflight.go index 8ffa99c4..22d9b2e9 100644 --- a/s3api/middlewares/apply-bucket-cors-preflight.go +++ b/s3api/middlewares/apply-bucket-cors-preflight.go @@ -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.APIError); ok && (s3Err.Code == "NoSuchCORSConfiguration" || s3Err.Code == "NoSuchBucket") { if len(ctx.Response().Header.Peek("Access-Control-Allow-Origin")) == 0 { diff --git a/s3api/middlewares/apply-bucket-cors-preflight_test.go b/s3api/middlewares/apply-bucket-cors-preflight_test.go index 776bfae4..89648994 100644 --- a/s3api/middlewares/apply-bucket-cors-preflight_test.go +++ b/s3api/middlewares/apply-bucket-cors-preflight_test.go @@ -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) }, @@ -86,7 +86,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) }, ) @@ -125,7 +125,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) }, ) diff --git a/s3api/middlewares/apply-bucket-cors.go b/s3api/middlewares/apply-bucket-cors.go index 930dd161..ad2f6595 100644 --- a/s3api/middlewares/apply-bucket-cors.go +++ b/s3api/middlewares/apply-bucket-cors.go @@ -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" @@ -35,7 +35,7 @@ var VaryHdr = "Origin, Access-Control-Request-Headers, Access-Control-Request-Me func ApplyBucketCORS(be backend.Backend, fallbackOrigin string) fiber.Handler { fallbackOrigin = strings.TrimSpace(fallbackOrigin) - return func(ctx *fiber.Ctx) error { + return func(ctx fiber.Ctx) error { bucket := ctx.Params("bucket") origin := ctx.Get("Origin") // If neither Origin is present nor a fallback is configured, skip CORS entirely. @@ -44,7 +44,7 @@ func ApplyBucketCORS(be backend.Backend, fallbackOrigin string) fiber.Handler { } // 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. diff --git a/s3api/middlewares/apply-default-cors-preflight.go b/s3api/middlewares/apply-default-cors-preflight.go index dc8cf018..4ede423a 100644 --- a/s3api/middlewares/apply-default-cors-preflight.go +++ b/s3api/middlewares/apply-default-cors-preflight.go @@ -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) } diff --git a/s3api/middlewares/apply-default-cors-preflight_test.go b/s3api/middlewares/apply-default-cors-preflight_test.go index ae0ebfff..a86fb39f 100644 --- a/s3api/middlewares/apply-default-cors-preflight_test.go +++ b/s3api/middlewares/apply-default-cors-preflight_test.go @@ -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) diff --git a/s3api/middlewares/apply-default-cors.go b/s3api/middlewares/apply-default-cors.go index afb40731..d8957223 100644 --- a/s3api/middlewares/apply-default-cors.go +++ b/s3api/middlewares/apply-default-cors.go @@ -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"} 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) } diff --git a/s3api/middlewares/apply-default-cors_test.go b/s3api/middlewares/apply-default-cors_test.go index df181c2c..1120c1eb 100644 --- a/s3api/middlewares/apply-default-cors_test.go +++ b/s3api/middlewares/apply-default-cors_test.go @@ -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) }) @@ -51,10 +51,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) }) diff --git a/s3api/middlewares/authentication.go b/s3api/middlewares/authentication.go index 91ed7797..66968acd 100644 --- a/s3api/middlewares/authentication.go +++ b/s3api/middlewares/authentication.go @@ -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" @@ -40,7 +40,7 @@ type RootUserConfig struct { func VerifyV4Signature(root RootUserConfig, iam auth.IAMService, region string, streamBody bool, requireContentSha256 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 @@ -159,7 +159,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 diff --git a/s3api/middlewares/body-reader.go b/s3api/middlewares/body-reader.go index 97a705a3..0e52cc11 100644 --- a/s3api/middlewares/body-reader.go +++ b/s3api/middlewares/body-reader.go @@ -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() diff --git a/s3api/middlewares/bucket-object-name-validator.go b/s3api/middlewares/bucket-object-name-validator.go index f099afd8..62fff99a 100644 --- a/s3api/middlewares/bucket-object-name-validator.go +++ b/s3api/middlewares/bucket-object-name-validator.go @@ -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 diff --git a/s3api/middlewares/checksum.go b/s3api/middlewares/checksum.go index 9ca12532..cc8fa0c8 100644 --- a/s3api/middlewares/checksum.go +++ b/s3api/middlewares/checksum.go @@ -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) } diff --git a/s3api/middlewares/host-style-parser.go b/s3api/middlewares/host-style-parser.go index 5f6445b6..e0d5afc2 100644 --- a/s3api/middlewares/host-style-parser.go +++ b/s3api/middlewares/host-style-parser.go @@ -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, _, found := strings.Cut(host, "."+virtualDomain) diff --git a/s3api/middlewares/logger.go b/s3api/middlewares/logger.go index b2b84fdc..bb7e8a0e 100644 --- a/s3api/middlewares/logger.go +++ b/s3api/middlewares/logger.go @@ -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) diff --git a/s3api/middlewares/presign-auth.go b/s3api/middlewares/presign-auth.go index 6bebafdb..1f7cc72e 100644 --- a/s3api/middlewares/presign-auth.go +++ b/s3api/middlewares/presign-auth.go @@ -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 diff --git a/s3api/middlewares/public-bucket.go b/s3api/middlewares/public-bucket.go index ba7dce52..31b6c800 100644 --- a/s3api/middlewares/public-bucket.go +++ b/s3api/middlewares/public-bucket.go @@ -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") != "" { 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 diff --git a/s3api/middlewares/router-utilities.go b/s3api/middlewares/router-utilities.go index 47929103..0309de31 100644 --- a/s3api/middlewares/router-utilities.go +++ b/s3api/middlewares/router-utilities.go @@ -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() } diff --git a/s3api/middlewares/set-default-keys.go b/s3api/middlewares/set-default-keys.go index e87cbbfe..38eb624c 100644 --- a/s3api/middlewares/set-default-keys.go +++ b/s3api/middlewares/set-default-keys.go @@ -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()) diff --git a/s3api/middlewares/url-decoder.go b/s3api/middlewares/url-decoder.go index 7c4b209b..ac618527 100644 --- a/s3api/middlewares/url-decoder.go +++ b/s3api/middlewares/url-decoder.go @@ -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 diff --git a/s3api/router.go b/s3api/router.go index 8816f496..0222b8be 100644 --- a/s3api/router.go +++ b/s3api/router.go @@ -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" diff --git a/s3api/router_cors_test.go b/s3api/router_cors_test.go index e83ca366..e8508abb 100644 --- a/s3api/router_cors_test.go +++ b/s3api/router_cors_test.go @@ -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/s3api/middlewares" diff --git a/s3api/router_test.go b/s3api/router_test.go index c54451bb..f27e977c 100644 --- a/s3api/router_test.go +++ b/s3api/router_test.go @@ -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" "github.com/versity/versitygw/s3api/middlewares" diff --git a/s3api/server.go b/s3api/server.go index bfa2ce87..277fe298 100644 --- a/s3api/server.go +++ b/s3api/server.go @@ -20,9 +20,9 @@ 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/versity/versitygw/auth" "github.com/versity/versitygw/backend" "github.com/versity/versitygw/debuglogger" @@ -75,19 +75,17 @@ func New( } app := fiber.New(fiber.Config{ - AppName: "versitygw", - ServerHeader: "VERSITYGW", - StreamRequestBody: true, - DisableKeepalive: !server.keepAlive, - Network: fiber.NetworkTCP, - DisableStartupMessage: true, - ErrorHandler: globalErrorHandler, + AppName: "versitygw", + ServerHeader: "VERSITYGW", + StreamRequestBody: true, + DisableKeepalive: !server.keepAlive, + ErrorHandler: globalErrorHandler, }) server.app = app // initialize the panic recovery middleware - app.Use(recover.New( + app.Use("*", recover.New( recover.Config{ EnableStackTrace: true, StackTraceHandler: stackTraceHandler, @@ -95,32 +93,32 @@ 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", })) } // 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) }) } // 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 host-style parser in virtual domain is specified if server.virtualDomain != "" { - app.Use(middlewares.HostStyleParser(server.virtualDomain)) + app.Use("*", middlewares.HostStyleParser(server.virtualDomain)) } // 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, adminLogger, evs, mm, server.readonly, region, server.virtualDomain, root, server.corsAllowOrigin) @@ -173,14 +171,21 @@ func WithCORSAllowOrigin(origin string) Option { func (sa *S3ApiServer) Serve() (err error) { if sa.CertStorage != nil { - ln, err := utils.NewTLSListener(sa.app.Config().Network, sa.port, sa.CertStorage.GetCertificate) + ln, err := utils.NewTLSListener(fiber.NetworkTCP, sa.port, sa.CertStorage.GetCertificate) if err != nil { return err } - return sa.app.Listener(ln) + return sa.app.Listener(ln, + fiber.ListenConfig{ + ListenerNetwork: fiber.NetworkTCP, + DisableStartupMessage: true, + }) } - return sa.app.Listen(sa.port) + return sa.app.Listen(sa.port, fiber.ListenConfig{ + ListenerNetwork: fiber.NetworkTCP, + DisableStartupMessage: true, + }) } // ShutDown gracefully shuts down the server with a context timeout @@ -190,13 +195,13 @@ 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) } // 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 { if utils.ContextKeyStack.IsSet(ctx) { // if stack is set, it means the stack trace // has caught a panic diff --git a/s3api/server_test.go b/s3api/server_test.go index 1b21eae5..1e1edc4c 100644 --- a/s3api/server_test.go +++ b/s3api/server_test.go @@ -17,7 +17,7 @@ package s3api import ( "testing" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" "github.com/versity/versitygw/backend" "github.com/versity/versitygw/s3api/utils" ) diff --git a/s3api/utils/auth-reader.go b/s3api/utils/auth-reader.go index 6c7e5b4d..7ebd6871 100644 --- a/s3api/utils/auth-reader.go +++ b/s3api/utils/auth-reader.go @@ -25,7 +25,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" @@ -41,7 +41,7 @@ const ( // data requests where the data size and checksum are not known until // the data is completely read. type AuthReader struct { - ctx *fiber.Ctx + ctx fiber.Ctx auth AuthData secret string size int @@ -52,7 +52,7 @@ type AuthReader struct { // v4 auth when the underlying reader returns io.EOF. This postpones the // authorization check until the reader is consumed. So it is important that // the consumer of this reader checks for the auth errors while reading. -func NewAuthReader(ctx *fiber.Ctx, r io.Reader, auth AuthData, secret string) *AuthReader { +func NewAuthReader(ctx fiber.Ctx, r io.Reader, auth AuthData, secret string) *AuthReader { var hr *HashReader hashPayload := ctx.Get("X-Amz-Content-Sha256") if !IsSpecialPayload(hashPayload) { @@ -114,7 +114,7 @@ const ( ) // CheckValidSignature validates the ctx v4 auth signature -func CheckValidSignature(ctx *fiber.Ctx, auth AuthData, secret, checksum string, tdate time.Time, contentLen int64, streamBody bool) error { +func CheckValidSignature(ctx fiber.Ctx, auth AuthData, secret, checksum string, tdate time.Time, contentLen int64, streamBody bool) error { signedHdrs := strings.Split(auth.SignedHeaders, ";") // Create a new http request instance from fasthttp request diff --git a/s3api/utils/auth_test.go b/s3api/utils/auth_test.go index 995243de..e63ace82 100644 --- a/s3api/utils/auth_test.go +++ b/s3api/utils/auth_test.go @@ -15,12 +15,13 @@ package utils import ( - "net" "testing" "time" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/client" + "github.com/stretchr/testify/assert" "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()), true) if err != nil { t.Fatal(err) @@ -129,16 +130,16 @@ func Test_Client_UserAgent(t *testing.T) { ln := fasthttputil.NewInmemoryListener() go func() { - err := app.Listener(ln) + err := app.Listener(ln, fiber.ListenConfig{ + DisableStartupMessage: true, + }) if err != nil { panic(err) } }() - 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) + c := client.New() + c.SetUserAgent(agent) + _, err = c.Get("http://example.com") + assert.NoError(t, err) } diff --git a/s3api/utils/chunk-reader.go b/s3api/utils/chunk-reader.go index 05ee98c2..fad62d0a 100644 --- a/s3api/utils/chunk-reader.go +++ b/s3api/utils/chunk-reader.go @@ -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" ) @@ -90,7 +90,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() { @@ -162,7 +162,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'") @@ -182,7 +182,7 @@ func ParseDecodedContentLength(ctx *fiber.Ctx) (int64, error) { return decContLength, nil } -func NewChunkReader(ctx *fiber.Ctx, r io.Reader, authdata AuthData, secret string, date time.Time) (io.Reader, error) { +func NewChunkReader(ctx fiber.Ctx, r io.Reader, authdata AuthData, secret string, date time.Time) (io.Reader, error) { cLength, err := ParseDecodedContentLength(ctx) if err != nil { return nil, err diff --git a/s3api/utils/context-keys.go b/s3api/utils/context-keys.go index 76dfde0b..11fcf0bf 100644 --- a/s3api/utils/context-keys.go +++ b/s3api/utils/context-keys.go @@ -15,7 +15,7 @@ package utils import ( - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" ) // Region, StartTime, IsRoot, Account, AccessKey context locals @@ -55,19 +55,19 @@ func (ck ContextKey) Values() []ContextKey { } } -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)) } diff --git a/s3api/utils/precondition.go b/s3api/utils/precondition.go index 08529808..6c7de8eb 100644 --- a/s3api/utils/precondition.go +++ b/s3api/utils/precondition.go @@ -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 diff --git a/s3api/utils/presign-auth-reader.go b/s3api/utils/presign-auth-reader.go index e4328cf1..8dc60236 100644 --- a/s3api/utils/presign-auth-reader.go +++ b/s3api/utils/presign-auth-reader.go @@ -27,7 +27,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" "github.com/aws/smithy-go/logging" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" "github.com/versity/versitygw/debuglogger" "github.com/versity/versitygw/s3err" ) @@ -44,13 +44,13 @@ const ( // data requests where the data size is not known until // the data is completely read. type PresignedAuthReader struct { - ctx *fiber.Ctx + ctx fiber.Ctx auth AuthData secret string r io.Reader } -func NewPresignedAuthReader(ctx *fiber.Ctx, r io.Reader, auth AuthData, secret string) *PresignedAuthReader { +func NewPresignedAuthReader(ctx fiber.Ctx, r io.Reader, auth AuthData, secret string) *PresignedAuthReader { return &PresignedAuthReader{ ctx: ctx, r: r, @@ -74,7 +74,7 @@ func (pr *PresignedAuthReader) Read(p []byte) (int, error) { } // CheckPresignedSignature validates presigned request signature -func CheckPresignedSignature(ctx *fiber.Ctx, auth AuthData, secret string, streamBody bool) error { +func CheckPresignedSignature(ctx fiber.Ctx, auth AuthData, secret string, streamBody bool) error { signedHdrs := strings.Split(auth.SignedHeaders, ";") var contentLength int64 @@ -96,7 +96,7 @@ func CheckPresignedSignature(ctx *fiber.Ctx, auth AuthData, secret string, strea date, _ := time.Parse(iso8601Format, auth.Date) signer := v4.NewSigner() - uri, _, signErr := signer.PresignHTTP(ctx.Context(), aws.Credentials{ + uri, _, signErr := signer.PresignHTTP(ctx.RequestCtx(), aws.Credentials{ AccessKeyID: auth.Access, SecretAccessKey: secret, }, req, unsignedPayload, service, auth.Region, date, func(options *v4.SignerOptions) { @@ -133,7 +133,7 @@ func CheckPresignedSignature(ctx *fiber.Ctx, auth AuthData, secret string, strea // &X-Amz-Expires=86400 // &X-Amz-SignedHeaders=host // &X-Amz-Signature=1e68ad45c1db540284a4a1eca3884c293ba1a0ff63ab9db9a15b5b29dfa02cd8 -func ParsePresignedURIParts(ctx *fiber.Ctx) (AuthData, error) { +func ParsePresignedURIParts(ctx fiber.Ctx) (AuthData, error) { a := AuthData{} // Get and verify algorithm query parameter @@ -267,7 +267,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") diff --git a/s3api/utils/utils.go b/s3api/utils/utils.go index fdefdaca..1f897a9a 100644 --- a/s3api/utils/utils.go +++ b/s3api/utils/utils.go @@ -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/oklog/ulid/v2" "github.com/valyala/fasthttp" "github.com/versity/versitygw/debuglogger" @@ -71,7 +71,7 @@ func GetUserMetaData(headers *fasthttp.RequestHeader) (metadata map[string]strin return } -func createHttpRequestFromCtx(ctx *fiber.Ctx, signedHdrs []string, contentLength int64, streamBody bool) (*http.Request, error) { +func createHttpRequestFromCtx(ctx fiber.Ctx, signedHdrs []string, contentLength int64, streamBody bool) (*http.Request, error) { req := ctx.Request() var body io.Reader if streamBody { @@ -126,7 +126,7 @@ var ( } ) -func createPresignedHttpRequestFromCtx(ctx *fiber.Ctx, signedHdrs []string, contentLength int64, streamBody bool) (*http.Request, error) { +func createPresignedHttpRequestFromCtx(ctx fiber.Ctx, signedHdrs []string, contentLength int64, streamBody bool) (*http.Request, error) { req := ctx.Request() var body io.Reader if streamBody { @@ -177,7 +177,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) @@ -267,17 +267,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 { @@ -361,7 +361,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() { @@ -400,7 +400,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") @@ -482,7 +482,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 @@ -525,7 +525,7 @@ func ParseCalculatedChecksumHeaders(ctx *fiber.Ctx) (ChecksumValues, error) { // ParseCompleteMpChecksumHeaders parses and validates // the 'CompleteMultipartUpload' x-amz-checksum-x headers // by supporting both 'checksum' and 'checksum-' 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 { @@ -559,7 +559,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 { @@ -718,7 +718,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 @@ -918,7 +918,7 @@ func ValidateCopySource(copysource 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 @@ -950,9 +950,9 @@ func ValidateVersionId(versionId string) error { // 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) @@ -1011,7 +1011,7 @@ func NewTLSListener(network string, address string, getCertificateFunc func(*tls // since ACL operations are not supported on objects, the presence of any ACL headers // results in a NotImplemented error. It returns nil only when all ACL headers // are absent. -func ValidateNoACLHeaders(ctx *fiber.Ctx) error { +func ValidateNoACLHeaders(ctx fiber.Ctx) error { for _, header := range []string{ "x-amz-acl", "x-amz-grant-full-control", diff --git a/s3api/utils/utils_test.go b/s3api/utils/utils_test.go index 077dc9dc..0148d5c0 100644 --- a/s3api/utils/utils_test.go +++ b/s3api/utils/utils_test.go @@ -25,7 +25,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" @@ -35,7 +35,7 @@ import ( func TestCreateHttpRequestFromCtx(t *testing.T) { type args struct { - ctx *fiber.Ctx + ctx fiber.Ctx } app := fiber.New() diff --git a/s3event/event.go b/s3event/event.go index 2e6f53ac..c3d69731 100644 --- a/s3event/event.go +++ b/s3event/event.go @@ -20,13 +20,13 @@ import ( "strings" "time" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" "github.com/versity/versitygw/auth" "github.com/versity/versitygw/s3api/utils" ) type S3EventSender interface { - SendEvent(ctx *fiber.Ctx, meta EventMeta) + SendEvent(ctx fiber.Ctx, meta EventMeta) Close() error } @@ -147,7 +147,7 @@ func InitEventSender(cfg *EventConfig) (S3EventSender, error) { return evSender, err } -func createEventSchema(ctx *fiber.Ctx, meta EventMeta, configId ConfigurationId) EventSchema { +func createEventSchema(ctx fiber.Ctx, meta EventMeta, configId ConfigurationId) EventSchema { path := strings.Split(ctx.Path(), "/") var bucket, object string diff --git a/s3event/kafka.go b/s3event/kafka.go index 257c1c44..bbd50664 100644 --- a/s3event/kafka.go +++ b/s3event/kafka.go @@ -23,7 +23,7 @@ import ( "sync" "time" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" "github.com/segmentio/kafka-go" "github.com/versity/versitygw/s3response" ) @@ -73,7 +73,7 @@ func InitKafkaEventService(url, topic, key string, filter EventFilter) (S3EventS }, nil } -func (ks *Kafka) SendEvent(ctx *fiber.Ctx, meta EventMeta) { +func (ks *Kafka) SendEvent(ctx fiber.Ctx, meta EventMeta) { ks.mu.Lock() defer ks.mu.Unlock() @@ -84,7 +84,7 @@ func (ks *Kafka) SendEvent(ctx *fiber.Ctx, meta EventMeta) { if meta.EventName == EventObjectRemovedDeleteObjects { var dObj s3response.DeleteObjects - if err := xml.Unmarshal(ctx.Body(), &dObj); err != nil { + if err := xml.Unmarshal(ctx.BodyRaw(), &dObj); err != nil { fmt.Fprintf(os.Stderr, "failed to parse delete objects input payload: %v\n", err.Error()) return } diff --git a/s3event/nats.go b/s3event/nats.go index 189105aa..6ae3e621 100644 --- a/s3event/nats.go +++ b/s3event/nats.go @@ -21,7 +21,7 @@ import ( "os" "sync" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" "github.com/nats-io/nats.go" "github.com/versity/versitygw/s3response" ) @@ -60,7 +60,7 @@ func InitNatsEventService(url, topic string, filter EventFilter) (S3EventSender, }, nil } -func (ns *NatsEventSender) SendEvent(ctx *fiber.Ctx, meta EventMeta) { +func (ns *NatsEventSender) SendEvent(ctx fiber.Ctx, meta EventMeta) { ns.mu.Lock() defer ns.mu.Unlock() @@ -71,7 +71,7 @@ func (ns *NatsEventSender) SendEvent(ctx *fiber.Ctx, meta EventMeta) { if meta.EventName == EventObjectRemovedDeleteObjects { var dObj s3response.DeleteObjects - if err := xml.Unmarshal(ctx.Body(), &dObj); err != nil { + if err := xml.Unmarshal(ctx.BodyRaw(), &dObj); err != nil { fmt.Fprintf(os.Stderr, "failed to parse delete objects input payload: %v\n", err.Error()) return } diff --git a/s3event/rabbitmq.go b/s3event/rabbitmq.go index fb35f113..8c38f444 100644 --- a/s3event/rabbitmq.go +++ b/s3event/rabbitmq.go @@ -22,7 +22,7 @@ import ( "sync" "time" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" "github.com/google/uuid" amqp "github.com/rabbitmq/amqp091-go" "github.com/versity/versitygw/s3response" @@ -87,7 +87,7 @@ func InitRabbitmqEventService(url, exchange, routingKey string, filter EventFilt }, nil } -func (rs *RabbitmqEventSender) SendEvent(ctx *fiber.Ctx, meta EventMeta) { +func (rs *RabbitmqEventSender) SendEvent(ctx fiber.Ctx, meta EventMeta) { rs.mu.Lock() defer rs.mu.Unlock() @@ -97,7 +97,7 @@ func (rs *RabbitmqEventSender) SendEvent(ctx *fiber.Ctx, meta EventMeta) { if meta.EventName == EventObjectRemovedDeleteObjects { var dObj s3response.DeleteObjects - if err := xml.Unmarshal(ctx.Body(), &dObj); err != nil { + if err := xml.Unmarshal(ctx.BodyRaw(), &dObj); err != nil { fmt.Fprintf(os.Stderr, "failed to parse delete objects input payload: %v\n", err.Error()) return } diff --git a/s3event/webhook.go b/s3event/webhook.go index bce571c6..327d6b2f 100644 --- a/s3event/webhook.go +++ b/s3event/webhook.go @@ -25,7 +25,7 @@ import ( "sync" "time" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" "github.com/versity/versitygw/s3response" ) @@ -72,7 +72,7 @@ func InitWebhookEventSender(url string, filter EventFilter) (S3EventSender, erro }, nil } -func (w *Webhook) SendEvent(ctx *fiber.Ctx, meta EventMeta) { +func (w *Webhook) SendEvent(ctx fiber.Ctx, meta EventMeta) { w.mu.Lock() defer w.mu.Unlock() @@ -83,7 +83,7 @@ func (w *Webhook) SendEvent(ctx *fiber.Ctx, meta EventMeta) { if meta.EventName == EventObjectRemovedDeleteObjects { var dObj s3response.DeleteObjects - if err := xml.Unmarshal(ctx.Body(), &dObj); err != nil { + if err := xml.Unmarshal(ctx.BodyRaw(), &dObj); err != nil { fmt.Fprintf(os.Stderr, "failed to parse delete objects input payload: %v\n", err.Error()) return } diff --git a/s3log/audit-logger.go b/s3log/audit-logger.go index 24796a45..852c10ce 100644 --- a/s3log/audit-logger.go +++ b/s3log/audit-logger.go @@ -22,11 +22,11 @@ import ( "strings" "time" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" ) type AuditLogger interface { - Log(ctx *fiber.Ctx, err error, body []byte, meta LogMeta) + Log(ctx fiber.Ctx, err error, body []byte, meta LogMeta) HangUp() error Shutdown() error } diff --git a/s3log/file.go b/s3log/file.go index e2e8b417..fff497b7 100644 --- a/s3log/file.go +++ b/s3log/file.go @@ -22,7 +22,7 @@ import ( "sync" "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" @@ -56,7 +56,7 @@ func InitFileLogger(logname string) (AuditLogger, error) { } // Log sends log message to file logger -func (f *FileLogger) Log(ctx *fiber.Ctx, err error, body []byte, meta LogMeta) { +func (f *FileLogger) Log(ctx fiber.Ctx, err error, body []byte, meta LogMeta) { f.mu.Lock() defer f.mu.Unlock() @@ -79,7 +79,7 @@ func (f *FileLogger) Log(ctx *fiber.Ctx, err error, body []byte, meta LogMeta) { if !ok { startTime = time.Now() } - tlsConnState := ctx.Context().TLSConnectionState() + tlsConnState := ctx.RequestCtx().TLSConnectionState() if tlsConnState != nil { lf.CipherSuite = tls.CipherSuiteName(tlsConnState.CipherSuite) lf.TLSVersion = getTLSVersionName(tlsConnState.Version) diff --git a/s3log/file_admin.go b/s3log/file_admin.go index 9b6f8129..940a914d 100644 --- a/s3log/file_admin.go +++ b/s3log/file_admin.go @@ -20,7 +20,7 @@ import ( "os" "time" - "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v3" "github.com/versity/versitygw/auth" "github.com/versity/versitygw/s3api/utils" ) @@ -45,7 +45,7 @@ func InitAdminFileLogger(logname string) (AuditLogger, error) { } // Log sends log message to file logger -func (f *AdminFileLogger) Log(ctx *fiber.Ctx, err error, body []byte, meta LogMeta) { +func (f *AdminFileLogger) Log(ctx fiber.Ctx, err error, body []byte, meta LogMeta) { f.mu.Lock() defer f.mu.Unlock() @@ -62,7 +62,7 @@ func (f *AdminFileLogger) Log(ctx *fiber.Ctx, err error, body []byte, meta LogMe if !ok { startTime = time.Now() } - tlsConnState := ctx.Context().TLSConnectionState() + tlsConnState := ctx.RequestCtx().TLSConnectionState() if tlsConnState != nil { lf.CipherSuite = tls.CipherSuiteName(tlsConnState.CipherSuite) lf.TLSVersion = getTLSVersionName(tlsConnState.Version) diff --git a/s3log/webhook.go b/s3log/webhook.go index 989977ef..72af9e8f 100644 --- a/s3log/webhook.go +++ b/s3log/webhook.go @@ -26,7 +26,7 @@ import ( "sync" "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" @@ -57,7 +57,7 @@ func InitWebhookLogger(url string) (AuditLogger, error) { } // Log sends log message to webhook -func (wl *WebhookLogger) Log(ctx *fiber.Ctx, err error, body []byte, meta LogMeta) { +func (wl *WebhookLogger) Log(ctx fiber.Ctx, err error, body []byte, meta LogMeta) { wl.mu.Lock() defer wl.mu.Unlock() @@ -76,7 +76,7 @@ func (wl *WebhookLogger) Log(ctx *fiber.Ctx, err error, body []byte, meta LogMet if !ok { startTime = time.Now() } - tlsConnState := ctx.Context().TLSConnectionState() + tlsConnState := ctx.RequestCtx().TLSConnectionState() if tlsConnState != nil { lf.CipherSuite = tls.CipherSuiteName(tlsConnState.CipherSuite) lf.TLSVersion = getTLSVersionName(tlsConnState.Version) diff --git a/v3 b/v3 new file mode 100644 index 00000000..56b06018 --- /dev/null +++ b/v3 @@ -0,0 +1 @@ +branch 'sis/fiber-mgration-v2-' set up to track 'origin/sis/fiber-mgration-v2-'. diff --git a/webui/webserver.go b/webui/webserver.go index aae23724..db11412c 100644 --- a/webui/webserver.go +++ b/webui/webserver.go @@ -16,13 +16,13 @@ package webui import ( "fmt" - "net/http" + "io/fs" "strings" - "github.com/gofiber/fiber/v2" - "github.com/gofiber/fiber/v2/middleware/filesystem" - "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/gofiber/fiber/v3/middleware/static" "github.com/versity/versitygw/s3api/utils" ) @@ -57,11 +57,10 @@ func WithTLS(cs *utils.CertStorage) Option { } // NewServer creates a new GUI server instance -func NewServer(cfg *ServerConfig, opts ...Option) *Server { +func NewServer(cfg *ServerConfig, opts ...Option) (*Server, error) { app := fiber.New(fiber.Config{ - AppName: "versitygw", - ServerHeader: "VERSITYGW", - DisableStartupMessage: true, + AppName: "versitygw", + ServerHeader: "VERSITYGW", }) server := &Server{ @@ -74,43 +73,55 @@ func NewServer(cfg *ServerConfig, opts ...Option) *Server { } server.setupMiddleware() - server.setupRoutes() + err := server.setupRoutes() + if err != nil { + return nil, err + } fmt.Printf("initializing web dashboard on %s\n", cfg.ListenAddr) - return server + return server, nil } // setupMiddleware configures middleware func (s *Server) setupMiddleware() { // Panic recovery - s.app.Use(recover.New()) + s.app.Use("*", recover.New()) // Request logging if !s.quiet { - s.app.Use(logger.New(logger.Config{ + s.app.Use("*", logger.New(logger.Config{ Format: "${time} | web | ${status} | ${latency} | ${ip} | ${method} | ${path}\n", })) } } // setupRoutes configures all routes -func (s *Server) setupRoutes() { +func (s *Server) setupRoutes() error { // API endpoint to get configured gateways s.app.Get("/api/gateways", s.handleGetGateways) - // Serve embedded static files from web/ - s.app.Use("/", filesystem.New(filesystem.Config{ - Root: http.FS(webFS), - PathPrefix: "web", - Index: "index.html", - NotFoundFile: "index.html", // SPA fallback - Browse: false, + // create a subtree from 'web' directory + // so that routing works correctly + // currently there's a bug in fasthttp resolving fs root + // https://github.com/valyala/fasthttp/issues/2141 + // TODO: remove sub fs after the bug fix + subFS, err := fs.Sub(webFS, "web") + if err != nil { + return err + } + + s.app.Use("/", static.New("", static.Config{ + FS: subFS, + Browse: false, + IndexNames: []string{"index.html"}, })) + + return nil } // handleGetGateways returns the configured gateway URLs (both S3 and Admin) -func (s *Server) handleGetGateways(c *fiber.Ctx) error { +func (s *Server) handleGetGateways(c fiber.Ctx) error { adminGateways := s.config.AdminGateways if len(adminGateways) == 0 { // Fallback to S3 gateways if admin gateways not configured @@ -133,15 +144,23 @@ func (s *Server) Serve() error { // Check if TLS is configured if s.CertStorage != nil { - ln, err := utils.NewTLSListener(s.app.Config().Network, addr, s.CertStorage.GetCertificate) + ln, err := utils.NewTLSListener(fiber.NetworkTCP, addr, s.CertStorage.GetCertificate) if err != nil { return err } - return s.app.Listener(ln) + return s.app.Listener(ln, + fiber.ListenConfig{ + ListenerNetwork: fiber.NetworkTCP, + DisableStartupMessage: true, + }) } - return s.app.Listen(addr) + return s.app.Listen(addr, + fiber.ListenConfig{ + ListenerNetwork: fiber.NetworkTCP, + DisableStartupMessage: true, + }) } // Shutdown gracefully shuts down the server