Merge branch 'main' into renanbastos93improve-error-handling-csrf-middle

pull/3021/head
Juan Calderon-Perez 2024-10-05 07:05:22 -04:00 committed by GitHub
commit f5933a6cfd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 305 additions and 86 deletions

View File

@ -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.3
version: v1.61.0

View File

@ -15,7 +15,7 @@ jobs:
uses: actions/checkout@v4
- name: Run markdownlint-cli2
uses: DavidAnson/markdownlint-cli2-action@v16
uses: DavidAnson/markdownlint-cli2-action@v17
with:
globs: |
**/*.md

View File

@ -35,7 +35,7 @@ markdown:
## lint: 🚨 Run lint checks
.PHONY: lint
lint:
go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.60.3 run ./...
go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0 run ./...
## test: 🚦 Execute all tests
.PHONY: test

View File

@ -1,13 +1,15 @@
package binder
import (
"errors"
"reflect"
"strings"
"sync"
"github.com/gofiber/fiber/v3/internal/schema"
"github.com/gofiber/utils/v2"
"github.com/valyala/bytebufferpool"
"github.com/gofiber/fiber/v3/internal/schema"
)
// ParserConfig form decoder config for SetParserDecoder
@ -132,15 +134,24 @@ func parseParamSquareBrackets(k string) (string, error) {
defer bytebufferpool.Put(bb)
kbytes := []byte(k)
openBracketsCount := 0
for i, b := range kbytes {
if b == '[' && kbytes[i+1] != ']' {
if err := bb.WriteByte('.'); err != nil {
return "", err //nolint:wrapcheck // unnecessary to wrap it
if b == '[' {
openBracketsCount++
if i+1 < len(kbytes) && kbytes[i+1] != ']' {
if err := bb.WriteByte('.'); err != nil {
return "", err //nolint:wrapcheck // unnecessary to wrap it
}
}
continue
}
if b == '[' || b == ']' {
if b == ']' {
openBracketsCount--
if openBracketsCount < 0 {
return "", errors.New("unmatched brackets")
}
continue
}
@ -149,6 +160,10 @@ func parseParamSquareBrackets(k string) (string, error) {
}
}
if openBracketsCount > 0 {
return "", errors.New("unmatched brackets")
}
return bb.String(), nil
}

View File

@ -1,6 +1,7 @@
package binder
import (
"errors"
"reflect"
"testing"
@ -29,3 +30,70 @@ func Test_EqualFieldType(t *testing.T) {
require.True(t, equalFieldType(&user, reflect.Int, "AGE"))
require.True(t, equalFieldType(&user, reflect.Int, "age"))
}
func Test_ParseParamSquareBrackets(t *testing.T) {
tests := []struct {
err error
input string
expected string
}{
{
err: nil,
input: "foo[bar]",
expected: "foo.bar",
},
{
err: nil,
input: "foo[bar][baz]",
expected: "foo.bar.baz",
},
{
err: errors.New("unmatched brackets"),
input: "foo[bar",
expected: "",
},
{
err: errors.New("unmatched brackets"),
input: "foo[bar][baz",
expected: "",
},
{
err: errors.New("unmatched brackets"),
input: "foo]bar[",
expected: "",
},
{
err: nil,
input: "foo[bar[baz]]",
expected: "foo.bar.baz",
},
{
err: nil,
input: "",
expected: "",
},
{
err: nil,
input: "[]",
expected: "",
},
{
err: nil,
input: "foo[]",
expected: "foo",
},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
result, err := parseParamSquareBrackets(tt.input)
if tt.err != nil {
require.Error(t, err)
require.EqualError(t, err, tt.err.Error())
} else {
require.NoError(t, err)
require.Equal(t, tt.expected, result)
}
})
}
}

16
ctx.go
View File

@ -624,7 +624,7 @@ func (c *DefaultCtx) Fresh() bool {
if err != nil {
return false
}
return lastModifiedTime.Before(modifiedSinceTime)
return lastModifiedTime.Compare(modifiedSinceTime) != 1
}
}
}
@ -1841,21 +1841,9 @@ func (c *DefaultCtx) IsProxyTrusted() bool {
return false
}
var localHosts = [...]string{"127.0.0.1", "::1"}
// IsLocalHost will return true if address is a localhost address.
func (*DefaultCtx) isLocalHost(address string) bool {
for _, h := range localHosts {
if address == h {
return true
}
}
return false
}
// IsFromLocal will return true if request came from local.
func (c *DefaultCtx) IsFromLocal() bool {
return c.isLocalHost(c.fasthttp.RemoteIP().String())
return c.fasthttp.RemoteIP().IsLoopback()
}
// Bind You can bind body, cookie, headers etc. into the map, map slice, struct easily by using Binding method.

View File

@ -318,8 +318,6 @@ type Ctx interface {
// If EnableTrustedProxyCheck false, it returns true
// IsProxyTrusted can check remote ip by proxy ranges and ip map.
IsProxyTrusted() bool
// IsLocalHost will return true if address is a localhost address.
isLocalHost(address string) bool
// IsFromLocal will return true if request came from local.
IsFromLocal() bool
// Bind You can bind body, cookie, headers etc. into the map, map slice, struct easily by using Binding method.

View File

@ -1397,6 +1397,10 @@ func Test_Ctx_Fresh(t *testing.T) {
require.False(t, c.Fresh())
c.Request().Header.Set(HeaderIfModifiedSince, "Wed, 21 Oct 2015 07:28:00 GMT")
require.True(t, c.Fresh())
c.Request().Header.Set(HeaderIfModifiedSince, "Wed, 21 Oct 2015 07:27:59 GMT")
c.Response().Header.Set(HeaderLastModified, "Wed, 21 Oct 2015 07:28:00 GMT")
require.False(t, c.Fresh())
}
@ -1412,6 +1416,18 @@ func Benchmark_Ctx_Fresh_WithNoCache(b *testing.B) {
}
}
// go test -v -run=^$ -bench=Benchmark_Ctx_Fresh_LastModified -benchmem -count=4
func Benchmark_Ctx_Fresh_LastModified(b *testing.B) {
app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{})
c.Response().Header.Set(HeaderLastModified, "Wed, 21 Oct 2015 07:28:00 GMT")
c.Request().Header.Set(HeaderIfModifiedSince, "Wed, 21 Oct 2015 07:28:00 GMT")
for n := 0; n < b.N; n++ {
c.Fresh()
}
}
// go test -run Test_Ctx_Binders -v
func Test_Ctx_Binders(t *testing.T) {
t.Parallel()
@ -6352,3 +6368,61 @@ func Benchmark_Ctx_IsProxyTrusted(b *testing.B) {
})
})
}
func Benchmark_Ctx_IsFromLocalhost(b *testing.B) {
// Scenario without localhost check
b.Run("Non_Localhost", func(b *testing.B) {
app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{})
c.Request().SetRequestURI("http://google.com:8080/test")
b.ReportAllocs()
b.ResetTimer()
for n := 0; n < b.N; n++ {
c.IsFromLocal()
}
app.ReleaseCtx(c)
})
// Scenario without localhost check in parallel
b.Run("Non_Localhost_Parallel", func(b *testing.B) {
app := New()
b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
c := app.AcquireCtx(&fasthttp.RequestCtx{})
c.Request().SetRequestURI("http://google.com:8080/test")
for pb.Next() {
c.IsFromLocal()
}
app.ReleaseCtx(c)
})
})
// Scenario with localhost check
b.Run("Localhost", func(b *testing.B) {
app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{})
c.Request().SetRequestURI("http://localhost:8080/test")
b.ReportAllocs()
b.ResetTimer()
for n := 0; n < b.N; n++ {
c.IsFromLocal()
}
app.ReleaseCtx(c)
})
// Scenario with localhost check in parallel
b.Run("Localhost_Parallel", func(b *testing.B) {
app := New()
b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
c := app.AcquireCtx(&fasthttp.RequestCtx{})
c.Request().SetRequestURI("http://localhost:8080/test")
for pb.Next() {
c.IsFromLocal()
}
app.ReleaseCtx(c)
})
})
}

View File

@ -788,7 +788,7 @@ Improper use of the X-Forwarded-For header can be a security risk. For details,
## Is
Returns the matching **content type**, if the incoming requests [Content-Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) HTTP header field matches the [MIME type](https://developer.mozilla.org/ru/docs/Web/HTTP/Basics_of_HTTP/MIME_types) specified by the type parameter.
Returns the matching **content type**, if the incoming requests [Content-Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) HTTP header field matches the [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) specified by the type parameter.
:::info
If the request has **no** body, it returns **false**.

View File

@ -2,7 +2,7 @@
id: hooks
title: 🎣 Hooks
description: >-
Hooks are used to manipulate request/response proccess of Fiber client.
Hooks are used to manipulate request/response process of Fiber client.
sidebar_position: 4
---
@ -77,7 +77,7 @@ There are also some builtin request hooks provide some functionalities for Fiber
- [parserRequestURL](https://github.com/gofiber/fiber/blob/main/client/hooks.go#L62): parserRequestURL customizes the URL according to the path params and query params. It's necessary for `PathParam` and `QueryParam` methods.
- [parserRequestHeader](https://github.com/gofiber/fiber/blob/main/client/hooks.go#L113): parserRequestHeader sets request headers, cookies, body type, referer, user agent according to client and request proeprties. It's necessary to make request header and cookiejar methods functional.
- [parserRequestHeader](https://github.com/gofiber/fiber/blob/main/client/hooks.go#L113): parserRequestHeader sets request headers, cookies, body type, referer, user agent according to client and request properties. It's necessary to make request header and cookiejar methods functional.
- [parserRequestBody](https://github.com/gofiber/fiber/blob/main/client/hooks.go#L178): parserRequestBody serializes the body automatically. It is useful for XML, JSON, form, file bodies.

View File

@ -44,7 +44,7 @@ app.Use(logger.New(logger.Config{
app.Use(requestid.New())
app.Use(logger.New(logger.Config{
// For more options, see the Config section
Format: "${pid} ${locals:requestid} ${status} - ${method} ${path}\n",
Format: "${pid} ${locals:requestid} ${status} - ${method} ${path}\n",
}))
// Changing TimeZone & TimeFormat

View File

@ -19,7 +19,7 @@ Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/recover"
recoverer "github.com/gofiber/fiber/v3/middleware/recover"
)
```
@ -27,7 +27,7 @@ After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use(recover.New())
app.Use(recoverer.New())
// This panic will be caught by the middleware
app.Get("/", func(c fiber.Ctx) error {

12
go.mod
View File

@ -8,20 +8,20 @@ require (
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.20
github.com/stretchr/testify v1.9.0
github.com/tinylib/msgp v1.1.8
github.com/tinylib/msgp v1.2.1
github.com/valyala/bytebufferpool v1.0.0
github.com/valyala/fasthttp v1.55.0
github.com/valyala/fasthttp v1.56.0
)
require (
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/philhofer/fwd v1.1.2 // indirect
github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

54
go.sum
View File

@ -13,58 +13,28 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
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/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4=
github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
github.com/tinylib/msgp v1.2.1 h1:6ypy2qcCznxpP4hpORzhtXyTqrBs7cfM9MCCWY8zsmU=
github.com/tinylib/msgp v1.2.1/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8=
github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
github.com/valyala/fasthttp v1.56.0 h1:bEZdJev/6LCBlpdORfrLu/WOZXXxvrUQSiyniuaoW8U=
github.com/valyala/fasthttp v1.56.0/go.mod h1:sReBt3XZVnudxuLOx4J/fMrJVorWRiWY2koQKgABiVI=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@ -14,6 +14,11 @@ import (
"github.com/valyala/fasthttp/fasthttpadaptor"
)
type disableLogger struct{}
func (*disableLogger) Printf(string, ...any) {
}
var ctxPool = sync.Pool{
New: func() any {
return new(fasthttp.RequestCtx)
@ -96,6 +101,8 @@ func HTTPMiddleware(mw func(http.Handler) http.Handler) fiber.Handler {
c.Request().SetHost(r.Host)
c.Request().Header.SetHost(r.Host)
// Remove all cookies before setting, see https://github.com/valyala/fasthttp/pull/1864
c.Request().Header.DelAllCookies()
for key, val := range r.Header {
for _, v := range val {
c.Request().Header.Set(key, v)
@ -171,7 +178,7 @@ func handlerFunc(app *fiber.App, h ...fiber.Handler) http.HandlerFunc {
fctx.Response.Reset()
fctx.Request.Reset()
defer ctxPool.Put(fctx)
fctx.Init(req, remoteAddr, nil)
fctx.Init(req, remoteAddr, &disableLogger{})
if len(h) > 0 {
// New fiber Ctx

View File

@ -10,6 +10,7 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"github.com/gofiber/fiber/v3"
@ -86,7 +87,7 @@ func Test_HTTPHandler(t *testing.T) {
remoteAddr, err := net.ResolveTCPAddr("tcp", expectedRemoteAddr)
require.NoError(t, err)
fctx.Init(&req, remoteAddr, nil)
fctx.Init(&req, remoteAddr, &disableLogger{})
app := fiber.New()
ctx := app.AcquireCtx(&fctx)
defer app.ReleaseCtx(ctx)
@ -200,6 +201,81 @@ func Test_HTTPMiddleware(t *testing.T) {
require.Equal(t, "okay", resp.Header.Get("context_second_okay"))
}
func Test_HTTPMiddlewareWithCookies(t *testing.T) {
const (
cookieHeader = "Cookie"
setCookieHeader = "Set-Cookie"
cookieOneName = "cookieOne"
cookieTwoName = "cookieTwo"
cookieOneValue = "valueCookieOne"
cookieTwoValue = "valueCookieTwo"
)
nethttpMW := func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
next.ServeHTTP(w, r)
})
}
app := fiber.New()
app.Use(HTTPMiddleware(nethttpMW))
app.Post("/", func(c fiber.Ctx) error {
// RETURNING CURRENT COOKIES TO RESPONSE
var cookies []string = strings.Split(c.Get(cookieHeader), "; ")
for _, cookie := range cookies {
c.Set(setCookieHeader, cookie)
}
return c.SendStatus(fiber.StatusOK)
})
// Test case for POST request with cookies
t.Run("POST request with cookies", func(t *testing.T) {
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodPost, "/", nil)
require.NoError(t, err)
req.AddCookie(&http.Cookie{Name: cookieOneName, Value: cookieOneValue})
req.AddCookie(&http.Cookie{Name: cookieTwoName, Value: cookieTwoValue})
resp, err := app.Test(req)
require.NoError(t, err)
cookies := resp.Cookies()
require.Len(t, cookies, 2)
for _, cookie := range cookies {
switch cookie.Name {
case cookieOneName:
require.Equal(t, cookieOneValue, cookie.Value)
case cookieTwoName:
require.Equal(t, cookieTwoValue, cookie.Value)
default:
t.Error("unexpected cookie key")
}
}
})
// New test case for GET request
t.Run("GET request", func(t *testing.T) {
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/", nil)
require.NoError(t, err)
resp, err := app.Test(req)
require.NoError(t, err)
require.Equal(t, http.StatusMethodNotAllowed, resp.StatusCode)
})
// New test case for request without cookies
t.Run("POST request without cookies", func(t *testing.T) {
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodPost, "/", nil)
require.NoError(t, err)
resp, err := app.Test(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
require.Empty(t, resp.Cookies())
})
}
func Test_FiberHandler(t *testing.T) {
testFiberToHandlerFunc(t, false)
}
@ -412,6 +488,10 @@ func Benchmark_FiberHandlerFunc(b *testing.B) {
name string
bodyContent []byte
}{
{
name: "No Content",
bodyContent: nil, // No body content case
},
{
name: "100KB",
bodyContent: make([]byte, 100*1024),
@ -450,7 +530,14 @@ func Benchmark_FiberHandlerFunc(b *testing.B) {
for _, bm := range benchmarks {
b.Run(bm.name, func(b *testing.B) {
w := httptest.NewRecorder()
bodyBuffer := bytes.NewBuffer(bm.bodyContent)
var bodyBuffer *bytes.Buffer
// Handle the "No Content" case where bodyContent is nil
if bm.bodyContent != nil {
bodyBuffer = bytes.NewBuffer(bm.bodyContent)
} else {
bodyBuffer = bytes.NewBuffer([]byte{}) // Empty buffer for no content
}
r := http.Request{
Method: http.MethodPost,
@ -476,6 +563,10 @@ func Benchmark_FiberHandlerFunc_Parallel(b *testing.B) {
name string
bodyContent []byte
}{
{
name: "No Content",
bodyContent: nil, // No body content case
},
{
name: "100KB",
bodyContent: make([]byte, 100*1024),
@ -513,7 +604,15 @@ func Benchmark_FiberHandlerFunc_Parallel(b *testing.B) {
for _, bm := range benchmarks {
b.Run(bm.name, func(b *testing.B) {
bodyBuffer := bytes.NewBuffer(bm.bodyContent)
var bodyBuffer *bytes.Buffer
// Handle the "No Content" case where bodyContent is nil
if bm.bodyContent != nil {
bodyBuffer = bytes.NewBuffer(bm.bodyContent)
} else {
bodyBuffer = bytes.NewBuffer([]byte{}) // Empty buffer for no content
}
b.ReportAllocs()
b.ResetTimer()

View File

@ -63,7 +63,7 @@ func New(config ...Config) fiber.Handler {
var (
// Cache settings
mux = &sync.RWMutex{}
timestamp = uint64(time.Now().Unix())
timestamp = uint64(time.Now().Unix()) //nolint:gosec //Not a concern
)
// Create manager to simplify storage operations ( see manager.go )
manager := newManager(cfg.Storage)
@ -75,7 +75,7 @@ func New(config ...Config) fiber.Handler {
// Update timestamp in the configured interval
go func() {
for {
atomic.StoreUint64(&timestamp, uint64(time.Now().Unix()))
atomic.StoreUint64(&timestamp, uint64(time.Now().Unix())) //nolint:gosec //Not a concern
time.Sleep(timestampUpdatePeriod)
}
}()
@ -117,7 +117,7 @@ func New(config ...Config) fiber.Handler {
// Get timestamp
ts := atomic.LoadUint64(&timestamp)
// Cache Entry not found
// Cache Entry found
if e != nil {
// Invalidate cache if requested
if cfg.CacheInvalidator != nil && cfg.CacheInvalidator(c) {

View File

@ -65,7 +65,7 @@ func New(config ...Config) fiber.Handler {
return c.SendStatus(fiber.StatusRequestEntityTooLarge)
}
bb.B = appendUint(bb.Bytes(), uint32(bodyLength)) //nolint:gosec // Body length is validated above
bb.B = appendUint(bb.Bytes(), uint32(bodyLength))
bb.WriteByte('-')
bb.B = appendUint(bb.Bytes(), crc32.Checksum(body, crc32q))
bb.WriteByte('"')