mirror of https://github.com/gofiber/fiber.git
parent
4acdc602ce
commit
f668537c02
|
@ -37,4 +37,4 @@ jobs:
|
||||||
uses: golangci/golangci-lint-action@v6
|
uses: golangci/golangci-lint-action@v6
|
||||||
with:
|
with:
|
||||||
# NOTE: Keep this in sync with the version from .golangci.yml
|
# NOTE: Keep this in sync with the version from .golangci.yml
|
||||||
version: v1.60.1
|
version: v1.60.3
|
||||||
|
|
|
@ -5,11 +5,7 @@ on:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- main
|
- main
|
||||||
paths:
|
|
||||||
- "**/*.md"
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
|
||||||
- "**/*.md"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
markdownlint:
|
markdownlint:
|
||||||
|
|
|
@ -278,7 +278,7 @@ linters:
|
||||||
- depguard
|
- depguard
|
||||||
- dogsled
|
- dogsled
|
||||||
# - dupl
|
# - dupl
|
||||||
# - dupword # TODO: Enable
|
- dupword # TODO: Enable
|
||||||
- durationcheck
|
- durationcheck
|
||||||
- errcheck
|
- errcheck
|
||||||
- errchkjson
|
- errchkjson
|
||||||
|
@ -287,7 +287,7 @@ linters:
|
||||||
- exhaustive
|
- exhaustive
|
||||||
# - exhaustivestruct
|
# - exhaustivestruct
|
||||||
# - exhaustruct
|
# - exhaustruct
|
||||||
- exportloopref
|
- copyloopvar
|
||||||
- forbidigo
|
- forbidigo
|
||||||
- forcetypeassert
|
- forcetypeassert
|
||||||
# - funlen
|
# - funlen
|
||||||
|
@ -298,7 +298,7 @@ linters:
|
||||||
# - gochecknoinits # TODO: Enable
|
# - gochecknoinits # TODO: Enable
|
||||||
- gochecksumtype
|
- gochecksumtype
|
||||||
# - gocognit
|
# - gocognit
|
||||||
# - goconst # TODO: Enable
|
- goconst # TODO: Enable
|
||||||
- gocritic
|
- gocritic
|
||||||
# - gocyclo
|
# - gocyclo
|
||||||
# - godot
|
# - godot
|
||||||
|
@ -307,9 +307,8 @@ linters:
|
||||||
- gofmt
|
- gofmt
|
||||||
- gofumpt
|
- gofumpt
|
||||||
# - goheader
|
# - goheader
|
||||||
# - goimports
|
- goimports
|
||||||
# - golint
|
# - mnd # TODO: Enable
|
||||||
# - gomnd # TODO: Enable
|
|
||||||
- gomoddirectives
|
- gomoddirectives
|
||||||
# - gomodguard
|
# - gomodguard
|
||||||
- goprintffuncname
|
- goprintffuncname
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -35,7 +35,7 @@ markdown:
|
||||||
## lint: 🚨 Run lint checks
|
## lint: 🚨 Run lint checks
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
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
|
## test: 🚦 Execute all tests
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
|
|
|
@ -51,7 +51,6 @@ func Test_ExponentialBackoff_Retry(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
err := tt.expBackoff.Retry(tt.f)
|
err := tt.expBackoff.Retry(tt.f)
|
||||||
|
@ -106,7 +105,6 @@ func Test_ExponentialBackoff_Next(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
for i := 0; i < tt.expBackoff.MaxRetryCount; i++ {
|
for i := 0; i < tt.expBackoff.MaxRetryCount; i++ {
|
||||||
|
|
|
@ -49,7 +49,6 @@ func Test_AddMissing_Port(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt // create a new 'tt' variable for the goroutine
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
require.Equal(t, tt.want, addMissingPort(tt.args.addr, tt.args.isTLS))
|
require.Equal(t, tt.want, addMissingPort(tt.args.addr, tt.args.isTLS))
|
||||||
|
|
|
@ -35,7 +35,6 @@ func Test_Rand_String(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
got := randString(tt.args)
|
got := randString(tt.args)
|
||||||
|
@ -188,7 +187,7 @@ func Test_Parser_Request_URL(t *testing.T) {
|
||||||
flag1 = true
|
flag1 = true
|
||||||
case "foo2":
|
case "foo2":
|
||||||
flag2 = true
|
flag2 = true
|
||||||
case "foo":
|
case "foo": //nolint:goconst // test
|
||||||
flag3 = true
|
flag3 = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1340,7 +1340,7 @@ func Test_SetValWithStruct(t *testing.T) {
|
||||||
|
|
||||||
require.True(t, func() bool {
|
require.True(t, func() bool {
|
||||||
for _, v := range p.PeekMulti("TSlice") {
|
for _, v := range p.PeekMulti("TSlice") {
|
||||||
if string(v) == "bar" {
|
if string(v) == "bar" { //nolint:goconst // test
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -908,7 +908,6 @@ func Test_Ctx_UserContext_Multiple_Requests(t *testing.T) {
|
||||||
|
|
||||||
// Consecutive Requests
|
// Consecutive Requests
|
||||||
for i := 1; i <= 10; i++ {
|
for i := 1; i <= 10; i++ {
|
||||||
i := i
|
|
||||||
t.Run(fmt.Sprintf("request_%d", i), func(t *testing.T) {
|
t.Run(fmt.Sprintf("request_%d", i), func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
resp, err := app.Test(httptest.NewRequest(MethodGet, fmt.Sprintf("/?input=%d", i), nil))
|
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
|
// Note: deflate is not supported by fasthttp.FS
|
||||||
algorithms := []string{"zstd", "gzip", "br"}
|
algorithms := []string{"zstd", "gzip", "br"}
|
||||||
for _, algo := range algorithms {
|
for _, algo := range algorithms {
|
||||||
algo := algo
|
|
||||||
|
|
||||||
t.Run(algo+"_compression", func(t *testing.T) {
|
t.Run(algo+"_compression", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -3338,7 +3335,6 @@ func Test_Ctx_SendFile_Immutable(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, endpoint := range endpointsForTest {
|
for _, endpoint := range endpointsForTest {
|
||||||
endpoint := endpoint
|
|
||||||
t.Run(endpoint, func(t *testing.T) {
|
t.Run(endpoint, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// 1st try
|
// 1st try
|
||||||
|
|
|
@ -326,7 +326,7 @@ func getSplicedStrList(headerValue string, dst []string) []string {
|
||||||
var (
|
var (
|
||||||
index int
|
index int
|
||||||
character rune
|
character rune
|
||||||
lastElementEndsAt uint8
|
lastElementEndsAt int
|
||||||
insertIndex int
|
insertIndex int
|
||||||
)
|
)
|
||||||
for index, character = range headerValue + "$" {
|
for index, character = range headerValue + "$" {
|
||||||
|
@ -337,7 +337,7 @@ func getSplicedStrList(headerValue string, dst []string) []string {
|
||||||
copy(dst, oldSlice)
|
copy(dst, oldSlice)
|
||||||
}
|
}
|
||||||
dst[insertIndex] = utils.TrimLeft(headerValue[lastElementEndsAt:index], ' ')
|
dst[insertIndex] = utils.TrimLeft(headerValue[lastElementEndsAt:index], ' ')
|
||||||
lastElementEndsAt = uint8(index + 1)
|
lastElementEndsAt = index + 1
|
||||||
insertIndex++
|
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...)
|
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 {
|
func genericParseType[V GenericType](str string, v V, defaultValue ...V) V {
|
||||||
switch any(v).(type) {
|
switch any(v).(type) {
|
||||||
case int:
|
case int:
|
||||||
|
|
|
@ -57,9 +57,7 @@ func Test_Compress_Different_Level(t *testing.T) {
|
||||||
algorithms := []string{"gzip", "deflate", "br", "zstd"}
|
algorithms := []string{"gzip", "deflate", "br", "zstd"}
|
||||||
|
|
||||||
for _, algo := range algorithms {
|
for _, algo := range algorithms {
|
||||||
algo := algo
|
|
||||||
for _, level := range levels {
|
for _, level := range levels {
|
||||||
level := level
|
|
||||||
t.Run(fmt.Sprintf("%s_level %d", algo, level), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%s_level %d", algo, level), func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
app := fiber.New()
|
app := fiber.New()
|
||||||
|
|
|
@ -44,7 +44,6 @@ func Test_Middleware_InvalidKeys(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
|
||||||
t.Run(strconv.Itoa(tt.length)+"_length_encrypt", func(t *testing.T) {
|
t.Run(strconv.Itoa(tt.length)+"_length_encrypt", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
key := make([]byte, tt.length)
|
key := make([]byte, tt.length)
|
||||||
|
@ -296,7 +295,6 @@ func Test_GenerateKey(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
|
||||||
t.Run(strconv.Itoa(tt.length)+"_length", func(t *testing.T) {
|
t.Run(strconv.Itoa(tt.length)+"_length", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
key := GenerateKey(tt.length)
|
key := GenerateKey(tt.length)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package etag
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
|
"math"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v3"
|
"github.com/gofiber/fiber/v3"
|
||||||
"github.com/valyala/bytebufferpool"
|
"github.com/valyala/bytebufferpool"
|
||||||
|
@ -56,8 +57,15 @@ func New(config ...Config) fiber.Handler {
|
||||||
bb.Write(weakPrefix)
|
bb.Write(weakPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write ETag
|
||||||
bb.WriteByte('"')
|
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.WriteByte('-')
|
||||||
bb.B = appendUint(bb.Bytes(), crc32.Checksum(body, crc32q))
|
bb.B = appendUint(bb.Bytes(), crc32.Checksum(body, crc32q))
|
||||||
bb.WriteByte('"')
|
bb.WriteByte('"')
|
||||||
|
|
|
@ -89,14 +89,14 @@ func (SlidingWindow) New(cfg Config) fiber.Handler {
|
||||||
// ^ ^ ^ ^
|
// ^ ^ ^ ^
|
||||||
// ts e.exp End sample window End next window
|
// ts e.exp End sample window End next window
|
||||||
// <------------>
|
// <------------>
|
||||||
// resetInSec
|
// Reset In Sec
|
||||||
// resetInSec = e.exp - ts - time until end of current window.
|
// resetInSec = e.exp - ts - time until end of current window.
|
||||||
// duration + expiration = end of next window.
|
// duration + expiration = end of next window.
|
||||||
// Because we don't want to garbage collect in the middle of a window
|
// Because we don't want to garbage collect in the middle of a window
|
||||||
// we add the expiration to the duration.
|
// we add the expiration to the duration.
|
||||||
// Otherwise after the end of "sample window", attackers could launch
|
// Otherwise after the end of "sample window", attackers could launch
|
||||||
// a new request with the full window length.
|
// 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
|
// Unlock entry
|
||||||
mux.Unlock()
|
mux.Unlock()
|
||||||
|
|
|
@ -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 {
|
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(400)
|
||||||
}
|
}
|
||||||
return c.SendStatus(200)
|
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 {
|
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(400)
|
||||||
}
|
}
|
||||||
return c.SendStatus(200)
|
return c.SendStatus(200)
|
||||||
|
|
|
@ -100,7 +100,6 @@ func Test_Pprof_Subs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, sub := range subs {
|
for _, sub := range subs {
|
||||||
sub := sub
|
|
||||||
t.Run(sub, func(t *testing.T) {
|
t.Run(sub, func(t *testing.T) {
|
||||||
target := "/debug/pprof/" + sub
|
target := "/debug/pprof/" + sub
|
||||||
if sub == "profile" {
|
if sub == "profile" {
|
||||||
|
@ -128,7 +127,6 @@ func Test_Pprof_Subs_WithPrefix(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, sub := range subs {
|
for _, sub := range subs {
|
||||||
sub := sub
|
|
||||||
t.Run(sub, func(t *testing.T) {
|
t.Run(sub, func(t *testing.T) {
|
||||||
target := "/federated-fiber/debug/pprof/" + sub
|
target := "/federated-fiber/debug/pprof/" + sub
|
||||||
if sub == "profile" {
|
if sub == "profile" {
|
||||||
|
|
|
@ -723,7 +723,7 @@ func Test_isFile(t *testing.T) {
|
||||||
|
|
||||||
func Test_Static_Compress(t *testing.T) {
|
func Test_Static_Compress(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
dir := "../../.github/testdata/fs"
|
dir := "../../.github/testdata/fs" //nolint:goconst // test
|
||||||
app := fiber.New()
|
app := fiber.New()
|
||||||
app.Get("/*", New(dir, Config{
|
app.Get("/*", New(dir, Config{
|
||||||
Compress: true,
|
Compress: true,
|
||||||
|
@ -733,7 +733,6 @@ func Test_Static_Compress(t *testing.T) {
|
||||||
algorithms := []string{"zstd", "gzip", "br"}
|
algorithms := []string{"zstd", "gzip", "br"}
|
||||||
|
|
||||||
for _, algo := range algorithms {
|
for _, algo := range algorithms {
|
||||||
algo := algo
|
|
||||||
t.Run(algo+"_compression", func(t *testing.T) {
|
t.Run(algo+"_compression", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// request non-compressable file (less than 200 bytes), Content Lengh will remain the same
|
// request non-compressable file (less than 200 bytes), Content Lengh will remain the same
|
||||||
|
|
4
mount.go
4
mount.go
|
@ -188,7 +188,7 @@ func (app *App) processSubAppsRoutes() {
|
||||||
// If not, update the route's position and continue
|
// If not, update the route's position and continue
|
||||||
route.pos = routePos
|
route.pos = routePos
|
||||||
if !route.use || (route.use && m == 0) {
|
if !route.use || (route.use && m == 0) {
|
||||||
handlersCount += uint32(len(route.Handlers))
|
handlersCount += uint32(len(route.Handlers)) //nolint:gosec // Not a concern
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ func (app *App) processSubAppsRoutes() {
|
||||||
atomic.AddUint32(&app.routesCount, ^uint32(0))
|
atomic.AddUint32(&app.routesCount, ^uint32(0))
|
||||||
i--
|
i--
|
||||||
// Increase the parent app's route count to account for the sub-app's routes
|
// 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
|
// Mark the parent app's routes as refreshed
|
||||||
app.routesRefreshed = true
|
app.routesRefreshed = true
|
||||||
|
|
|
@ -347,7 +347,7 @@ func Test_App_UseMountedErrorHandlerForBestPrefixMatch(t *testing.T) {
|
||||||
app := New()
|
app := New()
|
||||||
|
|
||||||
tsf := func(c Ctx, _ error) error {
|
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{
|
tripleSubFiber := New(Config{
|
||||||
ErrorHandler: tsf,
|
ErrorHandler: tsf,
|
||||||
|
@ -394,7 +394,7 @@ func Test_App_UseMountedErrorHandlerForBestPrefixMatch(t *testing.T) {
|
||||||
|
|
||||||
b, err = io.ReadAll(resp2.Body)
|
b, err = io.ReadAll(resp2.Body)
|
||||||
require.NoError(t, err, "iotuil.ReadAll()")
|
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
|
// go test -run Test_Mount_Route_Names
|
||||||
|
|
|
@ -358,7 +358,7 @@ func (app *App) register(methods []string, pathRaw string, group *Group, handler
|
||||||
Handlers: handlers,
|
Handlers: handlers,
|
||||||
}
|
}
|
||||||
// Increment global handler count
|
// 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
|
// Middleware route matches all HTTP methods
|
||||||
if isUse {
|
if isUse {
|
||||||
|
|
Loading…
Reference in New Issue