Problem
The cache middleware handler uses a fragile stateful lock/unlock/relock pattern with goto statements. This makes the code difficult to reason about and easy to introduce bugs when adding new exit paths.
Affected Code
middleware/cache/cache.go:313-326:
mux.Lock() // line 313
locked := true
unlock := func() { if locked { mux.Unlock(); locked = false } }
relock := func() { if !locked { mux.Lock(); locked = true } }
The handler uses goto continueRequest (lines 370, 412, 536) that jumps over unlock calls. While the idempotent unlock() function mitigates missed unlocks, the pattern is fragile — any future code change that adds a new exit path could easily miss an unlock or create a deadlock.
Suggested Fix
Refactor into smaller functions with clear lock scope boundaries, or use a state machine struct:
type cacheHandler struct {
mux sync.Mutex
locked bool
}
func (h *cacheHandler) withLock(fn func()) {
h.mux.Lock()
defer h.mux.Unlock()
fn()
}
func (h *cacheHandler) withLockDo(fn func() error) error {
h.mux.Lock()
defer h.mux.Unlock()
return fn()
}
Fiber Version
v3 (latest main branch)
Problem
The cache middleware handler uses a fragile stateful lock/unlock/relock pattern with
gotostatements. This makes the code difficult to reason about and easy to introduce bugs when adding new exit paths.Affected Code
middleware/cache/cache.go:313-326:The handler uses
goto continueRequest(lines 370, 412, 536) that jumps over unlock calls. While the idempotentunlock()function mitigates missed unlocks, the pattern is fragile — any future code change that adds a new exit path could easily miss an unlock or create a deadlock.Suggested Fix
Refactor into smaller functions with clear lock scope boundaries, or use a state machine struct:
Fiber Version
v3 (latest main branch)