mirror of https://github.com/gofiber/fiber.git
Merge branch 'main' into feature/3098-allow-removing-registered-route
commit
42744aed98
|
@ -37,4 +37,7 @@ jobs:
|
|||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
# NOTE: Keep this in sync with the version from .golangci.yml
|
||||
version: v1.62.2
|
||||
version: v1.64.7
|
||||
# NOTE(ldez): temporary workaround
|
||||
install-mode: goinstall
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ run:
|
|||
|
||||
output:
|
||||
sort-results: true
|
||||
uniq-by-line: false
|
||||
|
||||
linters-settings:
|
||||
depguard:
|
||||
|
@ -187,7 +186,7 @@ linters-settings:
|
|||
- name: unchecked-type-assertion
|
||||
disabled: true # TODO: Do not disable
|
||||
- name: unhandled-error
|
||||
arguments: ['bytes\.Buffer\.Write']
|
||||
disabled: true
|
||||
|
||||
stylecheck:
|
||||
checks:
|
||||
|
@ -250,7 +249,10 @@ issues:
|
|||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
exclude-dirs:
|
||||
- internal # TODO: Do not ignore interal packages
|
||||
- internal # TODO: Do not ignore internal packages
|
||||
exclude-files:
|
||||
- '_msgp\.go'
|
||||
- '_msgp_test\.go'
|
||||
exclude-rules:
|
||||
- linters:
|
||||
- err113
|
||||
|
@ -263,7 +265,10 @@ issues:
|
|||
linters:
|
||||
- bodyclose
|
||||
- err113
|
||||
# fix: true
|
||||
- source: 'fmt.Fprintf?'
|
||||
linters:
|
||||
- errcheck
|
||||
- revive
|
||||
|
||||
linters:
|
||||
enable:
|
||||
|
@ -358,7 +363,6 @@ linters:
|
|||
- stylecheck
|
||||
# - tagalign # TODO: Enable
|
||||
- tagliatelle
|
||||
- tenv
|
||||
- testableexamples
|
||||
- testifylint
|
||||
# - testpackage # TODO: Enable
|
||||
|
|
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.62.2 run ./...
|
||||
golangci-lint run
|
||||
|
||||
## test: 🚦 Execute all tests
|
||||
.PHONY: test
|
||||
|
|
2
app.go
2
app.go
|
@ -1024,7 +1024,7 @@ func (app *App) Test(req *http.Request, config ...TestConfig) (*http.Response, e
|
|||
select {
|
||||
case err = <-channel:
|
||||
case <-time.After(cfg.Timeout):
|
||||
conn.Close() //nolint:errcheck, revive // It is fine to ignore the error here
|
||||
conn.Close() //nolint:errcheck // It is fine to ignore the error here
|
||||
if cfg.FailOnTimeout {
|
||||
return nil, os.ErrDeadlineExceeded
|
||||
}
|
||||
|
|
|
@ -403,7 +403,7 @@ func Test_App_serverErrorHandler_Internal_Error(t *testing.T) {
|
|||
t.Parallel()
|
||||
app := New()
|
||||
msg := "test err"
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
app.serverErrorHandler(c.fasthttp, errors.New(msg))
|
||||
require.Equal(t, string(c.fasthttp.Response.Body()), msg)
|
||||
|
@ -413,7 +413,7 @@ func Test_App_serverErrorHandler_Internal_Error(t *testing.T) {
|
|||
func Test_App_serverErrorHandler_Network_Error(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
app.serverErrorHandler(c.fasthttp, &net.DNSError{
|
||||
Err: "test error",
|
||||
|
|
|
@ -1378,7 +1378,7 @@ func Benchmark_Bind_URI(b *testing.B) {
|
|||
var err error
|
||||
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.route = &Route{
|
||||
Params: []string{
|
||||
|
@ -1415,7 +1415,7 @@ func Benchmark_Bind_URI_Map(b *testing.B) {
|
|||
var err error
|
||||
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.route = &Route{
|
||||
Params: []string{
|
||||
|
|
|
@ -131,7 +131,7 @@ func testRequestFail(t *testing.T, handler fiber.Handler, wrapAgent func(agent *
|
|||
}
|
||||
}
|
||||
|
||||
func testClient(t *testing.T, handler fiber.Handler, wrapAgent func(agent *Client), excepted string, count ...int) { //nolint: unparam // maybe needed
|
||||
func testClient(t *testing.T, handler fiber.Handler, wrapAgent func(agent *Client), excepted string, count ...int) { //nolint:unparam // maybe needed
|
||||
t.Helper()
|
||||
|
||||
app, ln, start := createHelperServer(t)
|
||||
|
|
|
@ -199,7 +199,7 @@ func parserRequestBody(c *Client, req *Request) error {
|
|||
case filesBody:
|
||||
return parserRequestBodyFile(req)
|
||||
case rawBody:
|
||||
if body, ok := req.body.([]byte); ok {
|
||||
if body, ok := req.body.([]byte); ok { //nolint:revive // ignore simplicity
|
||||
req.RawRequest.SetBody(body)
|
||||
} else {
|
||||
return ErrBodyType
|
||||
|
|
|
@ -298,11 +298,12 @@ func (r *Request) Cookie(key string) string {
|
|||
// Use maps.Collect() to gather them into a map if needed.
|
||||
func (r *Request) Cookies() iter.Seq2[string, string] {
|
||||
return func(yield func(string, string) bool) {
|
||||
r.cookies.VisitAll(func(key, val string) {
|
||||
if !yield(key, val) {
|
||||
for k, v := range *r.cookies {
|
||||
res := yield(k, v)
|
||||
if !res {
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,11 +344,11 @@ func (r *Request) PathParam(key string) string {
|
|||
// Use maps.Collect() to gather them into a map if needed.
|
||||
func (r *Request) PathParams() iter.Seq2[string, string] {
|
||||
return func(yield func(string, string) bool) {
|
||||
r.path.VisitAll(func(key, val string) {
|
||||
if !yield(key, val) {
|
||||
for k, v := range *r.path {
|
||||
if !yield(k, v) {
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//nolint:goconst // Much easier to just ignore memory leaks in tests
|
||||
package client
|
||||
|
||||
import (
|
||||
|
@ -451,6 +452,14 @@ func Test_Request_Cookies(t *testing.T) {
|
|||
require.Equal(t, "bar", cookies["foo"])
|
||||
require.Equal(t, "foo", cookies["bar"])
|
||||
|
||||
require.NotPanics(t, func() {
|
||||
for _, v := range req.Cookies() {
|
||||
if v == "bar" {
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
require.Len(t, cookies, 2)
|
||||
}
|
||||
|
||||
|
@ -564,6 +573,14 @@ func Test_Request_PathParams(t *testing.T) {
|
|||
require.Equal(t, "foo", pathParams["bar"])
|
||||
|
||||
require.Len(t, pathParams, 2)
|
||||
|
||||
require.NotPanics(t, func() {
|
||||
for _, v := range req.PathParams() {
|
||||
if v == "bar" {
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Benchmark_Request_PathParams(b *testing.B) {
|
||||
|
@ -1579,7 +1596,7 @@ func Test_SetValWithStruct(t *testing.T) {
|
|||
|
||||
require.True(t, func() bool {
|
||||
for _, v := range p.PeekMulti("TSlice") {
|
||||
if string(v) == "bar" { //nolint:goconst // test
|
||||
if string(v) == "bar" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
76
ctx_test.go
76
ctx_test.go
|
@ -192,7 +192,7 @@ func Test_Ctx_AcceptsCharsets(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_AcceptsCharsets -benchmem -count=4
|
||||
func Benchmark_Ctx_AcceptsCharsets(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().Header.Set("Accept-Charset", "utf-8, iso-8859-1;q=0.5")
|
||||
var res string
|
||||
|
@ -218,7 +218,7 @@ func Test_Ctx_AcceptsEncodings(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_AcceptsEncodings -benchmem -count=4
|
||||
func Benchmark_Ctx_AcceptsEncodings(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().Header.Set(HeaderAcceptEncoding, "deflate, gzip;q=1.0, *;q=0.5")
|
||||
var res string
|
||||
|
@ -243,7 +243,7 @@ func Test_Ctx_AcceptsLanguages(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_AcceptsLanguages -benchmem -count=4
|
||||
func Benchmark_Ctx_AcceptsLanguages(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().Header.Set(HeaderAcceptLanguage, "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5")
|
||||
var res string
|
||||
|
@ -304,7 +304,7 @@ func Test_Ctx_Append(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_Append -benchmem -count=4
|
||||
func Benchmark_Ctx_Append(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -337,7 +337,7 @@ func Test_Ctx_Attachment(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_Attachment -benchmem -count=4
|
||||
func Benchmark_Ctx_Attachment(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -363,7 +363,7 @@ func Test_Ctx_BaseURL(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_BaseURL -benchmem
|
||||
func Benchmark_Ctx_BaseURL(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().SetHost("google.com:1337")
|
||||
c.Request().URI().SetPath("/haha/oke/lol")
|
||||
|
@ -380,7 +380,7 @@ func Benchmark_Ctx_BaseURL(b *testing.B) {
|
|||
func Test_Ctx_Body(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().SetBody([]byte("john=doe"))
|
||||
require.Equal(t, []byte("john=doe"), c.Body())
|
||||
|
@ -390,7 +390,7 @@ func Test_Ctx_Body(t *testing.T) {
|
|||
func Test_Ctx_BodyRaw(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().SetBodyRaw([]byte("john=doe"))
|
||||
require.Equal(t, []byte("john=doe"), c.BodyRaw())
|
||||
|
@ -400,7 +400,7 @@ func Test_Ctx_BodyRaw(t *testing.T) {
|
|||
func Test_Ctx_BodyRaw_Immutable(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New(Config{Immutable: true})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().SetBodyRaw([]byte("john=doe"))
|
||||
require.Equal(t, []byte("john=doe"), c.BodyRaw())
|
||||
|
@ -411,7 +411,7 @@ func Benchmark_Ctx_Body(b *testing.B) {
|
|||
const input = "john=doe"
|
||||
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().SetBody([]byte(input))
|
||||
b.ReportAllocs()
|
||||
|
@ -428,7 +428,7 @@ func Benchmark_Ctx_BodyRaw(b *testing.B) {
|
|||
const input = "john=doe"
|
||||
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().SetBodyRaw([]byte(input))
|
||||
b.ReportAllocs()
|
||||
|
@ -445,7 +445,7 @@ func Benchmark_Ctx_BodyRaw_Immutable(b *testing.B) {
|
|||
const input = "john=doe"
|
||||
|
||||
app := New(Config{Immutable: true})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().SetBodyRaw([]byte(input))
|
||||
b.ReportAllocs()
|
||||
|
@ -462,7 +462,7 @@ func Test_Ctx_Body_Immutable(t *testing.T) {
|
|||
t.Parallel()
|
||||
app := New()
|
||||
app.config.Immutable = true
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().SetBody([]byte("john=doe"))
|
||||
require.Equal(t, []byte("john=doe"), c.Body())
|
||||
|
@ -474,7 +474,7 @@ func Benchmark_Ctx_Body_Immutable(b *testing.B) {
|
|||
|
||||
app := New()
|
||||
app.config.Immutable = true
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().SetBody([]byte(input))
|
||||
b.ReportAllocs()
|
||||
|
@ -527,7 +527,7 @@ func Test_Ctx_Body_With_Compression(t *testing.T) {
|
|||
t.Run(tCase.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
c.Request().Header.Set("Content-Encoding", tCase.contentEncoding)
|
||||
|
||||
if strings.Contains(tCase.contentEncoding, "gzip") {
|
||||
|
@ -720,7 +720,7 @@ func Test_Ctx_Body_With_Compression_Immutable(t *testing.T) {
|
|||
t.Parallel()
|
||||
app := New()
|
||||
app.config.Immutable = true
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
c.Request().Header.Set("Content-Encoding", tCase.contentEncoding)
|
||||
|
||||
if strings.Contains(tCase.contentEncoding, "gzip") {
|
||||
|
@ -897,7 +897,7 @@ func Test_Ctx_Context(t *testing.T) {
|
|||
t.Parallel()
|
||||
testKey := struct{}{}
|
||||
testValue := "Test Value"
|
||||
ctx := context.WithValue(context.Background(), testKey, testValue) //nolint: staticcheck // not needed for tests
|
||||
ctx := context.WithValue(context.Background(), testKey, testValue) //nolint:staticcheck // not needed for tests
|
||||
require.Equal(t, testValue, ctx.Value(testKey))
|
||||
})
|
||||
}
|
||||
|
@ -910,7 +910,7 @@ func Test_Ctx_SetContext(t *testing.T) {
|
|||
|
||||
testKey := struct{}{}
|
||||
testValue := "Test Value"
|
||||
ctx := context.WithValue(context.Background(), testKey, testValue) //nolint: staticcheck // not needed for tests
|
||||
ctx := context.WithValue(context.Background(), testKey, testValue) //nolint:staticcheck // not needed for tests
|
||||
c.SetContext(ctx)
|
||||
require.Equal(t, testValue, c.Context().Value(testKey))
|
||||
}
|
||||
|
@ -930,7 +930,7 @@ func Test_Ctx_Context_Multiple_Requests(t *testing.T) {
|
|||
}
|
||||
|
||||
input := utils.CopyString(Query(c, "input", "NO_VALUE"))
|
||||
ctx = context.WithValue(ctx, testKey, fmt.Sprintf("%s_%s", testValue, input)) //nolint: staticcheck // not needed for tests
|
||||
ctx = context.WithValue(ctx, testKey, fmt.Sprintf("%s_%s", testValue, input)) //nolint:staticcheck // not needed for tests
|
||||
c.SetContext(ctx)
|
||||
|
||||
return c.Status(StatusOK).SendString(fmt.Sprintf("resp_%s_returned", input))
|
||||
|
@ -1013,7 +1013,7 @@ func Test_Ctx_Cookie(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_Cookie -benchmem -count=4
|
||||
func Benchmark_Ctx_Cookie(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -1544,12 +1544,12 @@ func Test_Ctx_Binders(t *testing.T) {
|
|||
t.Run("URI", func(t *testing.T) {
|
||||
t.Skip("URI is not ready for v3")
|
||||
//nolint:gocritic // TODO: uncomment
|
||||
//t.Parallel()
|
||||
//withValues(t, func(c Ctx, testStruct *TestStruct) error {
|
||||
// t.Parallel()
|
||||
// withValues(t, func(c Ctx, testStruct *TestStruct) error {
|
||||
// c.Route().Params = []string{"name", "name2", "class", "class2"}
|
||||
// c.Params().value = [30]string{"foo", "bar", "111", "222"}
|
||||
// return c.Bind().URI(testStruct)
|
||||
//})
|
||||
// })
|
||||
})
|
||||
t.Run("ReqHeader", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
@ -2566,7 +2566,7 @@ func Test_Ctx_Params_Case_Sensitive(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_Params -benchmem -count=4
|
||||
func Benchmark_Ctx_Params(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.route = &Route{
|
||||
Params: []string{
|
||||
|
@ -3746,7 +3746,7 @@ func Benchmark_Ctx_CBOR(b *testing.B) {
|
|||
func Benchmark_Ctx_JSON_Ctype(b *testing.B) {
|
||||
app := New()
|
||||
// TODO: Check extra allocs because of the interface stuff
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
type SomeStruct struct {
|
||||
Name string
|
||||
Age uint8
|
||||
|
@ -3813,7 +3813,7 @@ func Test_Ctx_JSONP(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_JSONP -benchmem -count=4
|
||||
func Benchmark_Ctx_JSONP(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
type SomeStruct struct {
|
||||
Name string
|
||||
|
@ -3838,7 +3838,7 @@ func Benchmark_Ctx_JSONP(b *testing.B) {
|
|||
func Test_Ctx_XML(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
require.Error(t, c.JSON(complex(1, 1)))
|
||||
|
||||
|
@ -3897,7 +3897,7 @@ func Test_Ctx_XML(t *testing.T) {
|
|||
// go test -run=^$ -bench=Benchmark_Ctx_XML -benchmem -count=4
|
||||
func Benchmark_Ctx_XML(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
type SomeStruct struct {
|
||||
Name string `xml:"Name"`
|
||||
Age uint8 `xml:"Age"`
|
||||
|
@ -3936,7 +3936,7 @@ func Test_Ctx_Links(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_Links -benchmem -count=4
|
||||
func Benchmark_Ctx_Links(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -4363,7 +4363,7 @@ func Benchmark_Ctx_Render_Engine(b *testing.B) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_Get_Location_From_Route -benchmem -count=4
|
||||
func Benchmark_Ctx_Get_Location_From_Route(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
app.Get("/user/:name", func(c Ctx) error {
|
||||
return c.SendString(c.Params("name"))
|
||||
|
@ -4578,14 +4578,14 @@ func Test_Ctx_SendStreamWriter(t *testing.T) {
|
|||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
|
||||
err := c.SendStreamWriter(func(w *bufio.Writer) {
|
||||
w.WriteString("Don't crash please") //nolint:errcheck, revive // It is fine to ignore the error
|
||||
w.WriteString("Don't crash please") //nolint:errcheck // It is fine to ignore the error
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "Don't crash please", string(c.Response().Body()))
|
||||
|
||||
err = c.SendStreamWriter(func(w *bufio.Writer) {
|
||||
for lineNum := 1; lineNum <= 5; lineNum++ {
|
||||
fmt.Fprintf(w, "Line %d\n", lineNum) //nolint:errcheck, revive // It is fine to ignore the error
|
||||
fmt.Fprintf(w, "Line %d\n", lineNum)
|
||||
if err := w.Flush(); err != nil {
|
||||
t.Errorf("unexpected error: %s", err)
|
||||
return
|
||||
|
@ -4607,7 +4607,7 @@ func Test_Ctx_SendStreamWriter_Interrupted(t *testing.T) {
|
|||
app.Get("/", func(c Ctx) error {
|
||||
return c.SendStreamWriter(func(w *bufio.Writer) {
|
||||
for lineNum := 1; lineNum <= 5; lineNum++ {
|
||||
fmt.Fprintf(w, "Line %d\n", lineNum) //nolint:errcheck // It is fine to ignore the error
|
||||
fmt.Fprintf(w, "Line %d\n", lineNum)
|
||||
|
||||
if err := w.Flush(); err != nil {
|
||||
if lineNum < 3 {
|
||||
|
@ -4728,7 +4728,7 @@ func Benchmark_Ctx_Type(b *testing.B) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_Type_Charset -benchmem -count=4
|
||||
func Benchmark_Ctx_Type_Charset(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -4753,7 +4753,7 @@ func Test_Ctx_Vary(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_Vary -benchmem -count=4
|
||||
func Benchmark_Ctx_Vary(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -4806,7 +4806,7 @@ func Test_Ctx_Writef(t *testing.T) {
|
|||
// go test -v -run=^$ -bench=Benchmark_Ctx_Writef -benchmem -count=4
|
||||
func Benchmark_Ctx_Writef(b *testing.B) {
|
||||
app := New()
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
world := "World!"
|
||||
b.ReportAllocs()
|
||||
|
@ -4951,11 +4951,11 @@ func Test_Ctx_BodyStreamWriter(t *testing.T) {
|
|||
ctx := &fasthttp.RequestCtx{}
|
||||
|
||||
ctx.SetBodyStreamWriter(func(w *bufio.Writer) {
|
||||
fmt.Fprintf(w, "body writer line 1\n") //nolint: errcheck // It is fine to ignore the error
|
||||
fmt.Fprintf(w, "body writer line 1\n")
|
||||
if err := w.Flush(); err != nil {
|
||||
t.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
fmt.Fprintf(w, "body writer line 2\n") //nolint: errcheck // It is fine to ignore the error
|
||||
fmt.Fprintf(w, "body writer line 2\n")
|
||||
})
|
||||
|
||||
require.True(t, ctx.IsBodyStream())
|
||||
|
|
|
@ -54,7 +54,7 @@ curl -I http://localhost:3000
|
|||
| ContentSecurityPolicy | `string` | ContentSecurityPolicy | "" |
|
||||
| CSPReportOnly | `bool` | CSPReportOnly | false |
|
||||
| HSTSPreloadEnabled | `bool` | HSTSPreloadEnabled | false |
|
||||
| ReferrerPolicy | `string` | ReferrerPolicy | "ReferrerPolicy" |
|
||||
| ReferrerPolicy | `string` | ReferrerPolicy | "no-referrer" |
|
||||
| PermissionPolicy | `string` | Permissions-Policy | "" |
|
||||
| CrossOriginEmbedderPolicy | `string` | Cross-Origin-Embedder-Policy | "require-corp" |
|
||||
| CrossOriginOpenerPolicy | `string` | Cross-Origin-Opener-Policy | "same-origin" |
|
||||
|
|
|
@ -79,7 +79,7 @@ app.Use(logger.New(logger.Config{
|
|||
TimeZone: "Asia/Shanghai",
|
||||
Done: func(c fiber.Ctx, logString []byte) {
|
||||
if c.Response().StatusCode() != fiber.StatusOK {
|
||||
reporter.SendToSlack(logString)
|
||||
reporter.SendToSlack(logString)
|
||||
}
|
||||
},
|
||||
}))
|
||||
|
@ -88,6 +88,23 @@ app.Use(logger.New(logger.Config{
|
|||
app.Use(logger.New(logger.Config{
|
||||
DisableColors: true,
|
||||
}))
|
||||
|
||||
// Use predefined formats
|
||||
app.Use(logger.New(logger.Config{
|
||||
Format: logger.FormatCommon,
|
||||
}))
|
||||
|
||||
app.Use(logger.New(logger.Config{
|
||||
Format: logger.FormatCombined,
|
||||
}))
|
||||
|
||||
app.Use(logger.New(logger.Config{
|
||||
Format: logger.FormatJSON,
|
||||
}))
|
||||
|
||||
app.Use(logger.New(logger.Config{
|
||||
Format: logger.FormatECS,
|
||||
}))
|
||||
```
|
||||
|
||||
### Use Logger Middleware with Other Loggers
|
||||
|
@ -136,37 +153,50 @@ Writing to os.File is goroutine-safe, but if you are using a custom Stream that
|
|||
|
||||
### Config
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
|:-----------------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------|
|
||||
| Next | `func(fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
|
||||
| Skip | `func(fiber.Ctx) bool` | Skip is a function to determine if logging is skipped or written to Stream. | `nil` |
|
||||
| Done | `func(fiber.Ctx, []byte)` | Done is a function that is called after the log string for a request is written to Stream, and pass the log string as parameter. | `nil` |
|
||||
| CustomTags | `map[string]LogFunc` | tagFunctions defines the custom tag action. | `map[string]LogFunc` |
|
||||
| Format | `string` | Format defines the logging tags. | `[${time}] ${ip} ${status} - ${latency} ${method} ${path} ${error}\n` |
|
||||
| TimeFormat | `string` | TimeFormat defines the time format for log timestamps. | `15:04:05` |
|
||||
| TimeZone | `string` | TimeZone can be specified, such as "UTC" and "America/New_York" and "Asia/Chongqing", etc | `"Local"` |
|
||||
| TimeInterval | `time.Duration` | TimeInterval is the delay before the timestamp is updated. | `500 * time.Millisecond` |
|
||||
| Stream | `io.Writer` | Stream is a writer where logs are written. | `os.Stdout` |
|
||||
| LoggerFunc | `func(c fiber.Ctx, data *Data, cfg Config) error` | Custom logger function for integration with logging libraries (Zerolog, Zap, Logrus, etc). Defaults to Fiber's default logger if not defined. | `see default_logger.go defaultLoggerInstance` |
|
||||
| DisableColors | `bool` | DisableColors defines if the logs output should be colorized. | `false` |
|
||||
| Property | Type | Description | Default |
|
||||
| :------------ | :------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------- |
|
||||
| Next | `func(fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
|
||||
| Skip | `func(fiber.Ctx) bool` | Skip is a function to determine if logging is skipped or written to Stream. | `nil` |
|
||||
| Done | `func(fiber.Ctx, []byte)` | Done is a function that is called after the log string for a request is written to Stream, and pass the log string as parameter. | `nil` |
|
||||
| CustomTags | `map[string]LogFunc` | tagFunctions defines the custom tag action. | `map[string]LogFunc` |
|
||||
| `Format` | `string` | Defines the logging tags. See more in [Predefined Formats](#predefined-formats), or create your own using [Tags](#constants). | `[${time}] ${ip} ${status} - ${latency} ${method} ${path} ${error}\n` (same as `DefaultFormat`) |
|
||||
| TimeFormat | `string` | TimeFormat defines the time format for log timestamps. | `15:04:05` |
|
||||
| TimeZone | `string` | TimeZone can be specified, such as "UTC" and "America/New_York" and "Asia/Chongqing", etc | `"Local"` |
|
||||
| TimeInterval | `time.Duration` | TimeInterval is the delay before the timestamp is updated. | `500 * time.Millisecond` |
|
||||
| Stream | `io.Writer` | Stream is a writer where logs are written. | `os.Stdout` |
|
||||
| LoggerFunc | `func(c fiber.Ctx, data *Data, cfg Config) error` | Custom logger function for integration with logging libraries (Zerolog, Zap, Logrus, etc). Defaults to Fiber's default logger if not defined. | `see default_logger.go defaultLoggerInstance` |
|
||||
| DisableColors | `bool` | DisableColors defines if the logs output should be colorized. | `false` |
|
||||
|
||||
## Default Config
|
||||
|
||||
```go
|
||||
var ConfigDefault = Config{
|
||||
Next: nil,
|
||||
Skip nil,
|
||||
Done: nil,
|
||||
Format: "[${time}] ${ip} ${status} - ${latency} ${method} ${path} ${error}\n",
|
||||
TimeFormat: "15:04:05",
|
||||
TimeZone: "Local",
|
||||
TimeInterval: 500 * time.Millisecond,
|
||||
Stream: os.Stdout,
|
||||
DisableColors: false,
|
||||
LoggerFunc: defaultLoggerInstance,
|
||||
Next: nil,
|
||||
Skip: nil,
|
||||
Done: nil,
|
||||
Format: DefaultFormat,
|
||||
TimeFormat: "15:04:05",
|
||||
TimeZone: "Local",
|
||||
TimeInterval: 500 * time.Millisecond,
|
||||
Stream: os.Stdout,
|
||||
BeforeHandlerFunc: beforeHandlerFunc,
|
||||
LoggerFunc: defaultLoggerInstance,
|
||||
enableColors: true,
|
||||
}
|
||||
```
|
||||
|
||||
## Predefined Formats
|
||||
|
||||
Logger provides predefined formats that you can use by name or directly by specifying the format string.
|
||||
|
||||
| **Format Constant** | **Format String** | **Description** |
|
||||
|---------------------|--------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------|
|
||||
| `DefaultFormat` | `"[${time}] ${ip} ${status} - ${latency} ${method} ${path} ${error}\n"` | Fiber's default logger format. |
|
||||
| `CommonFormat` | `"${ip} - - [${time}] "${method} ${url} ${protocol}" ${status} ${bytesSent}\n"` | Common Log Format (CLF) used in web server logs. |
|
||||
| `CombinedFormat` | `"${ip} - - [${time}] "${method} ${url} ${protocol}" ${status} ${bytesSent} "${referer}" "${ua}"\n"` | CLF format plus the `referer` and `user agent` fields. |
|
||||
| `JSONFormat` | `"{time: ${time}, ip: ${ip}, method: ${method}, url: ${url}, status: ${status}, bytesSent: ${bytesSent}}\n"` | JSON format for structured logging. |
|
||||
| `ECSFormat` | `"{\"@timestamp\":\"${time}\",\"ecs\":{\"version\":\"1.6.0\"},\"client\":{\"ip\":\"${ip}\"},\"http\":{\"request\":{\"method\":\"${method}\",\"url\":\"${url}\",\"protocol\":\"${protocol}\"},\"response\":{\"status_code\":${status},\"body\":{\"bytes\":${bytesSent}}}},\"log\":{\"level\":\"INFO\",\"logger\":\"fiber\"},\"message\":\"${method} ${url} responded with ${status}\"}\n"` | Elastic Common Schema (ECS) format for structured logging. |
|
||||
|
||||
## Constants
|
||||
|
||||
```go
|
||||
|
|
|
@ -937,6 +937,22 @@ app.Use(logger.New(logger.Config{
|
|||
|
||||
</details>
|
||||
|
||||
#### Predefined Formats
|
||||
|
||||
Logger provides predefined formats that you can use by name or directly by specifying the format string.
|
||||
<details>
|
||||
|
||||
<summary>Example Usage</summary>
|
||||
|
||||
```go
|
||||
app.Use(logger.New(logger.Config{
|
||||
Format: logger.FormatCombined,
|
||||
}))
|
||||
```
|
||||
|
||||
See more in [Logger](./middleware/logger.md#predefined-formats)
|
||||
</details>
|
||||
|
||||
### Filesystem
|
||||
|
||||
We've decided to remove filesystem middleware to clear up the confusion between static and filesystem middleware.
|
||||
|
|
2
go.mod
2
go.mod
|
@ -23,7 +23,7 @@ require (
|
|||
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/net v0.37.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
|
2
go.sum
2
go.sum
|
@ -36,6 +36,8 @@ golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
|||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
|
|
|
@ -51,16 +51,16 @@ func getTLSConfig(ln net.Listener) *tls.Config {
|
|||
}
|
||||
|
||||
// Copy value from pointer
|
||||
if val := reflect.Indirect(pointer); val.Type() != nil {
|
||||
if val := reflect.Indirect(pointer); val.IsValid() {
|
||||
// Get private field from value
|
||||
if field := val.FieldByName("config"); field.Type() != nil {
|
||||
if field := val.FieldByName("config"); field.IsValid() {
|
||||
// Copy value from pointer field (unsafe)
|
||||
newval := reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())) //nolint:gosec // Probably the only way to extract the *tls.Config from a net.Listener. TODO: Verify there really is no easier way without using unsafe.
|
||||
if newval.Type() == nil {
|
||||
if !newval.IsValid() {
|
||||
return nil
|
||||
}
|
||||
// Get element from pointer
|
||||
if elem := newval.Elem(); elem.Type() != nil {
|
||||
if elem := newval.Elem(); elem.IsValid() {
|
||||
// Cast value to *tls.Config
|
||||
c, ok := elem.Interface().(*tls.Config)
|
||||
if !ok {
|
||||
|
|
|
@ -566,7 +566,7 @@ func Test_Utils_TestConn_Closed_Write(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Close early, write should fail
|
||||
conn.Close() //nolint:errcheck, revive // It is fine to ignore the error here
|
||||
conn.Close() //nolint:errcheck // It is fine to ignore the error here
|
||||
_, err = conn.Write([]byte("Response 2\n"))
|
||||
require.ErrorIs(t, err, errTestConnClosed)
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ func Benchmark_Memory_Set(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = testStore.Set("john", []byte("doe"), 0) //nolint: errcheck // error not needed for benchmark
|
||||
_ = testStore.Set("john", []byte("doe"), 0) //nolint:errcheck // error not needed for benchmark
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,7 +220,7 @@ func Benchmark_Memory_Set_Parallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_ = testStore.Set("john", []byte("doe"), 0) //nolint: errcheck // error not needed for benchmark
|
||||
_ = testStore.Set("john", []byte("doe"), 0) //nolint:errcheck // error not needed for benchmark
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ func Benchmark_Memory_Get(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = testStore.Get("john") //nolint: errcheck // error not needed for benchmark
|
||||
_, _ = testStore.Get("john") //nolint:errcheck // error not needed for benchmark
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,7 +273,7 @@ func Benchmark_Memory_Get_Parallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, _ = testStore.Get("john") //nolint: errcheck // error not needed for benchmark
|
||||
_, _ = testStore.Get("john") //nolint:errcheck // error not needed for benchmark
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -315,8 +315,8 @@ func Benchmark_Memory_SetAndDelete(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = testStore.Set("john", []byte("doe"), 0) //nolint: errcheck // error not needed for benchmark
|
||||
_ = testStore.Delete("john") //nolint: errcheck // error not needed for benchmark
|
||||
_ = testStore.Set("john", []byte("doe"), 0) //nolint:errcheck // error not needed for benchmark
|
||||
_ = testStore.Delete("john") //nolint:errcheck // error not needed for benchmark
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,8 +327,8 @@ func Benchmark_Memory_SetAndDelete_Parallel(b *testing.B) {
|
|||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_ = testStore.Set("john", []byte("doe"), 0) //nolint: errcheck // error not needed for benchmark
|
||||
_ = testStore.Delete("john") //nolint: errcheck // error not needed for benchmark
|
||||
_ = testStore.Set("john", []byte("doe"), 0) //nolint:errcheck // error not needed for benchmark
|
||||
_ = testStore.Delete("john") //nolint:errcheck // error not needed for benchmark
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
34
listen.go
34
listen.go
|
@ -328,7 +328,7 @@ func (*App) prepareListenData(addr string, isTLS bool, cfg ListenConfig) ListenD
|
|||
}
|
||||
|
||||
// startupMessage prepares the startup message with the handler number, port, address and other information
|
||||
func (app *App) startupMessage(addr string, isTLS bool, pids string, cfg ListenConfig) { //nolint: revive // Accepting a bool param named isTLS if fine here
|
||||
func (app *App) startupMessage(addr string, isTLS bool, pids string, cfg ListenConfig) { //nolint:revive // Accepting a bool param named isTLS if fine here
|
||||
// ignore child processes
|
||||
if IsChild() {
|
||||
return
|
||||
|
@ -366,38 +366,35 @@ func (app *App) startupMessage(addr string, isTLS bool, pids string, cfg ListenC
|
|||
out = colorable.NewNonColorable(os.Stdout)
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "%s\n", fmt.Sprintf(figletFiberText, colors.Red+"v"+Version+colors.Reset)) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out, strings.Repeat("-", 50)+"\n") //nolint:errcheck,revive,govet // ignore error
|
||||
fmt.Fprintf(out, "%s\n", fmt.Sprintf(figletFiberText, colors.Red+"v"+Version+colors.Reset))
|
||||
fmt.Fprintf(out, strings.Repeat("-", 50)+"\n")
|
||||
|
||||
if host == "0.0.0.0" {
|
||||
//nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out,
|
||||
"%sINFO%s Server started on: \t%s%s://127.0.0.1:%s%s (bound on host 0.0.0.0 and port %s)\n",
|
||||
colors.Green, colors.Reset, colors.Blue, scheme, port, colors.Reset, port)
|
||||
} else {
|
||||
//nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out,
|
||||
"%sINFO%s Server started on: \t%s%s%s\n",
|
||||
colors.Green, colors.Reset, colors.Blue, fmt.Sprintf("%s://%s:%s", scheme, host, port), colors.Reset)
|
||||
}
|
||||
|
||||
if app.config.AppName != "" {
|
||||
fmt.Fprintf(out, "%sINFO%s Application name: \t\t%s%s%s\n", colors.Green, colors.Reset, colors.Blue, app.config.AppName, colors.Reset) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out, "%sINFO%s Application name: \t\t%s%s%s\n", colors.Green, colors.Reset, colors.Blue, app.config.AppName, colors.Reset)
|
||||
}
|
||||
|
||||
//nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out,
|
||||
"%sINFO%s Total handlers count: \t%s%s%s\n",
|
||||
colors.Green, colors.Reset, colors.Blue, strconv.Itoa(int(app.handlersCount)), colors.Reset)
|
||||
|
||||
if isPrefork == "Enabled" {
|
||||
fmt.Fprintf(out, "%sINFO%s Prefork: \t\t\t%s%s%s\n", colors.Green, colors.Reset, colors.Blue, isPrefork, colors.Reset) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out, "%sINFO%s Prefork: \t\t\t%s%s%s\n", colors.Green, colors.Reset, colors.Blue, isPrefork, colors.Reset)
|
||||
} else {
|
||||
fmt.Fprintf(out, "%sINFO%s Prefork: \t\t\t%s%s%s\n", colors.Green, colors.Reset, colors.Red, isPrefork, colors.Reset) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out, "%sINFO%s Prefork: \t\t\t%s%s%s\n", colors.Green, colors.Reset, colors.Red, isPrefork, colors.Reset)
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "%sINFO%s PID: \t\t\t%s%v%s\n", colors.Green, colors.Reset, colors.Blue, os.Getpid(), colors.Reset) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out, "%sINFO%s Total process count: \t%s%s%s\n", colors.Green, colors.Reset, colors.Blue, procs, colors.Reset) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out, "%sINFO%s PID: \t\t\t%s%v%s\n", colors.Green, colors.Reset, colors.Blue, os.Getpid(), colors.Reset)
|
||||
fmt.Fprintf(out, "%sINFO%s Total process count: \t%s%s%s\n", colors.Green, colors.Reset, colors.Blue, procs, colors.Reset)
|
||||
|
||||
if cfg.EnablePrefork {
|
||||
// Turn the `pids` variable (in the form ",a,b,c,d,e,f,etc") into a slice of PIDs
|
||||
|
@ -408,7 +405,7 @@ func (app *App) startupMessage(addr string, isTLS bool, pids string, cfg ListenC
|
|||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "%sINFO%s Child PIDs: \t\t%s", colors.Green, colors.Reset, colors.Blue) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out, "%sINFO%s Child PIDs: \t\t%s", colors.Green, colors.Reset, colors.Blue)
|
||||
totalPids := len(pidSlice)
|
||||
rowTotalPidCount := 10
|
||||
|
||||
|
@ -421,17 +418,17 @@ func (app *App) startupMessage(addr string, isTLS bool, pids string, cfg ListenC
|
|||
}
|
||||
|
||||
for n, pid := range pidSlice[start:end] {
|
||||
fmt.Fprintf(out, "%s", pid) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out, "%s", pid)
|
||||
if n+1 != len(pidSlice[start:end]) {
|
||||
fmt.Fprintf(out, ", ") //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out, ", ")
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(out, "\n%s", colors.Reset) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out, "\n%s", colors.Reset)
|
||||
}
|
||||
}
|
||||
|
||||
// add new Line as spacer
|
||||
fmt.Fprintf(out, "\n%s", colors.Reset) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(out, "\n%s", colors.Reset)
|
||||
}
|
||||
|
||||
// printRoutesMessage print all routes with method, path, name and handlers
|
||||
|
@ -473,11 +470,10 @@ func (app *App) printRoutesMessage() {
|
|||
return routes[i].path < routes[j].path
|
||||
})
|
||||
|
||||
fmt.Fprintf(w, "%smethod\t%s| %spath\t%s| %sname\t%s| %shandlers\t%s\n", colors.Blue, colors.White, colors.Green, colors.White, colors.Cyan, colors.White, colors.Yellow, colors.Reset) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(w, "%s------\t%s| %s----\t%s| %s----\t%s| %s--------\t%s\n", colors.Blue, colors.White, colors.Green, colors.White, colors.Cyan, colors.White, colors.Yellow, colors.Reset) //nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(w, "%smethod\t%s| %spath\t%s| %sname\t%s| %shandlers\t%s\n", colors.Blue, colors.White, colors.Green, colors.White, colors.Cyan, colors.White, colors.Yellow, colors.Reset)
|
||||
fmt.Fprintf(w, "%s------\t%s| %s----\t%s| %s----\t%s| %s--------\t%s\n", colors.Blue, colors.White, colors.Green, colors.White, colors.Cyan, colors.White, colors.Yellow, colors.Reset)
|
||||
|
||||
for _, route := range routes {
|
||||
//nolint:errcheck,revive // ignore error
|
||||
fmt.Fprintf(w, "%s%s\t%s| %s%s\t%s| %s%s\t%s| %s%s%s\n", colors.Blue, route.method, colors.White, colors.Green, route.path, colors.White, colors.Cyan, route.name, colors.White, colors.Yellow, route.handlers, colors.Reset)
|
||||
}
|
||||
|
||||
|
|
|
@ -53,9 +53,9 @@ func (l *defaultLogger) privateLogf(lv Level, format string, fmtArgs []any) {
|
|||
buf.WriteString(level)
|
||||
|
||||
if len(fmtArgs) > 0 {
|
||||
_, _ = fmt.Fprintf(buf, format, fmtArgs...) //nolint: errcheck // It is fine to ignore the error
|
||||
_, _ = fmt.Fprintf(buf, format, fmtArgs...)
|
||||
} else {
|
||||
_, _ = fmt.Fprint(buf, fmtArgs...) //nolint: errcheck // It is fine to ignore the error
|
||||
_, _ = fmt.Fprint(buf, fmtArgs...)
|
||||
}
|
||||
|
||||
_ = l.stdlog.Output(l.depth, buf.String()) //nolint:errcheck // It is fine to ignore the error
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//nolint:contextcheck, revive // Much easier to just ignore memory leaks in tests
|
||||
//nolint:contextcheck,revive // Much easier to just ignore memory leaks in tests
|
||||
package adaptor
|
||||
|
||||
import (
|
||||
|
@ -68,7 +68,7 @@ func Test_HTTPHandler(t *testing.T) {
|
|||
w.Header().Set("Header1", "value1")
|
||||
w.Header().Set("Header2", "value2")
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
fmt.Fprintf(w, "request body is %q", body) //nolint:errcheck // not needed
|
||||
fmt.Fprintf(w, "request body is %q", body)
|
||||
}
|
||||
fiberH := HTTPHandlerFunc(http.HandlerFunc(nethttpH))
|
||||
fiberH = setFiberContextValueMiddleware(fiberH, expectedContextKey, expectedContextValue)
|
||||
|
|
|
@ -1331,56 +1331,65 @@ func Test_CSRF_Cookie_Injection_Exploit(t *testing.T) {
|
|||
}
|
||||
|
||||
// TODO: use this test case and make the unsafe header value bug from https://github.com/gofiber/fiber/issues/2045 reproducible and permanently fixed/tested by this testcase
|
||||
// func Test_CSRF_UnsafeHeaderValue(t *testing.T) {
|
||||
// t.Parallel()
|
||||
// app := fiber.New()
|
||||
func Test_CSRF_UnsafeHeaderValue(t *testing.T) {
|
||||
t.SkipNow()
|
||||
t.Parallel()
|
||||
app := fiber.New()
|
||||
|
||||
// app.Use(New())
|
||||
// app.Get("/", func(c fiber.Ctx) error {
|
||||
// return c.SendStatus(fiber.StatusOK)
|
||||
// })
|
||||
// app.Get("/test", func(c fiber.Ctx) error {
|
||||
// return c.SendStatus(fiber.StatusOK)
|
||||
// })
|
||||
// app.Post("/", func(c fiber.Ctx) error {
|
||||
// return c.SendStatus(fiber.StatusOK)
|
||||
// })
|
||||
app.Use(New())
|
||||
app.Get("/", func(c fiber.Ctx) error {
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
})
|
||||
app.Get("/test", func(c fiber.Ctx) error {
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
})
|
||||
app.Post("/", func(c fiber.Ctx) error {
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
})
|
||||
|
||||
// resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
|
||||
// require.NoError(t, err)
|
||||
// require.Equal(t, fiber.StatusOK, resp.StatusCode)
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusOK, resp.StatusCode)
|
||||
|
||||
// var token string
|
||||
// for _, c := range resp.Cookies() {
|
||||
// if c.Name != ConfigDefault.CookieName {
|
||||
// continue
|
||||
// }
|
||||
// token = c.Value
|
||||
// break
|
||||
// }
|
||||
var token string
|
||||
for _, c := range resp.Cookies() {
|
||||
if c.Name != ConfigDefault.CookieName {
|
||||
continue
|
||||
}
|
||||
token = c.Value
|
||||
break
|
||||
}
|
||||
|
||||
// fmt.Println("token", token)
|
||||
t.Log("token", token)
|
||||
|
||||
// getReq := httptest.NewRequest(fiber.MethodGet, "/", nil)
|
||||
// getReq.Header.Set(HeaderName, token)
|
||||
// resp, err = app.Test(getReq)
|
||||
getReq := httptest.NewRequest(fiber.MethodGet, "/", nil)
|
||||
getReq.Header.Set(HeaderName, token)
|
||||
resp, err = app.Test(getReq)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusOK, resp.StatusCode)
|
||||
|
||||
// getReq = httptest.NewRequest(fiber.MethodGet, "/test", nil)
|
||||
// getReq.Header.Set("X-Requested-With", "XMLHttpRequest")
|
||||
// getReq.Header.Set(fiber.HeaderCacheControl, "no")
|
||||
// getReq.Header.Set(HeaderName, token)
|
||||
getReq = httptest.NewRequest(fiber.MethodGet, "/test", nil)
|
||||
getReq.Header.Set("X-Requested-With", "XMLHttpRequest")
|
||||
getReq.Header.Set(fiber.HeaderCacheControl, "no")
|
||||
getReq.Header.Set(HeaderName, token)
|
||||
|
||||
// resp, err = app.Test(getReq)
|
||||
resp, err = app.Test(getReq)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusOK, resp.StatusCode)
|
||||
|
||||
// getReq.Header.Set(fiber.HeaderAccept, "*/*")
|
||||
// getReq.Header.Del(HeaderName)
|
||||
// resp, err = app.Test(getReq)
|
||||
getReq.Header.Set(fiber.HeaderAccept, "*/*")
|
||||
getReq.Header.Del(HeaderName)
|
||||
resp, err = app.Test(getReq)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusOK, resp.StatusCode)
|
||||
|
||||
// postReq := httptest.NewRequest(fiber.MethodPost, "/", nil)
|
||||
// postReq.Header.Set("X-Requested-With", "XMLHttpRequest")
|
||||
// postReq.Header.Set(HeaderName, token)
|
||||
// resp, err = app.Test(postReq)
|
||||
// }
|
||||
postReq := httptest.NewRequest(fiber.MethodPost, "/", nil)
|
||||
postReq.Header.Set("X-Requested-With", "XMLHttpRequest")
|
||||
postReq.Header.Set(HeaderName, token)
|
||||
resp, err = app.Test(postReq)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusOK, resp.StatusCode)
|
||||
}
|
||||
|
||||
// go test -v -run=^$ -bench=Benchmark_Middleware_CSRF_Check -benchmem -count=4
|
||||
func Benchmark_Middleware_CSRF_Check(b *testing.B) {
|
||||
|
|
|
@ -28,7 +28,7 @@ type Config struct {
|
|||
ContentSecurityPolicy string
|
||||
|
||||
// ReferrerPolicy
|
||||
// Optional. Default value "ReferrerPolicy".
|
||||
// Optional. Default value "no-referrer".
|
||||
ReferrerPolicy string
|
||||
|
||||
// Permissions-Policy
|
||||
|
|
|
@ -50,9 +50,23 @@ type Config struct {
|
|||
|
||||
timeZoneLocation *time.Location
|
||||
|
||||
// Format defines the logging tags
|
||||
// Format defines the logging format for the middleware.
|
||||
//
|
||||
// Optional. Default: [${time}] ${ip} ${status} - ${latency} ${method} ${path} ${error}
|
||||
// You can customize the log output by defining a format string with placeholders
|
||||
// such as: ${time}, ${ip}, ${status}, ${method}, ${path}, ${latency}, ${error}, etc.
|
||||
// The full list of available placeholders can be found in 'tags.go' or at
|
||||
// 'https://docs.gofiber.io/api/middleware/logger/#constants'.
|
||||
//
|
||||
// Fiber provides predefined logging formats that can be used directly:
|
||||
//
|
||||
// - DefaultFormat → Uses the default log format: "[${time}] ${ip} ${status} - ${latency} ${method} ${path} ${error}"
|
||||
// - CommonFormat → Uses the Apache Common Log Format (CLF): "${ip} - - [${time}] \"${method} ${url} ${protocol}\" ${status} ${bytesSent}\n"
|
||||
// - CombinedFormat → Uses the Apache Combined Log Format: "${ip} - - [${time}] \"${method} ${url} ${protocol}\" ${status} ${bytesSent} \"${referer}\" \"${ua}\"\n"
|
||||
// - JSONFormat → Uses the JSON log format: "{\"time\":\"${time}\",\"ip\":\"${ip}\",\"method\":\"${method}\",\"url\":\"${url}\",\"status\":${status},\"bytesSent\":${bytesSent}}\n"
|
||||
// - ECSFormat → Uses the Elastic Common Schema (ECS) log format: {\"@timestamp\":\"${time}\",\"ecs\":{\"version\":\"1.6.0\"},\"client\":{\"ip\":\"${ip}\"},\"http\":{\"request\":{\"method\":\"${method}\",\"url\":\"${url}\",\"protocol\":\"${protocol}\"},\"response\":{\"status_code\":${status},\"body\":{\"bytes\":${bytesSent}}}},\"log\":{\"level\":\"INFO\",\"logger\":\"fiber\"},\"message\":\"${method} ${url} responded with ${status}\"}"
|
||||
// If both `Format` and `CustomFormat` are provided, the `CustomFormat` will be used, and the `Format` field will be ignored.
|
||||
// If no format is specified, the default format is used:
|
||||
// "[${time}] ${ip} ${status} - ${latency} ${method} ${path} ${error}"
|
||||
Format string
|
||||
|
||||
// TimeFormat https://programming.guide/go/format-parse-string-time-date-example.html
|
||||
|
@ -105,7 +119,7 @@ var ConfigDefault = Config{
|
|||
Next: nil,
|
||||
Skip: nil,
|
||||
Done: nil,
|
||||
Format: defaultFormat,
|
||||
Format: DefaultFormat,
|
||||
TimeFormat: "15:04:05",
|
||||
TimeZone: "Local",
|
||||
TimeInterval: 500 * time.Millisecond,
|
||||
|
@ -115,9 +129,6 @@ var ConfigDefault = Config{
|
|||
enableColors: true,
|
||||
}
|
||||
|
||||
// default logging format for Fiber's default logger
|
||||
var defaultFormat = "[${time}] ${ip} ${status} - ${latency} ${method} ${path} ${error}\n"
|
||||
|
||||
// Helper function to set default values
|
||||
func configDefault(config ...Config) Config {
|
||||
// Return default config if nothing provided
|
||||
|
|
|
@ -28,7 +28,7 @@ func defaultLoggerInstance(c fiber.Ctx, data *Data, cfg Config) error {
|
|||
buf := bytebufferpool.Get()
|
||||
|
||||
// Default output when no custom Format or io.Writer is given
|
||||
if cfg.Format == defaultFormat {
|
||||
if cfg.Format == DefaultFormat {
|
||||
// Format error if exist
|
||||
formatErr := ""
|
||||
if cfg.enableColors {
|
||||
|
@ -166,7 +166,7 @@ func writeLog(w io.Writer, msg []byte) {
|
|||
// Write error to output
|
||||
if _, err := w.Write([]byte(err.Error())); err != nil {
|
||||
// There is something wrong with the given io.Writer
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) //nolint: errcheck // It is fine to ignore the error
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package logger
|
||||
|
||||
const (
|
||||
// Fiber's default logger
|
||||
DefaultFormat = "[${time}] ${ip} ${status} - ${latency} ${method} ${path} ${error}\n"
|
||||
// Apache Common Log Format (CLF)
|
||||
CommonFormat = "${ip} - - [${time}] \"${method} ${url} ${protocol}\" ${status} ${bytesSent}\n"
|
||||
// Apache Combined Log Format
|
||||
CombinedFormat = "${ip} - - [${time}] \"${method} ${url} ${protocol}\" ${status} ${bytesSent} \"${referer}\" \"${ua}\"\n"
|
||||
// JSON log formats
|
||||
JSONFormat = "{\"time\":\"${time}\",\"ip\":\"${ip}\",\"method\":\"${method}\",\"url\":\"${url}\",\"status\":${status},\"bytesSent\":${bytesSent}}\n"
|
||||
// Elastic Common Schema (ECS) Log Format
|
||||
ECSFormat = "{\"@timestamp\":\"${time}\",\"ecs\":{\"version\":\"1.6.0\"},\"client\":{\"ip\":\"${ip}\"},\"http\":{\"request\":{\"method\":\"${method}\",\"url\":\"${url}\",\"protocol\":\"${protocol}\"},\"response\":{\"status_code\":${status},\"body\":{\"bytes\":${bytesSent}}}},\"log\":{\"level\":\"INFO\",\"logger\":\"fiber\"},\"message\":\"${method} ${url} responded with ${status}\"}\n"
|
||||
)
|
|
@ -40,7 +40,6 @@ func New(config ...Config) fiber.Handler {
|
|||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Set PID once
|
||||
pid := strconv.Itoa(os.Getpid())
|
||||
|
||||
|
|
|
@ -467,6 +467,124 @@ func Test_Logger_All(t *testing.T) {
|
|||
require.Equal(t, expected, buf.String())
|
||||
}
|
||||
|
||||
func Test_Logger_CLF_Format(t *testing.T) {
|
||||
t.Parallel()
|
||||
buf := bytebufferpool.Get()
|
||||
defer bytebufferpool.Put(buf)
|
||||
|
||||
app := fiber.New()
|
||||
|
||||
app.Use(New(Config{
|
||||
Format: CommonFormat,
|
||||
Stream: buf,
|
||||
}))
|
||||
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/?foo=bar", nil))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusNotFound, resp.StatusCode)
|
||||
|
||||
expected := fmt.Sprintf("0.0.0.0 - - [%s] \"%s %s %s\" %d %d\n",
|
||||
time.Now().Format("15:04:05"),
|
||||
fiber.MethodGet, "/?foo=bar", "HTTP/1.1",
|
||||
fiber.StatusNotFound,
|
||||
0)
|
||||
logResponse := buf.String()
|
||||
require.Equal(t, expected, logResponse)
|
||||
}
|
||||
|
||||
func Test_Logger_Combined_CLF_Format(t *testing.T) {
|
||||
t.Parallel()
|
||||
buf := bytebufferpool.Get()
|
||||
defer bytebufferpool.Put(buf)
|
||||
|
||||
app := fiber.New()
|
||||
|
||||
app.Use(New(Config{
|
||||
Format: CombinedFormat,
|
||||
Stream: buf,
|
||||
}))
|
||||
const expectedUA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
|
||||
const expectedReferer = "http://example.com"
|
||||
req := httptest.NewRequest(fiber.MethodGet, "/?foo=bar", nil)
|
||||
req.Header.Set("Referer", expectedReferer)
|
||||
req.Header.Set("User-Agent", expectedUA)
|
||||
resp, err := app.Test(req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusNotFound, resp.StatusCode)
|
||||
|
||||
expected := fmt.Sprintf("0.0.0.0 - - [%s] %q %d %d %q %q\n",
|
||||
time.Now().Format("15:04:05"),
|
||||
fmt.Sprintf("%s %s %s", fiber.MethodGet, "/?foo=bar", "HTTP/1.1"),
|
||||
fiber.StatusNotFound,
|
||||
0,
|
||||
expectedReferer,
|
||||
expectedUA)
|
||||
logResponse := buf.String()
|
||||
require.Equal(t, expected, logResponse)
|
||||
}
|
||||
|
||||
func Test_Logger_Json_Format(t *testing.T) {
|
||||
t.Parallel()
|
||||
buf := bytebufferpool.Get()
|
||||
defer bytebufferpool.Put(buf)
|
||||
|
||||
app := fiber.New()
|
||||
|
||||
app.Use(New(Config{
|
||||
Format: JSONFormat,
|
||||
Stream: buf,
|
||||
}))
|
||||
|
||||
req := httptest.NewRequest(fiber.MethodGet, "/?foo=bar", nil)
|
||||
resp, err := app.Test(req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusNotFound, resp.StatusCode)
|
||||
|
||||
expected := fmt.Sprintf(
|
||||
"{\"time\":%q,\"ip\":%q,\"method\":%q,\"url\":%q,\"status\":%d,\"bytesSent\":%d}\n",
|
||||
time.Now().Format("15:04:05"),
|
||||
"0.0.0.0",
|
||||
fiber.MethodGet,
|
||||
"/?foo=bar",
|
||||
fiber.StatusNotFound,
|
||||
0,
|
||||
)
|
||||
logResponse := buf.String()
|
||||
require.Equal(t, expected, logResponse)
|
||||
}
|
||||
|
||||
func Test_Logger_ECS_Format(t *testing.T) {
|
||||
t.Parallel()
|
||||
buf := bytebufferpool.Get()
|
||||
defer bytebufferpool.Put(buf)
|
||||
|
||||
app := fiber.New()
|
||||
|
||||
app.Use(New(Config{
|
||||
Format: ECSFormat,
|
||||
Stream: buf,
|
||||
}))
|
||||
|
||||
req := httptest.NewRequest(fiber.MethodGet, "/?foo=bar", nil)
|
||||
resp, err := app.Test(req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusNotFound, resp.StatusCode)
|
||||
|
||||
expected := fmt.Sprintf(
|
||||
"{\"@timestamp\":%q,\"ecs\":{\"version\":\"1.6.0\"},\"client\":{\"ip\":%q},\"http\":{\"request\":{\"method\":%q,\"url\":%q,\"protocol\":%q},\"response\":{\"status_code\":%d,\"body\":{\"bytes\":%d}}},\"log\":{\"level\":\"INFO\",\"logger\":\"fiber\"},\"message\":%q}\n",
|
||||
time.Now().Format("15:04:05"),
|
||||
"0.0.0.0",
|
||||
fiber.MethodGet,
|
||||
"/?foo=bar",
|
||||
"HTTP/1.1",
|
||||
fiber.StatusNotFound,
|
||||
0,
|
||||
fmt.Sprintf("%s %s responded with %d", fiber.MethodGet, "/?foo=bar", fiber.StatusNotFound),
|
||||
)
|
||||
logResponse := buf.String()
|
||||
require.Equal(t, expected, logResponse)
|
||||
}
|
||||
|
||||
func getLatencyTimeUnits() []struct {
|
||||
unit string
|
||||
div time.Duration
|
||||
|
@ -865,7 +983,7 @@ func Test_Logger_ByteSent_Streaming(t *testing.T) {
|
|||
for {
|
||||
i++
|
||||
msg := fmt.Sprintf("%d - the time is %v", i, time.Now())
|
||||
fmt.Fprintf(w, "data: Message: %s\n\n", msg) //nolint:errcheck // ignore error
|
||||
fmt.Fprintf(w, "data: Message: %s\n\n", msg)
|
||||
err := w.Flush()
|
||||
if err != nil {
|
||||
break
|
||||
|
@ -1049,7 +1167,7 @@ func Benchmark_Logger(b *testing.B) {
|
|||
for {
|
||||
i++
|
||||
msg := fmt.Sprintf("%d - the time is %v", i, time.Now())
|
||||
fmt.Fprintf(w, "data: Message: %s\n\n", msg) //nolint:errcheck // ignore error
|
||||
fmt.Fprintf(w, "data: Message: %s\n\n", msg)
|
||||
err := w.Flush()
|
||||
if err != nil {
|
||||
break
|
||||
|
@ -1217,7 +1335,7 @@ func Benchmark_Logger_Parallel(b *testing.B) {
|
|||
for {
|
||||
i++
|
||||
msg := fmt.Sprintf("%d - the time is %v", i, time.Now())
|
||||
fmt.Fprintf(w, "data: Message: %s\n\n", msg) //nolint:errcheck // ignore error
|
||||
fmt.Fprintf(w, "data: Message: %s\n\n", msg)
|
||||
err := w.Flush()
|
||||
if err != nil {
|
||||
break
|
||||
|
|
|
@ -506,7 +506,10 @@ func Test_Proxy_Do_WithRealURL(t *testing.T) {
|
|||
return Do(c, "https://www.google.com")
|
||||
})
|
||||
|
||||
resp, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil))
|
||||
resp, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err1)
|
||||
require.Equal(t, fiber.StatusOK, resp.StatusCode)
|
||||
require.Equal(t, "/test", resp.Request.URL.String())
|
||||
|
@ -523,7 +526,10 @@ func Test_Proxy_Do_WithRedirect(t *testing.T) {
|
|||
return Do(c, "https://google.com")
|
||||
})
|
||||
|
||||
resp, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil))
|
||||
resp, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err1)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
@ -558,7 +564,10 @@ func Test_Proxy_DoRedirects_TooManyRedirects(t *testing.T) {
|
|||
return DoRedirects(c, "http://google.com", 0)
|
||||
})
|
||||
|
||||
resp, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil))
|
||||
resp, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err1)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
|
2
path.go
2
path.go
|
@ -487,7 +487,7 @@ func splitNonEscaped(s, sep string) []string {
|
|||
}
|
||||
|
||||
// getMatch parses the passed url and tries to match it against the route segments and determine the parameter positions
|
||||
func (parser *routeParser) getMatch(detectionPath, path string, params *[maxParams]string, partialCheck bool) bool { //nolint: revive // Accepting a bool param is fine here
|
||||
func (parser *routeParser) getMatch(detectionPath, path string, params *[maxParams]string, partialCheck bool) bool { //nolint:revive // Accepting a bool param is fine here
|
||||
var i, paramsIterator, partLen int
|
||||
for _, segment := range parser.segs {
|
||||
partLen = len(detectionPath)
|
||||
|
|
|
@ -178,7 +178,7 @@ func Test_Redirect_Back_WithFlashMessages(t *testing.T) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
err := c.Redirect().With("success", "1").With("message", "test").Back("/")
|
||||
require.NoError(t, err)
|
||||
|
@ -225,7 +225,7 @@ func Test_Redirect_Route_WithFlashMessages(t *testing.T) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
err := c.Redirect().With("success", "1").With("message", "test").Route("user")
|
||||
|
||||
|
@ -259,7 +259,7 @@ func Test_Redirect_Route_WithOldInput(t *testing.T) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().URI().SetQueryString("id=1&name=tom")
|
||||
err := c.Redirect().With("success", "1").With("message", "test").WithInput().Route("user")
|
||||
|
@ -294,7 +294,7 @@ func Test_Redirect_Route_WithOldInput(t *testing.T) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Request().Header.Set(HeaderContentType, MIMEApplicationForm)
|
||||
c.Request().SetBodyString("id=1&name=tom")
|
||||
|
@ -330,7 +330,7 @@ func Test_Redirect_Route_WithOldInput(t *testing.T) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
|
@ -376,7 +376,7 @@ func Test_Redirect_parseAndClearFlashMessages(t *testing.T) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
msgs := redirectionMsgs{
|
||||
{
|
||||
|
@ -464,7 +464,7 @@ func Benchmark_Redirect_Route(b *testing.B) {
|
|||
return c.JSON(c.Params("name"))
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -491,7 +491,7 @@ func Benchmark_Redirect_Route_WithQueries(b *testing.B) {
|
|||
return c.JSON(c.Params("name"))
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -523,7 +523,7 @@ func Benchmark_Redirect_Route_WithFlashMessages(b *testing.B) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -576,7 +576,7 @@ func Benchmark_Redirect_parseAndClearFlashMessages(b *testing.B) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
val, err := testredirectionMsgs.MarshalMsg(nil)
|
||||
require.NoError(b, err)
|
||||
|
@ -618,7 +618,7 @@ func Benchmark_Redirect_processFlashMessages(b *testing.B) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
c.Redirect().With("success", "1").With("message", "test")
|
||||
|
||||
|
@ -647,7 +647,7 @@ func Benchmark_Redirect_Messages(b *testing.B) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
val, err := testredirectionMsgs.MarshalMsg(nil)
|
||||
require.NoError(b, err)
|
||||
|
@ -684,7 +684,7 @@ func Benchmark_Redirect_OldInputs(b *testing.B) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
val, err := testredirectionMsgs.MarshalMsg(nil)
|
||||
require.NoError(b, err)
|
||||
|
@ -719,7 +719,7 @@ func Benchmark_Redirect_Message(b *testing.B) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
val, err := testredirectionMsgs.MarshalMsg(nil)
|
||||
require.NoError(b, err)
|
||||
|
@ -750,7 +750,7 @@ func Benchmark_Redirect_OldInput(b *testing.B) {
|
|||
return c.SendString("user")
|
||||
}).Name("user")
|
||||
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
val, err := testredirectionMsgs.MarshalMsg(nil)
|
||||
require.NoError(b, err)
|
||||
|
|
|
@ -108,7 +108,7 @@ func (r *Route) match(detectionPath, path string, params *[maxParams]string) boo
|
|||
return false
|
||||
}
|
||||
|
||||
func (app *App) nextCustom(c CustomCtx) (bool, error) { //nolint: unparam // bool param might be useful for testing
|
||||
func (app *App) nextCustom(c CustomCtx) (bool, error) { //nolint:unparam // bool param might be useful for testing
|
||||
// Get stack length
|
||||
tree, ok := app.treeStack[c.getMethodINT()][c.getTreePath()]
|
||||
if !ok {
|
||||
|
|
|
@ -1025,7 +1025,7 @@ func Benchmark_Router_Next(b *testing.B) {
|
|||
var res bool
|
||||
var err error
|
||||
|
||||
c := app.AcquireCtx(request).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
c := app.AcquireCtx(request).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
|
@ -1250,7 +1250,7 @@ func Benchmark_Router_Github_API(b *testing.B) {
|
|||
for n := 0; n < b.N; n++ {
|
||||
c.URI().SetPath(routesFixture.TestRoutes[i].Path)
|
||||
|
||||
ctx := app.AcquireCtx(c).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
|
||||
ctx := app.AcquireCtx(c).(*DefaultCtx) //nolint:errcheck,forcetypeassert // not needed
|
||||
|
||||
match, err = app.next(ctx)
|
||||
app.ReleaseCtx(ctx)
|
||||
|
|
Loading…
Reference in New Issue