feat: fiber migration v2 -> v3

Fiber has released a new major version, **v3.0.0**, introducing several breaking changes. As part of the gateway migration from Fiber v2 to v3, the `filesystem` middleware has been deprecated and replaced with the `static` middleware for serving web assets. Currently, Fiber’s `static` middleware contains a bug in how it resolves the filesystem root path. Because of this, `fs.Sub` is used to set the embedded `web` directory as the effective root of the filesystem.
This commit is contained in:
niksis02
2026-02-11 19:29:19 +04:00
parent fc01ece8ba
commit 2b7c2e25ba
67 changed files with 529 additions and 480 deletions
+4 -1
View File
@@ -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 {
+4 -4
View File
@@ -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
+10 -4
View File
@@ -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
+16 -8
View File
@@ -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=
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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"
+21 -15
View File
@@ -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
+13 -13
View File
@@ -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 {
+10 -10
View File
@@ -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
}
+31 -31
View File
@@ -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
})
+16 -16
View File
@@ -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,
+40 -40
View File
@@ -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{
+4 -4
View File
@@ -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,
})
+3 -3
View File
@@ -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,
+6 -6
View File
@@ -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{
+35 -35
View File
@@ -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,
@@ -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)
},
)
+11 -11
View File
@@ -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,
+23 -23
View File
@@ -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,
+5 -5
View File
@@ -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,
+18 -18
View File
@@ -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,
+33 -33
View File
@@ -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,
+3 -3
View File
@@ -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)) {
+3 -3
View File
@@ -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
}
+2 -2
View File
@@ -15,7 +15,7 @@
package middlewares
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
"github.com/versity/versitygw/auth"
"github.com/versity/versitygw/s3api/utils"
"github.com/versity/versitygw/s3err"
@@ -23,7 +23,7 @@ import (
// IsAdmin is a middleware that restricts access to admin APIs, allowing only admin users
func IsAdmin(action string) fiber.Handler {
return func(ctx *fiber.Ctx) error {
return func(ctx fiber.Ctx) error {
acct := utils.ContextKeyAccount.Get(ctx).(auth.Account)
if acct.Role != auth.RoleAdmin {
return s3err.GetAPIError(s3err.ErrAdminAccessDenied)
@@ -17,7 +17,7 @@ package middlewares
import (
"strings"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
"github.com/versity/versitygw/backend"
"github.com/versity/versitygw/s3err"
)
@@ -36,12 +36,12 @@ import (
func ApplyBucketCORSPreflightFallback(be backend.Backend, fallbackOrigin string) fiber.Handler {
fallbackOrigin = strings.TrimSpace(fallbackOrigin)
if fallbackOrigin == "" {
return func(ctx *fiber.Ctx) error { return ctx.Next() }
return func(ctx fiber.Ctx) error { return ctx.Next() }
}
return func(ctx *fiber.Ctx) error {
return func(ctx fiber.Ctx) error {
bucket := ctx.Params("bucket")
_, err := be.GetBucketCors(ctx.Context(), bucket)
_, err := be.GetBucketCors(ctx.RequestCtx(), bucket)
if err != nil {
if s3Err, ok := err.(s3err.APIError); ok && (s3Err.Code == "NoSuchCORSConfiguration" || s3Err.Code == "NoSuchBucket") {
if len(ctx.Response().Header.Peek("Access-Control-Allow-Origin")) == 0 {
@@ -19,7 +19,7 @@ import (
"net/http"
"testing"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
"github.com/versity/versitygw/backend"
"github.com/versity/versitygw/s3err"
)
@@ -43,7 +43,7 @@ func TestApplyBucketCORSPreflightFallback_NoBucketCors_Responds204(t *testing.T)
app := fiber.New()
app.Options("/:bucket",
ApplyBucketCORSPreflightFallback(be, "https://example.com"),
func(c *fiber.Ctx) error {
func(c fiber.Ctx) error {
// Should not be reached if fallback triggers
return c.SendStatus(http.StatusTeapot)
},
@@ -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)
},
)
+3 -3
View File
@@ -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.
@@ -17,7 +17,7 @@ package middlewares
import (
"strings"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
)
// ApplyDefaultCORSPreflight responds to CORS preflight (OPTIONS) requests for routes
@@ -29,10 +29,10 @@ import (
func ApplyDefaultCORSPreflight(fallbackOrigin string) fiber.Handler {
fallbackOrigin = strings.TrimSpace(fallbackOrigin)
if fallbackOrigin == "" {
return func(ctx *fiber.Ctx) error { return nil }
return func(ctx fiber.Ctx) error { return nil }
}
return func(ctx *fiber.Ctx) error {
return func(ctx fiber.Ctx) error {
if len(ctx.Response().Header.Peek("Access-Control-Allow-Origin")) == 0 {
ctx.Response().Header.Add("Access-Control-Allow-Origin", fallbackOrigin)
}
@@ -18,7 +18,7 @@ import (
"net/http"
"testing"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
)
func TestApplyDefaultCORSPreflight_OptionsSetsPreflightHeaders(t *testing.T) {
@@ -28,7 +28,7 @@ func TestApplyDefaultCORSPreflight_OptionsSetsPreflightHeaders(t *testing.T) {
app.Options("/admin",
ApplyDefaultCORSPreflight(origin),
ApplyDefaultCORS(origin),
func(c *fiber.Ctx) error { return nil },
func(c fiber.Ctx) error { return nil },
)
req, err := http.NewRequest(http.MethodOptions, "/admin", nil)
+4 -4
View File
@@ -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)
}
+4 -4
View File
@@ -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)
})
+3 -3
View File
@@ -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
+2 -2
View File
@@ -18,7 +18,7 @@ import (
"bytes"
"io"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
"github.com/versity/versitygw/s3api/utils"
)
@@ -85,7 +85,7 @@ func (rr *MockChecksumReader) Checksum() string {
var _ ChecksumReader = &MockChecksumReader{}
func wrapBodyReader(ctx *fiber.Ctx, wr func(io.Reader) io.Reader) {
func wrapBodyReader(ctx fiber.Ctx, wr func(io.Reader) io.Reader) {
rdr, ok := utils.ContextKeyBodyReader.Get(ctx).(io.Reader)
if !ok {
rdr = ctx.Request().BodyStream()
@@ -15,7 +15,7 @@
package middlewares
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
"github.com/versity/versitygw/s3api/utils"
"github.com/versity/versitygw/s3err"
)
@@ -23,7 +23,7 @@ import (
// BucketObjectNameValidator extracts and validates
// the bucket and object names from the request URI.
func BucketObjectNameValidator() fiber.Handler {
return func(ctx *fiber.Ctx) error {
return func(ctx fiber.Ctx) error {
bucket, object := parsePath(ctx.Path())
// check if the provided bucket name is valid
+3 -3
View File
@@ -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)
}
+2 -2
View File
@@ -18,13 +18,13 @@ import (
"fmt"
"strings"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
)
// HostStyleParser is a middleware which parses the bucket name
// from the 'Host' header and appends in the request URL path
func HostStyleParser(virtualDomain string) fiber.Handler {
return func(ctx *fiber.Ctx) error {
return func(ctx fiber.Ctx) error {
host := string(ctx.Request().Host())
// the host should match this pattern: '<bucket_name>.<virtual_domain>'
bucket, _, found := strings.Cut(host, "."+virtualDomain)
+2 -2
View File
@@ -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)
+2 -2
View File
@@ -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
+4 -4
View File
@@ -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
+4 -4
View File
@@ -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()
}
+2 -2
View File
@@ -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())
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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"
+27 -22
View File
@@ -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
+1 -1
View File
@@ -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"
)
+4 -4
View File
@@ -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
+12 -11
View File
@@ -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)
}
+4 -4
View File
@@ -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
+5 -5
View File
@@ -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))
}
+5 -5
View File
@@ -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
+7 -7
View File
@@ -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")
+18 -18
View File
@@ -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-<part_length>' formats
func ParseCompleteMpChecksumHeaders(ctx *fiber.Ctx) (ChecksumValues, error) {
func ParseCompleteMpChecksumHeaders(ctx fiber.Ctx) (ChecksumValues, error) {
// first parse/validate 'x-amz-checksum-x' headers
checksums, err := ParseCalculatedChecksumHeaders(ctx)
if err != nil {
@@ -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",
+2 -2
View File
@@ -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()
+3 -3
View File
@@ -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
+3 -3
View File
@@ -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
}
+3 -3
View File
@@ -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
}
+3 -3
View File
@@ -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
}
+3 -3
View File
@@ -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
}
+2 -2
View File
@@ -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
}
+3 -3
View File
@@ -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)
+3 -3
View File
@@ -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)
+3 -3
View File
@@ -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)
+1
View File
@@ -0,0 +1 @@
branch 'sis/fiber-mgration-v2-' set up to track 'origin/sis/fiber-mgration-v2-'.
+44 -25
View File
@@ -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