Skip to content

Commit eeffa22

Browse files
committed
Merge remote-tracking branch 'origin/main' into multipart-nested
# Conflicts: # binder/mapping.go
2 parents 8c28b9a + d0e767f commit eeffa22

File tree

14 files changed

+301
-111
lines changed

14 files changed

+301
-111
lines changed

.github/workflows/linter.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,4 @@ jobs:
3737
uses: golangci/golangci-lint-action@v6
3838
with:
3939
# NOTE: Keep this in sync with the version from .golangci.yml
40-
version: v1.62.0
40+
version: v1.62.2

.github/workflows/markdown.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
uses: actions/checkout@v4
1616

1717
- name: Run markdownlint-cli2
18-
uses: DavidAnson/markdownlint-cli2-action@v18
18+
uses: DavidAnson/markdownlint-cli2-action@v19
1919
with:
2020
globs: |
2121
**/*.md

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ markdown:
3535
## lint: 🚨 Run lint checks
3636
.PHONY: lint
3737
lint:
38-
go run github.com/golangci/golangci-lint/cmd/[email protected].0 run ./...
38+
go run github.com/golangci/golangci-lint/cmd/[email protected].2 run ./...
3939

4040
## test: 🚦 Execute all tests
4141
.PHONY: test

app.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,10 @@ func (app *App) handleTrustedProxy(ipAddress string) {
616616
// Note: It doesn't allow adding new methods, only customizing exist methods.
617617
func (app *App) NewCtxFunc(function func(app *App) CustomCtx) {
618618
app.newCtxFunc = function
619+
620+
if app.server != nil {
621+
app.server.Handler = app.customRequestHandler
622+
}
619623
}
620624

621625
// RegisterCustomConstraint allows to register custom constraint.
@@ -868,7 +872,11 @@ func (app *App) Config() Config {
868872
func (app *App) Handler() fasthttp.RequestHandler { //revive:disable-line:confusing-naming // Having both a Handler() (uppercase) and a handler() (lowercase) is fine. TODO: Use nolint:revive directive instead. See https://github.com/golangci/golangci-lint/issues/3476
869873
// prepare the server for the start
870874
app.startupProcess()
871-
return app.requestHandler
875+
876+
if app.newCtxFunc != nil {
877+
return app.customRequestHandler
878+
}
879+
return app.defaultRequestHandler
872880
}
873881

874882
// Stack returns the raw router stack.
@@ -1057,7 +1065,11 @@ func (app *App) init() *App {
10571065
}
10581066

10591067
// fasthttp server settings
1060-
app.server.Handler = app.requestHandler
1068+
if app.newCtxFunc != nil {
1069+
app.server.Handler = app.customRequestHandler
1070+
} else {
1071+
app.server.Handler = app.defaultRequestHandler
1072+
}
10611073
app.server.Name = app.config.ServerHeader
10621074
app.server.Concurrency = app.config.Concurrency
10631075
app.server.NoDefaultDate = app.config.DisableDefaultDate

app_test.go

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -581,32 +581,51 @@ func Test_App_Use_StrictRouting(t *testing.T) {
581581

582582
func Test_App_Add_Method_Test(t *testing.T) {
583583
t.Parallel()
584-
defer func() {
585-
if err := recover(); err != nil {
586-
require.Equal(t, "add: invalid http method JANE\n", fmt.Sprintf("%v", err))
587-
}
588-
}()
589584

590585
methods := append(DefaultMethods, "JOHN") //nolint:gocritic // We want a new slice here
591586
app := New(Config{
592587
RequestMethods: methods,
593588
})
594589

595-
app.Add([]string{"JOHN"}, "/doe", testEmptyHandler)
590+
app.Add([]string{"JOHN"}, "/john", testEmptyHandler)
596591

597-
resp, err := app.Test(httptest.NewRequest("JOHN", "/doe", nil))
592+
resp, err := app.Test(httptest.NewRequest("JOHN", "/john", nil))
598593
require.NoError(t, err, "app.Test(req)")
599594
require.Equal(t, StatusOK, resp.StatusCode, "Status code")
600595

601-
resp, err = app.Test(httptest.NewRequest(MethodGet, "/doe", nil))
596+
resp, err = app.Test(httptest.NewRequest(MethodGet, "/john", nil))
602597
require.NoError(t, err, "app.Test(req)")
603598
require.Equal(t, StatusMethodNotAllowed, resp.StatusCode, "Status code")
604599

605-
resp, err = app.Test(httptest.NewRequest("UNKNOWN", "/doe", nil))
600+
resp, err = app.Test(httptest.NewRequest("UNKNOWN", "/john", nil))
606601
require.NoError(t, err, "app.Test(req)")
607602
require.Equal(t, StatusNotImplemented, resp.StatusCode, "Status code")
608603

609-
app.Add([]string{"JANE"}, "/doe", testEmptyHandler)
604+
// Add a new method
605+
require.Panics(t, func() {
606+
app.Add([]string{"JANE"}, "/jane", testEmptyHandler)
607+
})
608+
}
609+
610+
func Test_App_All_Method_Test(t *testing.T) {
611+
t.Parallel()
612+
613+
methods := append(DefaultMethods, "JOHN") //nolint:gocritic // We want a new slice here
614+
app := New(Config{
615+
RequestMethods: methods,
616+
})
617+
618+
// Add a new method with All
619+
app.All("/doe", testEmptyHandler)
620+
621+
resp, err := app.Test(httptest.NewRequest("JOHN", "/doe", nil))
622+
require.NoError(t, err, "app.Test(req)")
623+
require.Equal(t, StatusOK, resp.StatusCode, "Status code")
624+
625+
// Add a new method
626+
require.Panics(t, func() {
627+
app.Add([]string{"JANE"}, "/jane", testEmptyHandler)
628+
})
610629
}
611630

612631
// go test -run Test_App_GETOnly

binder/mapping.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ func parseToMap(ptr any, data map[string][]string) error {
128128
newMap[k] = ""
129129
continue
130130
}
131-
132131
newMap[k] = v[len(v)-1]
133132
}
134133
default:

ctx_interface_gen.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ctx_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,35 @@ func Test_Ctx_CustomCtx(t *testing.T) {
127127
require.Equal(t, "prefix_v3", string(body))
128128
}
129129

130+
// go test -run Test_Ctx_CustomCtx
131+
func Test_Ctx_CustomCtx_and_Method(t *testing.T) {
132+
t.Parallel()
133+
134+
// Create app with custom request methods
135+
methods := append(DefaultMethods, "JOHN") //nolint:gocritic // We want a new slice here
136+
app := New(Config{
137+
RequestMethods: methods,
138+
})
139+
140+
// Create custom context
141+
app.NewCtxFunc(func(app *App) CustomCtx {
142+
return &customCtx{
143+
DefaultCtx: *NewDefaultCtx(app),
144+
}
145+
})
146+
147+
// Add route with custom method
148+
app.Add([]string{"JOHN"}, "/doe", testEmptyHandler)
149+
resp, err := app.Test(httptest.NewRequest("JOHN", "/doe", nil))
150+
require.NoError(t, err, "app.Test(req)")
151+
require.Equal(t, StatusOK, resp.StatusCode, "Status code")
152+
153+
// Add a new method
154+
require.Panics(t, func() {
155+
app.Add([]string{"JANE"}, "/jane", testEmptyHandler)
156+
})
157+
}
158+
130159
// go test -run Test_Ctx_Accepts_EmptyAccept
131160
func Test_Ctx_Accepts_EmptyAccept(t *testing.T) {
132161
t.Parallel()

docs/middleware/session.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
id: session
33
---
44

5-
# Session Middleware for [Fiber](https://github.com/gofiber/fiber)
5+
# Session
66

77
The `session` middleware provides session management for Fiber applications, utilizing the [Storage](https://github.com/gofiber/storage) package for multi-database support via a unified interface. By default, session data is stored in memory, but custom storage options are easily configurable (see examples below).
88

middleware/idempotency/locker.go

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,42 +10,58 @@ type Locker interface {
1010
Unlock(key string) error
1111
}
1212

13+
type countedLock struct {
14+
mu sync.Mutex
15+
locked int
16+
}
17+
1318
type MemoryLock struct {
14-
keys map[string]*sync.Mutex
19+
keys map[string]*countedLock
1520
mu sync.Mutex
1621
}
1722

1823
func (l *MemoryLock) Lock(key string) error {
1924
l.mu.Lock()
20-
mu, ok := l.keys[key]
25+
lock, ok := l.keys[key]
2126
if !ok {
22-
mu = new(sync.Mutex)
23-
l.keys[key] = mu
27+
lock = new(countedLock)
28+
l.keys[key] = lock
2429
}
30+
lock.locked++
2531
l.mu.Unlock()
2632

27-
mu.Lock()
33+
lock.mu.Lock()
2834

2935
return nil
3036
}
3137

3238
func (l *MemoryLock) Unlock(key string) error {
3339
l.mu.Lock()
34-
mu, ok := l.keys[key]
35-
l.mu.Unlock()
40+
lock, ok := l.keys[key]
3641
if !ok {
3742
// This happens if we try to unlock an unknown key
43+
l.mu.Unlock()
3844
return nil
3945
}
46+
l.mu.Unlock()
4047

41-
mu.Unlock()
48+
lock.mu.Unlock()
49+
50+
l.mu.Lock()
51+
lock.locked--
52+
if lock.locked <= 0 {
53+
// This happens if countedLock is used to Lock and Unlock the same number of times
54+
// So, we can delete the key to prevent memory leak
55+
delete(l.keys, key)
56+
}
57+
l.mu.Unlock()
4258

4359
return nil
4460
}
4561

4662
func NewMemoryLock() *MemoryLock {
4763
return &MemoryLock{
48-
keys: make(map[string]*sync.Mutex),
64+
keys: make(map[string]*countedLock),
4965
}
5066
}
5167

0 commit comments

Comments
 (0)