mirror of https://github.com/gofiber/fiber.git
Merge branch 'main' into renanbastos93improve-error-handling-csrf-middle
commit
f5933a6cfd
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
2
Makefile
2
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.3 run ./...
|
||||
go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0 run ./...
|
||||
|
||||
## test: 🚦 Execute all tests
|
||||
.PHONY: test
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
16
ctx.go
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
74
ctx_test.go
74
ctx_test.go
|
@ -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)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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 request’s [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 request’s [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**.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
12
go.mod
|
@ -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
54
go.sum
|
@ -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=
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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(×tamp, uint64(time.Now().Unix()))
|
||||
atomic.StoreUint64(×tamp, 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(×tamp)
|
||||
|
||||
// Cache Entry not found
|
||||
// Cache Entry found
|
||||
if e != nil {
|
||||
// Invalidate cache if requested
|
||||
if cfg.CacheInvalidator != nil && cfg.CacheInvalidator(c) {
|
||||
|
|
|
@ -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('"')
|
||||
|
|
Loading…
Reference in New Issue