diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index aa9c94597f..6c378e4043 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -37,4 +37,4 @@ jobs: uses: golangci/golangci-lint-action@v6 with: # NOTE: Keep this in sync with the version from .golangci.yml - version: v1.60.1 + version: v1.60.3 diff --git a/.github/workflows/markdown.yml b/.github/workflows/markdown.yml index 21ba3632f9..cc131e7fb2 100644 --- a/.github/workflows/markdown.yml +++ b/.github/workflows/markdown.yml @@ -5,11 +5,7 @@ on: branches: - master - main - paths: - - "**/*.md" pull_request: - paths: - - "**/*.md" jobs: markdownlint: diff --git a/.golangci.yml b/.golangci.yml index 833cf407fd..8b8d27b853 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -278,7 +278,7 @@ linters: - depguard - dogsled # - dupl - # - dupword # TODO: Enable + - dupword # TODO: Enable - durationcheck - errcheck - errchkjson @@ -287,7 +287,7 @@ linters: - exhaustive # - exhaustivestruct # - exhaustruct - - exportloopref + - copyloopvar - forbidigo - forcetypeassert # - funlen @@ -298,7 +298,7 @@ linters: # - gochecknoinits # TODO: Enable - gochecksumtype # - gocognit - # - goconst # TODO: Enable + - goconst # TODO: Enable - gocritic # - gocyclo # - godot @@ -307,9 +307,8 @@ linters: - gofmt - gofumpt # - goheader - # - goimports - # - golint - # - gomnd # TODO: Enable + - goimports + # - mnd # TODO: Enable - gomoddirectives # - gomodguard - goprintffuncname diff --git a/Makefile b/Makefile index 38816fab62..1d7f57d03c 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ markdown: ## lint: 🚨 Run lint checks .PHONY: lint lint: - go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.60.1 run ./... + go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.60.3 run ./... ## test: 🚦 Execute all tests .PHONY: test diff --git a/addon/retry/exponential_backoff_test.go b/addon/retry/exponential_backoff_test.go index a3b31fc23c..844ed0df94 100644 --- a/addon/retry/exponential_backoff_test.go +++ b/addon/retry/exponential_backoff_test.go @@ -51,7 +51,6 @@ func Test_ExponentialBackoff_Retry(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() err := tt.expBackoff.Retry(tt.f) @@ -106,7 +105,6 @@ func Test_ExponentialBackoff_Next(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() for i := 0; i < tt.expBackoff.MaxRetryCount; i++ { diff --git a/client/core_test.go b/client/core_test.go index f189c9f8a3..36e8eb78d4 100644 --- a/client/core_test.go +++ b/client/core_test.go @@ -49,7 +49,6 @@ func Test_AddMissing_Port(t *testing.T) { }, } for _, tt := range tests { - tt := tt // create a new 'tt' variable for the goroutine t.Run(tt.name, func(t *testing.T) { t.Parallel() require.Equal(t, tt.want, addMissingPort(tt.args.addr, tt.args.isTLS)) diff --git a/client/hooks_test.go b/client/hooks_test.go index dfea361d54..359e3184d2 100644 --- a/client/hooks_test.go +++ b/client/hooks_test.go @@ -35,7 +35,6 @@ func Test_Rand_String(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() got := randString(tt.args) @@ -188,7 +187,7 @@ func Test_Parser_Request_URL(t *testing.T) { flag1 = true case "foo2": flag2 = true - case "foo": + case "foo": //nolint:goconst // test flag3 = true } } diff --git a/client/request_test.go b/client/request_test.go index 3724e165ce..0593d04824 100644 --- a/client/request_test.go +++ b/client/request_test.go @@ -1340,7 +1340,7 @@ func Test_SetValWithStruct(t *testing.T) { require.True(t, func() bool { for _, v := range p.PeekMulti("TSlice") { - if string(v) == "bar" { + if string(v) == "bar" { //nolint:goconst // test return true } } diff --git a/ctx_test.go b/ctx_test.go index a1685898b0..6dcd74109e 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -908,7 +908,6 @@ func Test_Ctx_UserContext_Multiple_Requests(t *testing.T) { // Consecutive Requests for i := 1; i <= 10; i++ { - i := i t.Run(fmt.Sprintf("request_%d", i), func(t *testing.T) { t.Parallel() resp, err := app.Test(httptest.NewRequest(MethodGet, fmt.Sprintf("/?input=%d", i), nil)) @@ -3122,8 +3121,6 @@ func Test_Static_Compress(t *testing.T) { // Note: deflate is not supported by fasthttp.FS algorithms := []string{"zstd", "gzip", "br"} for _, algo := range algorithms { - algo := algo - t.Run(algo+"_compression", func(t *testing.T) { t.Parallel() @@ -3338,7 +3335,6 @@ func Test_Ctx_SendFile_Immutable(t *testing.T) { } for _, endpoint := range endpointsForTest { - endpoint := endpoint t.Run(endpoint, func(t *testing.T) { t.Parallel() // 1st try diff --git a/helpers.go b/helpers.go index 2a2a2cbad2..90621b1c42 100644 --- a/helpers.go +++ b/helpers.go @@ -326,7 +326,7 @@ func getSplicedStrList(headerValue string, dst []string) []string { var ( index int character rune - lastElementEndsAt uint8 + lastElementEndsAt int insertIndex int ) for index, character = range headerValue + "$" { @@ -337,7 +337,7 @@ func getSplicedStrList(headerValue string, dst []string) []string { copy(dst, oldSlice) } dst[insertIndex] = utils.TrimLeft(headerValue[lastElementEndsAt:index], ' ') - lastElementEndsAt = uint8(index + 1) + lastElementEndsAt = index + 1 insertIndex++ } } @@ -766,6 +766,7 @@ func genericParseBool[V GenericType](str string, parser func(bool) V, defaultVal return genericParseDefault[V](err, func() V { return parser(result) }, defaultValue...) } +//nolint:gosec // Casting in this function is not a concern func genericParseType[V GenericType](str string, v V, defaultValue ...V) V { switch any(v).(type) { case int: diff --git a/middleware/compress/compress_test.go b/middleware/compress/compress_test.go index 34332e1202..f258ba4460 100644 --- a/middleware/compress/compress_test.go +++ b/middleware/compress/compress_test.go @@ -57,9 +57,7 @@ func Test_Compress_Different_Level(t *testing.T) { algorithms := []string{"gzip", "deflate", "br", "zstd"} for _, algo := range algorithms { - algo := algo for _, level := range levels { - level := level t.Run(fmt.Sprintf("%s_level %d", algo, level), func(t *testing.T) { t.Parallel() app := fiber.New() diff --git a/middleware/encryptcookie/encryptcookie_test.go b/middleware/encryptcookie/encryptcookie_test.go index 07e729471e..1e7b2d383b 100644 --- a/middleware/encryptcookie/encryptcookie_test.go +++ b/middleware/encryptcookie/encryptcookie_test.go @@ -44,7 +44,6 @@ func Test_Middleware_InvalidKeys(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(strconv.Itoa(tt.length)+"_length_encrypt", func(t *testing.T) { t.Parallel() key := make([]byte, tt.length) @@ -296,7 +295,6 @@ func Test_GenerateKey(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(strconv.Itoa(tt.length)+"_length", func(t *testing.T) { t.Parallel() key := GenerateKey(tt.length) diff --git a/middleware/etag/etag.go b/middleware/etag/etag.go index 2a2c0ae161..aca57bc1e7 100644 --- a/middleware/etag/etag.go +++ b/middleware/etag/etag.go @@ -3,6 +3,7 @@ package etag import ( "bytes" "hash/crc32" + "math" "github.com/gofiber/fiber/v3" "github.com/valyala/bytebufferpool" @@ -56,8 +57,15 @@ func New(config ...Config) fiber.Handler { bb.Write(weakPrefix) } + // Write ETag bb.WriteByte('"') - bb.B = appendUint(bb.Bytes(), uint32(len(body))) + + bodyLength := len(body) + if bodyLength > math.MaxUint32 { + return c.SendStatus(fiber.StatusRequestEntityTooLarge) + } + + bb.B = appendUint(bb.Bytes(), uint32(bodyLength)) //nolint:gosec // Body length is validated above bb.WriteByte('-') bb.B = appendUint(bb.Bytes(), crc32.Checksum(body, crc32q)) bb.WriteByte('"') diff --git a/middleware/limiter/limiter_sliding.go b/middleware/limiter/limiter_sliding.go index 8eeb3f8222..de2f7d3b91 100644 --- a/middleware/limiter/limiter_sliding.go +++ b/middleware/limiter/limiter_sliding.go @@ -89,14 +89,14 @@ func (SlidingWindow) New(cfg Config) fiber.Handler { // ^ ^ ^ ^ // ts e.exp End sample window End next window // <------------> - // resetInSec + // Reset In Sec // resetInSec = e.exp - ts - time until end of current window. // duration + expiration = end of next window. // Because we don't want to garbage collect in the middle of a window // we add the expiration to the duration. // Otherwise after the end of "sample window", attackers could launch // a new request with the full window length. - manager.set(key, e, time.Duration(resetInSec+expiration)*time.Second) + manager.set(key, e, time.Duration(resetInSec+expiration)*time.Second) //nolint:gosec // Not a concern // Unlock entry mux.Unlock() diff --git a/middleware/limiter/limiter_test.go b/middleware/limiter/limiter_test.go index bd277ff1db..ac79214f07 100644 --- a/middleware/limiter/limiter_test.go +++ b/middleware/limiter/limiter_test.go @@ -28,7 +28,7 @@ func Test_Limiter_With_Max_Func_With_Zero_And_Limiter_Sliding(t *testing.T) { })) app.Get("/:status", func(c fiber.Ctx) error { - if c.Params("status") == "fail" { + if c.Params("status") == "fail" { //nolint:goconst // test return c.SendStatus(400) } return c.SendStatus(200) @@ -241,7 +241,7 @@ func Test_Limiter_Fixed_Window_No_Skip_Choices(t *testing.T) { })) app.Get("/:status", func(c fiber.Ctx) error { - if c.Params("status") == "fail" { //nolint:goconst // False positive + if c.Params("status") == "fail" { return c.SendStatus(400) } return c.SendStatus(200) diff --git a/middleware/pprof/pprof_test.go b/middleware/pprof/pprof_test.go index fd450657bd..7a279d488d 100644 --- a/middleware/pprof/pprof_test.go +++ b/middleware/pprof/pprof_test.go @@ -100,7 +100,6 @@ func Test_Pprof_Subs(t *testing.T) { } for _, sub := range subs { - sub := sub t.Run(sub, func(t *testing.T) { target := "/debug/pprof/" + sub if sub == "profile" { @@ -128,7 +127,6 @@ func Test_Pprof_Subs_WithPrefix(t *testing.T) { } for _, sub := range subs { - sub := sub t.Run(sub, func(t *testing.T) { target := "/federated-fiber/debug/pprof/" + sub if sub == "profile" { diff --git a/middleware/static/static_test.go b/middleware/static/static_test.go index 8f457b23ad..4d736b0c43 100644 --- a/middleware/static/static_test.go +++ b/middleware/static/static_test.go @@ -723,7 +723,7 @@ func Test_isFile(t *testing.T) { func Test_Static_Compress(t *testing.T) { t.Parallel() - dir := "../../.github/testdata/fs" + dir := "../../.github/testdata/fs" //nolint:goconst // test app := fiber.New() app.Get("/*", New(dir, Config{ Compress: true, @@ -733,7 +733,6 @@ func Test_Static_Compress(t *testing.T) { algorithms := []string{"zstd", "gzip", "br"} for _, algo := range algorithms { - algo := algo t.Run(algo+"_compression", func(t *testing.T) { t.Parallel() // request non-compressable file (less than 200 bytes), Content Lengh will remain the same diff --git a/mount.go b/mount.go index 61614a2f25..d97b226dfc 100644 --- a/mount.go +++ b/mount.go @@ -188,7 +188,7 @@ func (app *App) processSubAppsRoutes() { // If not, update the route's position and continue route.pos = routePos if !route.use || (route.use && m == 0) { - handlersCount += uint32(len(route.Handlers)) + handlersCount += uint32(len(route.Handlers)) //nolint:gosec // Not a concern } continue } @@ -219,7 +219,7 @@ func (app *App) processSubAppsRoutes() { atomic.AddUint32(&app.routesCount, ^uint32(0)) i-- // Increase the parent app's route count to account for the sub-app's routes - atomic.AddUint32(&app.routesCount, uint32(len(subRoutes))) + atomic.AddUint32(&app.routesCount, uint32(len(subRoutes))) //nolint:gosec // Not a concern // Mark the parent app's routes as refreshed app.routesRefreshed = true diff --git a/mount_test.go b/mount_test.go index cd021b248a..bb57fbbc1d 100644 --- a/mount_test.go +++ b/mount_test.go @@ -347,7 +347,7 @@ func Test_App_UseMountedErrorHandlerForBestPrefixMatch(t *testing.T) { app := New() tsf := func(c Ctx, _ error) error { - return c.Status(200).SendString("hi, i'm a custom sub sub fiber error") + return c.Status(200).SendString("hi, i'm a custom sub fiber error 2") } tripleSubFiber := New(Config{ ErrorHandler: tsf, @@ -394,7 +394,7 @@ func Test_App_UseMountedErrorHandlerForBestPrefixMatch(t *testing.T) { b, err = io.ReadAll(resp2.Body) require.NoError(t, err, "iotuil.ReadAll()") - require.Equal(t, "hi, i'm a custom sub sub fiber error", string(b), "Third fiber Response body") + require.Equal(t, "hi, i'm a custom sub fiber error 2", string(b), "Third fiber Response body") } // go test -run Test_Mount_Route_Names diff --git a/router.go b/router.go index 5b06ae3e84..d2429c194e 100644 --- a/router.go +++ b/router.go @@ -358,7 +358,7 @@ func (app *App) register(methods []string, pathRaw string, group *Group, handler Handlers: handlers, } // Increment global handler count - atomic.AddUint32(&app.handlersCount, uint32(len(handlers))) + atomic.AddUint32(&app.handlersCount, uint32(len(handlers))) //nolint:gosec // Not a concern // Middleware route matches all HTTP methods if isUse {