Skip to content

Conversation

@gaby
Copy link
Member

@gaby gaby commented Sep 20, 2025

Summary

  • Improve handling of errors when using a storage driver

Replaces #3597
Fixes #3020

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 20, 2025

Walkthrough

This PR adds explicit error returns and propagation across cache, CSRF, and limiter middleware. Manager methods now return errors, callers handle them, and tests introduce failing storage stubs to assert HTTP error paths. Several msgp-generated methods switch to pointer receivers. Control flow adds early returns and consistent unlocking on failures.

Changes

Cohort / File(s) Summary
Cache: managers and middleware
middleware/cache/cache.go, middleware/cache/manager.go
Convert get/set/setRaw/del and deleteKey to return errors; propagate errors on cache miss vs. other failures; wrap errors for expired entries, body fetch, eviction; stricter type checks; helper for cache-body fetch error.
Cache: tests
middleware/cache/cache_test.go, middleware/cache/manager_test.go
Add failing storage stub with per-op error injection; new tests for get/set/delete error propagation; adjust assertions for new error-return semantics; import updates.
CSRF: middleware and storage manager
middleware/csrf/csrf.go, middleware/csrf/storage_manager.go
getRaw/setRaw/delRaw now return errors; create/extend/delete token paths handle and route errors to ErrorHandler; wrap storage errors; update all call sites.
CSRF: msgp receivers
middleware/csrf/storage_manager_msgp.go
Change several methods to pointer receivers; rely on named returns; no functional logic changes beyond receivers.
CSRF: tests
middleware/csrf/csrf_test.go
Add failing storage stub and tests for get/set/delete error paths; update expectations and imports.
Limiter: fixed and sliding windows
middleware/limiter/limiter_fixed.go, middleware/limiter/limiter_sliding.go, middleware/limiter/manager.go
Manager.get/set now return errors; add error propagation and early unlock/return; wrap persist failures; unify c.Next error handling.
Limiter: tests
middleware/limiter/limiter_test.go
Add failing storage stub; tests for Get/Set error propagation and messages.
Session: msgp receivers
middleware/session/data_msgp.go
Switch EncodeMsg/MarshalMsg/Msgsize to pointer receivers; no logic changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant MW as Middleware
  participant Mgr as Manager
  participant Store as Storage

  rect rgb(245,248,252)
  note over MW,Mgr: Read path with error-aware cache/CSRF/limiter managers
  Client->>MW: Request
  MW->>Mgr: get/getRaw(key)
  alt storage-backed
    Mgr->>Store: GetWithContext(key)
    Store-->>Mgr: raw or error
    alt error
      Mgr-->>MW: error
      MW-->>Client: Error via ErrorHandler
    else miss/ok
      Mgr-->>MW: item/raw
      MW->>MW: proceed
    end
  else memory-backed
    Mgr->>Mgr: type-assert/lookup
    alt type mismatch
      Mgr-->>MW: error
      MW-->>Client: Error via ErrorHandler
    else ok
      Mgr-->>MW: item/raw
    end
  end
  end

  rect rgb(237,251,245)
  note over MW,Mgr: Write path with error propagation
  MW->>Mgr: set/setRaw(key, val, exp)
  alt storage-backed
    Mgr->>Mgr: MarshalMsg
    alt marshal error
      Mgr-->>MW: error
      MW-->>Client: Error via ErrorHandler
    else ok
      Mgr->>Store: SetWithContext(key, bytes, exp)
      Store-->>Mgr: ok or error
      alt error
        Mgr-->>MW: error
        MW-->>Client: Error via ErrorHandler
      else ok
        Mgr-->>MW: success
        MW->>Client: Continue
      end
    end
  else memory-backed
    Mgr-->>MW: success
  end
  end
Loading
sequenceDiagram
  autonumber
  actor Client
  participant CSRF as CSRF MW
  participant SM as storageManager
  participant Store as Storage
  Client->>CSRF: Request with token
  CSRF->>SM: getRaw(tokenKey)
  SM->>Store: GetWithContext
  Store-->>SM: raw or error
  alt error
    CSRF-->>Client: Routed to ErrorHandler
  else ok
    alt SingleUseToken
      CSRF->>SM: delRaw(tokenKey)
      SM->>Store: DeleteWithContext
      Store-->>SM: ok or error
      alt error
        CSRF-->>Client: Routed to ErrorHandler
      else ok
        CSRF-->>Client: Next
      end
    else reuse
      CSRF->>SM: setRaw(tokenKey,new,exp)
      SM->>Store: SetWithContext
      Store-->>SM: ok or error
      alt error
        CSRF-->>Client: Routed to ErrorHandler
      else ok
        CSRF-->>Client: Next
      end
    end
  end
Loading
sequenceDiagram
  autonumber
  actor Client
  participant Lim as Limiter MW
  participant Mgr as Manager
  participant Store as Storage
  Client->>Lim: Request
  Lim->>Mgr: get(key)
  Mgr->>Store: GetWithContext
  Store-->>Mgr: raw or error
  alt error
    Lim-->>Client: Error (wrapped)
  else ok/miss
    Lim->>Lim: update counters
    Lim->>Mgr: set(key, item, exp)
    Mgr->>Store: SetWithContext
    Store-->>Mgr: ok or error
    alt error
      Lim-->>Client: Error "limiter: failed to persist state"
    else success
      Lim-->>Client: 200 or 429
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • efectn
  • sixcolors
  • ReneWerner87

Poem

A rabbit taps keys with careful delight,
Turning silent failures into errors in sight.
Caches, tokens, limits now speak when they stumble,
Locks click open, no secrets to mumble.
With pointer paws and tidy returns,
The warren runs smoother—no hidden concerns. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The provided PR description is too brief and does not follow the repository's required template; it only contains a one-line summary and a "Replaces #3597" note. Required sections from the template—detailed "Description", "Changes introduced" with files/components and tests, explicit "Type of change", checklist items (tests, docs, benchmarks, migration notes), and commit formatting guidance—are missing or not filled in, so reviewers lack necessary context. Because these template fields are expected for review and release notes, the description is largely incomplete. Please expand the PR description to follow the repository template: add a detailed "Description" explaining purpose and benefits, enumerate "Changes introduced" with affected components and test updates, specify the "Type of change", complete the checklist (tests, docs, benchmarks, migration notes, changelog), and include explicit issue linkage (e.g., "Fixes #N") or migration guidance if applicable.
Docstring Coverage ⚠️ Warning Docstring coverage is 25.93% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly and accurately summarizes the primary change: improving error handling for storage drivers across multiple middleware components. The raw_summary shows consistent edits to cache, csrf, limiter, storage managers and related tests that align with this description, so the title is fully related to the changeset. The emoji is cosmetic but does not make the title misleading or incorrect.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-middleware-error-handling-for-storage

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gaby gaby changed the title Add storage failure coverage for cache, CSRF, and limiter middlewares 🧹 chore: Improve error handling when using storage drivers Sep 20, 2025
@codecov
Copy link

codecov bot commented Sep 20, 2025

Codecov Report

❌ Patch coverage is 61.13537% with 89 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.44%. Comparing base (b176062) to head (caa55b9).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
middleware/cache/manager.go 52.63% 22 Missing and 5 partials ⚠️
middleware/cache/cache.go 47.72% 19 Missing and 4 partials ⚠️
middleware/limiter/limiter_sliding.go 31.57% 9 Missing and 4 partials ⚠️
middleware/limiter/manager.go 70.37% 6 Missing and 2 partials ⚠️
middleware/limiter/limiter_fixed.go 63.15% 5 Missing and 2 partials ⚠️
middleware/csrf/csrf.go 83.33% 4 Missing and 2 partials ⚠️
middleware/csrf/storage_manager.go 81.48% 4 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3754      +/-   ##
==========================================
- Coverage   92.04%   91.44%   -0.60%     
==========================================
  Files         114      113       -1     
  Lines       11799    11806       +7     
==========================================
- Hits        10860    10796      -64     
- Misses        680      743      +63     
- Partials      259      267       +8     
Flag Coverage Δ
unittests 91.44% <61.13%> (-0.60%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gaby gaby added this to v3 Sep 20, 2025
@gaby gaby added this to the v3 milestone Sep 20, 2025
@gaby gaby marked this pull request as ready for review September 20, 2025 14:54
@gaby gaby requested a review from a team as a code owner September 20, 2025 14:54
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR improves error handling when using storage drivers in the CSRF, limiter, and cache middleware. The changes add proper error propagation and handling when storage operations fail, replacing previously ignored errors with appropriate error messages.

Key changes:

  • Enhanced error handling for storage operations (get, set, delete) across middleware
  • Converted void functions to return errors for better error propagation
  • Added comprehensive test coverage for storage failure scenarios

Reviewed Changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
middleware/session/data_msgp.go Updates method receivers from value to pointer for msgp generated code
middleware/limiter/manager.go Adds error handling and type checking for storage and memory operations
middleware/limiter/limiter_test.go Adds test cases for storage get and set error scenarios
middleware/limiter/limiter_sliding.go Updates to handle storage errors and propagate them properly
middleware/limiter/limiter_fixed.go Updates to handle storage errors and propagate them properly
middleware/csrf/storage_manager_msgp.go Simplifies return statements in msgp generated code
middleware/csrf/storage_manager.go Adds error handling for storage operations and type checking
middleware/csrf/csrf_test.go Adds comprehensive test coverage for storage error scenarios
middleware/csrf/csrf.go Updates CSRF handlers to properly handle and propagate storage errors
middleware/cache/manager_test.go Updates tests to handle new error returns from manager methods
middleware/cache/manager.go Adds error handling for all storage operations and introduces cache miss error
middleware/cache/cache_test.go Adds test cases for cache storage error scenarios
middleware/cache/cache.go Updates cache handlers to properly handle storage errors

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex Review: Here are some suggestions.

Reply with @codex fix comments to fix any unresolved comments.

About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you open a pull request for review, mark a draft as ready, or comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex fix this CI failure" or "@codex address that feedback".

Comment on lines 309 to +321

// For external Storage we store raw body separated
if cfg.Storage != nil {
manager.setRaw(c, key+"_body", e.body, expiration)
if err := manager.setRaw(c, key+"_body", e.body, expiration); err != nil {
manager.release(e)
return err
}
// avoid body msgp encoding
e.body = nil
manager.set(c, key, e, expiration)
if err := manager.set(c, key, e, expiration); err != nil {
manager.release(e)
return err
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Roll back heap accounting on storage write errors

When a storage write fails in New, the code returns immediately after manager.setRaw/manager.set but the entry has already been inserted into the LRU heap and storedBytes was incremented before the failing call. This leaves the heap containing a stale item and keeps storedBytes inflated even though nothing was cached, so subsequent requests may believe the cache is full and evict entries or refuse new ones until another eviction happens. Consider removing the heap entry and subtracting its size before returning an error to keep cache accounting consistent.

Useful? React with 👍 / 👎.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
middleware/cache/manager.go (1)

64-77: Reset all fields on release to prevent stale data.
cencoding and heapidx aren’t reset, risking leakage across pooled uses.

 func (m *manager) release(e *item) {
 	// don't release item if we using in-memory storage
 	if m.storage == nil {
 		return
 	}
 	e.body = nil
 	e.ctype = nil
+	e.cencoding = nil
 	e.status = 0
 	e.age = 0
 	e.exp = 0
 	e.ttl = 0
 	e.headers = nil
+	e.heapidx = 0
 	m.pool.Put(e)
 }
🧹 Nitpick comments (16)
middleware/limiter/limiter_test.go (1)

19-66: Make the failing storage stub goroutine-safe.

Tests run in parallel and Fiber may process requests concurrently; guard the maps with a mutex to avoid future racy reads/writes if these helpers get reused in other tests.

Apply:

 type failingLimiterStorage struct {
-	data map[string][]byte
-	errs map[string]error
+	mu   sync.RWMutex
+	data map[string][]byte
+	errs map[string]error
 }
 
 func newFailingLimiterStorage() *failingLimiterStorage {
 	return &failingLimiterStorage{
-		data: make(map[string][]byte),
-		errs: make(map[string]error),
+		data: make(map[string][]byte),
+		errs: make(map[string]error),
 	}
 }
 
 func (s *failingLimiterStorage) GetWithContext(_ context.Context, key string) ([]byte, error) {
-	if err, ok := s.errs["get|"+key]; ok && err != nil {
+	s.mu.RLock()
+	err, ok := s.errs["get|"+key]
+	s.mu.RUnlock()
+	if ok && err != nil {
 		return nil, err
 	}
-	if val, ok := s.data[key]; ok {
+	s.mu.RLock()
+	val, ok := s.data[key]
+	s.mu.RUnlock()
+	if ok {
 		return append([]byte(nil), val...), nil
 	}
 	return nil, nil
 }
 
 func (s *failingLimiterStorage) SetWithContext(_ context.Context, key string, val []byte, _ time.Duration) error {
-	if err, ok := s.errs["set|"+key]; ok && err != nil {
+	s.mu.RLock()
+	err, ok := s.errs["set|"+key]
+	s.mu.RUnlock()
+	if ok && err != nil {
 		return err
 	}
-	s.data[key] = append([]byte(nil), val...)
+	s.mu.Lock()
+	s.data[key] = append([]byte(nil), val...)
+	s.mu.Unlock()
 	return nil
 }
middleware/limiter/limiter_sliding.go (3)

46-51: Pass cancellable context to storage calls (honor timeout middleware).

Fiber’s Ctx implements context.Context but Deadline/Done are no-ops; timeout middleware exposes the real derived context via c.Context(). Use it so store drivers can observe cancellations/timeouts.

-		e, err := manager.get(c, key)
+		e, err := manager.get(c.Context(), key)

104-107: Propagate cancellation to Set as well.

-		if setErr := manager.set(c, key, e, time.Duration(resetInSec+expiration)*time.Second); setErr != nil { //nolint:gosec // Not a concern
+		if setErr := manager.set(c.Context(), key, e, time.Duration(resetInSec+expiration)*time.Second); setErr != nil { //nolint:gosec // Not a concern

136-147: Use c.Context() in Skip branch for get/set to keep semantics consistent.*

-			entry, getErr := manager.get(c, key)
+			entry, getErr := manager.get(c.Context(), key)
 			if getErr != nil {
 				mux.Unlock()
 				return getErr
 			}
 			e = entry
 			e.currHits--
 			remaining++
-			if setErr := manager.set(c, key, e, cfg.Expiration); setErr != nil {
+			if setErr := manager.set(c.Context(), key, e, cfg.Expiration); setErr != nil {
 				mux.Unlock()
 				return fmt.Errorf("limiter: failed to persist state: %w", setErr)
 			}
middleware/limiter/limiter_fixed.go (3)

45-50: Pass the derived context into storage get.

Aligns with timeout middleware and cancellation propagation.

-		e, err := manager.get(c, key)
+		e, err := manager.get(c.Context(), key)

73-76: Pass the derived context into storage set.

-		if setErr := manager.set(c, key, e, cfg.Expiration); setErr != nil {
+		if setErr := manager.set(c.Context(), key, e, cfg.Expiration); setErr != nil {
 			mux.Unlock()
 			return fmt.Errorf("limiter: failed to persist state: %w", setErr)
 		}

105-116: Keep Skip branch consistent with context propagation.*

-			entry, getErr := manager.get(c, key)
+			entry, getErr := manager.get(c.Context(), key)
 			if getErr != nil {
 				mux.Unlock()
 				return getErr
 			}
 			e = entry
 			e.currHits--
 			remaining++
-			if setErr := manager.set(c, key, e, cfg.Expiration); setErr != nil {
+			if setErr := manager.set(c.Context(), key, e, cfg.Expiration); setErr != nil {
 				mux.Unlock()
 				return fmt.Errorf("limiter: failed to persist state: %w", setErr)
 			}
middleware/limiter/manager.go (2)

42-44: Tiny typo in comment.

“too” → “to”.

-		// Fallback too memory storage
+		// Fallback to memory storage

62-67: Avoid logging/returning raw keys (may contain PII like IPs).

Including the full key in error strings can leak user IPs or custom identifiers to logs. Consider redacting or truncating in the formatted message.

-			return nil, fmt.Errorf("limiter: failed to get key %q from storage: %w", key, err)
+			return nil, fmt.Errorf("limiter: failed to get key from storage: %w", err)

Similarly adjust other error formats that embed %q.

middleware/csrf/csrf.go (1)

109-113: Optional: consider fail‑open for safe methods on transient storage errors.

For GET/HEAD/OPTIONS/TRACE with a cookie present, you might opt to ignore storage errors (treat as token missing) instead of failing the request, to improve availability. Gate behind a config flag if needed.

middleware/csrf/csrf_test.go (1)

20-81: Great failing storage test double; add a regression for secret redaction.

Nice targeted error‑path coverage. After removing key from errors, assert the token isn’t present in captured error messages.

 require.ErrorContains(t, captured, "csrf: failed to fetch token from storage")
+require.NotContains(t, captured.Error(), "token")

Apply the same NotContains in TestCSRFStorageSetError and TestCSRFStorageDeleteError.

Also applies to: 82-176

middleware/cache/manager_test.go (2)

18-21: Prefer require over assert for nil checks in fatal paths.
Switch assert.Nil(t, it) to require.Nil(t, it) so the subtest stops immediately on failure.

-		assert.Nil(t, it)
+		require.Nil(t, it)

27-30: Strengthen positive-path assertions.
Also assert the stored body equals what was set to catch serialization/retention regressions.

 		it, err := cacheManager.get(context.Background(), id)
 		require.NoError(t, err)
 		assert.NotNil(t, it)
+		require.Equal(t, []byte("test-body"), it.body)
middleware/cache/cache_test.go (1)

88-171: Consider adding a missing-body scenario test.
Prepopulate metadata key only (no /_GET_body) and assert cacheBodyFetchError is returned on hit.

middleware/cache/cache.go (1)

103-114: Use request context for storage deletes.
deleteKey uses context.Background(), which ignores cancellations/timeouts. Thread through the request context for better control.

-	deleteKey := func(dkey string) error {
-		if err := manager.del(context.Background(), dkey); err != nil {
+	deleteKey := func(ctx context.Context, dkey string) error {
+		if err := manager.del(ctx, dkey); err != nil {
 			return err
 		}
 		// External storage saves body data with different key
 		if cfg.Storage != nil {
-			if err := manager.del(context.Background(), dkey+"_body"); err != nil {
+			if err := manager.del(ctx, dkey+"_body"); err != nil {
 				return err
 			}
 		}
 		return nil
 	}

And update call sites:

-				if err := deleteKey(key); err != nil {
+				if err := deleteKey(c, key); err != nil {
-				keyToRemove, size := heap.removeFirst()
-				if err := deleteKey(keyToRemove); err != nil {
+				keyToRemove, size := heap.removeFirst()
+				if err := deleteKey(c, keyToRemove); err != nil {
middleware/cache/manager.go (1)

17-28: Consider excluding heap index from serialization.
Persisting heapidx couples on-disk data to an in-process structure. If feasible, mark it ignored (e.g., heapidx int \msg:"-"``) and derive indices from the heap map instead.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1471049 and caa55b9.

📒 Files selected for processing (13)
  • middleware/cache/cache.go (8 hunks)
  • middleware/cache/cache_test.go (2 hunks)
  • middleware/cache/manager.go (3 hunks)
  • middleware/cache/manager_test.go (1 hunks)
  • middleware/csrf/csrf.go (7 hunks)
  • middleware/csrf/csrf_test.go (3 hunks)
  • middleware/csrf/storage_manager.go (2 hunks)
  • middleware/csrf/storage_manager_msgp.go (6 hunks)
  • middleware/limiter/limiter_fixed.go (5 hunks)
  • middleware/limiter/limiter_sliding.go (5 hunks)
  • middleware/limiter/limiter_test.go (2 hunks)
  • middleware/limiter/manager.go (2 hunks)
  • middleware/session/data_msgp.go (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Format Go code using gofumpt (enforced via make format)
Ensure code passes golangci-lint checks (enforced via make lint)
Optimize struct field alignment using betteralign (enforced via make betteralign)
Modernize Go code using gopls modernize (enforced via make modernize)

Files:

  • middleware/limiter/limiter_sliding.go
  • middleware/cache/manager_test.go
  • middleware/csrf/storage_manager.go
  • middleware/limiter/manager.go
  • middleware/limiter/limiter_fixed.go
  • middleware/limiter/limiter_test.go
  • middleware/cache/cache.go
  • middleware/csrf/csrf.go
  • middleware/cache/manager.go
  • middleware/session/data_msgp.go
  • middleware/cache/cache_test.go
  • middleware/csrf/csrf_test.go
  • middleware/csrf/storage_manager_msgp.go
🧠 Learnings (5)
📚 Learning: 2024-10-08T19:06:06.583Z
Learnt from: sixcolors
PR: gofiber/fiber#3016
File: middleware/session/store.go:164-167
Timestamp: 2024-10-08T19:06:06.583Z
Learning: Unit tests in this project use testify require.

Applied to files:

  • middleware/cache/manager_test.go
📚 Learning: 2024-10-08T19:06:06.583Z
Learnt from: sixcolors
PR: gofiber/fiber#2922
File: middleware/cors/utils.go:63-71
Timestamp: 2024-10-08T19:06:06.583Z
Learning: The project uses the testify/assert package for assertions in unit tests.

Applied to files:

  • middleware/cache/manager_test.go
📚 Learning: 2024-12-13T08:14:22.851Z
Learnt from: efectn
PR: gofiber/fiber#3162
File: hooks_test.go:228-228
Timestamp: 2024-12-13T08:14:22.851Z
Learning: In Go test files, prefer using the `require` methods from the `testify` package for assertions instead of manual comparisons and calls to `t.Fatal` or `t.Fatalf`.

Applied to files:

  • middleware/cache/manager_test.go
📚 Learning: 2024-11-29T12:37:27.581Z
Learnt from: efectn
PR: gofiber/fiber#3162
File: app_test.go:893-895
Timestamp: 2024-11-29T12:37:27.581Z
Learning: In the `Test_App_ShutdownWithContext` function in `app_test.go`, the `clientDone` channel is used to synchronize the client's request completion before proceeding, eliminating the need for additional `time.Sleep` calls.

Applied to files:

  • middleware/csrf/storage_manager.go
  • middleware/limiter/manager.go
📚 Learning: 2024-10-08T19:06:06.583Z
Learnt from: sixcolors
PR: gofiber/fiber#3016
File: middleware/csrf/csrf_test.go:164-165
Timestamp: 2024-10-08T19:06:06.583Z
Learning: In the `Test_CSRF_WithSession_Middleware` function, calling `session.NewWithStore()` without arguments is acceptable, as the default configuration is sufficient.

Applied to files:

  • middleware/csrf/csrf_test.go
🧬 Code graph analysis (6)
middleware/limiter/limiter_test.go (2)
internal/storage/memory/memory.go (2)
  • New (28-44)
  • Storage (14-19)
middleware/limiter/config.go (1)
  • Config (10-70)
middleware/cache/cache.go (1)
storage_interface.go (1)
  • Storage (10-46)
middleware/csrf/csrf.go (2)
app.go (2)
  • ErrorHandler (59-59)
  • Config (113-418)
middleware/csrf/config.go (1)
  • Config (16-121)
middleware/cache/manager.go (1)
middleware/cache/cache.go (1)
  • New (70-335)
middleware/cache/cache_test.go (1)
middleware/cache/config.go (1)
  • Config (11-75)
middleware/csrf/csrf_test.go (3)
middleware/csrf/csrf.go (1)
  • New (47-205)
middleware/csrf/config.go (3)
  • Config (16-121)
  • ConfigDefault (127-134)
  • HeaderName (124-124)
storage_interface.go (1)
  • Storage (10-46)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: repeated
  • GitHub Check: Compare
🔇 Additional comments (26)
middleware/limiter/limiter_test.go (2)

67-91: LGTM: Get error path is asserted end-to-end.

Good capture via ErrorHandler and substring checks; this validates the wrapped message without over-coupling.


93-118: LGTM — assertions are precise; approving.

rg confirms the messages originate from middleware/limiter/manager.go ("limiter: failed to store key") and from middleware/limiter/limiter_fixed.go and middleware/limiter/limiter_sliding.go ("limiter: failed to persist state"); only middleware/limiter/limiter_test.go asserts those strings.

middleware/limiter/manager.go (2)

62-90: Solid: clear error surfaces and pool hygiene.

Good wrapping on storage errors, release on unmarshal failure, and strict type checks for memory path.
Optional: ensure there’s a test that forces an unmarshal error (e.g., store invalid bytes) to cover the new branch.


93-110: LGTM: release semantics on all storage set paths.

Releasing on both success and error avoids pool leaks; memory path correctly keeps the pointer owned by the store.

middleware/session/data_msgp.go (1)

39-47: Pointer receivers for msgp methods: good; ensure no value-typed call sites remain.

The switch to pointer receivers for EncodeMsg/MarshalMsg/Msgsize is fine and matches other msgp updates in this PR. Please confirm all internal uses take a *data, not a value, to avoid method-set mismatches.

Also applies to: 50-56, 89-92

middleware/csrf/csrf.go (2)

109-113: Error propagation to ErrorHandler: solid and consistent.

The new error paths for get/store/delete correctly funnel to cfg.ErrorHandler and align with the updated storage manager API.

Also applies to: 161-165, 174-176, 189-191, 299-301


229-238: Double‑wrap wording is fine; verify no secret leakage.

getRawFromStorage wraps underlying storage errors with context. Once storage_manager stops embedding the token (see sibling comment), messages won’t leak secrets.

middleware/csrf/csrf_test.go (1)

1738-1749: Session and storage delete tests: good coverage.

Validates both session-backed and storage-backed delete paths with the new error-aware APIs.

Also applies to: 1745-1750

middleware/csrf/storage_manager_msgp.go (1)

124-132: Pointer receivers for storageManager msgp methods: OK.

Matches runtime usage where storageManager is held as a pointer. Regenerate msgp artifacts consistently to avoid drift.

Also applies to: 135-141, 174-177

middleware/cache/manager_test.go (1)

10-10: Good addition: use require for fatal assertions.

middleware/cache/cache_test.go (9)

7-8: New imports are appropriate for error‑injection tests.


26-36: Test storage stub looks correct and mirrors fiber.Storage semantics.
Clones byte slices to avoid aliasing and returns (nil, nil) on miss as required.


38-47: LGTM: GetWithContext mimics per‑key failures via errs map.


52-59: LGTM: SetWithContext handles injected errors and copies payloads.


64-70: LGTM: DeleteWithContext returns nil on missing keys, as required.


76-86: Reset/Close helpers are fine.


88-112: Great coverage of get‑path failures.
Captures and asserts the propagated error and 500 response.


114-138: Great coverage of set‑path failures.
Validates raw‑body store error propagation.


140-171: Great coverage of delete‑path failures on expiry.
Seeds an expired entry and asserts wrapped delete error reaches ErrorHandler.

middleware/cache/cache.go (4)

136-140: Confirm: does fiber.Ctx implement context.Context?
manager.get(c, key) (and friends) require a context.Context. If fiber.Ctx does not implement it in v3, these calls won’t compile; otherwise, all good. Please confirm.


171-178: Good: body fetch error path releases and unlocks before returning.


255-257: Good: eviction path now propagates delete errors with key context.


360-366: Helpful sentinel translation for missing raw bodies.
Clearer error when metadata exists but body is missing.

middleware/cache/manager.go (3)

37-38: Sentinel miss is appropriate and used with errors.Is.


80-109: Storage get wrapping is solid; caller must release on success.
Ensure all call sites release the item on both success and all early returns; see cache.go expiry path fix.


135-152: set (storage mode) owns release — document and keep call sites release-free.
Matches the fix proposed in cache.go to avoid double Put.

@ReneWerner87 ReneWerner87 merged commit 8136af2 into main Sep 20, 2025
13 of 15 checks passed
@ReneWerner87 ReneWerner87 deleted the fix-middleware-error-handling-for-storage branch September 20, 2025 22:20
@github-project-automation github-project-automation bot moved this to Done in v3 Sep 20, 2025
Abhirup-99 pushed a commit to Abhirup-99/fiber that referenced this pull request Nov 3, 2025
)

* Add error propagation tests for storage-backed middlewares

* Address lint issues in middleware error handling tests

* Handle cache misses without nolint directives

* Refactor cache miss handling to reduce nesting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Improve Error Handling in CSRF Middleware Storage

3 participants