Thanks to visit codestin.com
Credit goes to github.com

Skip to content

🔥 feat: expand middleware context helpers#4079

Merged
ReneWerner87 merged 16 commits intomainfrom
update-middleware-helpers-for-context-types
Feb 23, 2026
Merged

🔥 feat: expand middleware context helpers#4079
ReneWerner87 merged 16 commits intomainfrom
update-middleware-helpers-for-context-types

Conversation

@gaby
Copy link
Member

@gaby gaby commented Feb 9, 2026

Motivation

  • Broaden middleware helper lookups so helpers can read stored values from multiple context types (fiber.Ctx, *fasthttp.RequestCtx, and context.Context) without panicking when an unexpected type is passed.
  • Ensure middleware writes values into both Fiber locals and the Go context.Context to keep lookups consistent across APIs and compatibility with code that uses plain context.Context or raw fasthttp contexts.
  • Update documentation and tests to reflect the new helper signatures and verify the three supported context types are handled.

Description

  • Changed helper signatures in middleware to accept ctx any and implemented a safe type switch supporting fiber.Ctx, *fasthttp.RequestCtx, and context.Context for requestid.FromContext, session.FromContext, csrf.TokenFromContext/HandlerFromContext, basicauth.UsernameFromContext, and keyauth.TokenFromContext.
  • Mirrored values into both locals and the Go context inside middleware handlers by keeping c.Locals(key, val) and adding c.SetContext(context.WithValue(c.Context(), key, val)) where values are set.
  • Updated docs under docs/middleware/*.md to document the new any-typed helper signatures and added/adjusted tests to cover lookups from fiber.Ctx, *fasthttp.RequestCtx, and context.Context.
  • Minor comment updates to ctx_interface_gen.go regarding Value/request release behavior and other small generated doc tweaks.

Fixes: #4066
Replaces: #4068

Copilot AI review requested due to automatic review settings February 9, 2026 15:50
@gaby gaby requested a review from a team as a code owner February 9, 2026 15:50
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Widen middleware context accessors to accept a generic ctx any, and propagate middleware values into the standard Go context.Context via c.SetContext(context.WithValue(...)), enabling retrieval from fiber.Ctx, fiber.CustomCtx, *fasthttp.RequestCtx, or context.Context.

Changes

Cohort / File(s) Summary
Context Interface Documentation
ctx_interface_gen.go
Doc comments updated noting Request(), Response() and Value() may return nil after context release.
Middleware API Docs
docs/middleware/basicauth.md, docs/middleware/csrf.md, docs/middleware/keyauth.md, docs/middleware/requestid.md, docs/middleware/session.md
Examples and public API signatures changed from fiber.Ctx to ctx any; docs now list accepted context types (fiber.Ctx, fiber.CustomCtx, *fasthttp.RequestCtx, context.Context).
BasicAuth
middleware/basicauth/basicauth.go, middleware/basicauth/basicauth_test.go
Store username in both Locals and Go context; UsernameFromContext(ctx any) added to read across supported context types; test added for cross-context retrieval.
CSRF
middleware/csrf/csrf.go, middleware/csrf/csrf_test.go
Store token and handler in both Locals and Go context; TokenFromContext(ctx any) and HandlerFromContext(ctx any) accept multiple context types; tests extended for multi-context reads.
KeyAuth
middleware/keyauth/keyauth.go, middleware/keyauth/keyauth_test.go
Store token in Go context as well as Locals; TokenFromContext(ctx any) supports multiple context sources; test validating consistency added.
RequestID
middleware/requestid/requestid.go, middleware/requestid/requestid_test.go
Middleware writes request ID into Go context and Locals; FromContext(ctx any) supports multiple context variants; test added for cross-context retrieval.
Session
middleware/session/middleware.go, middleware/session/middleware_test.go
Store session middleware instance into Go context and Locals; FromContext(ctx any) accepts multiple context types; tests added to verify retrieval across representations.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Client as Client
participant Fiber as Fiber App
participant MW as Middleware
participant Locals as Locals
participant GoCtx as Go Context
participant Handler as Downstream

Client->>Fiber: HTTP request
Fiber->>MW: enter middleware
MW->>Locals: set Locals(key)=value
MW->>GoCtx: c.SetContext(context.WithValue(...))
MW->>Handler: pass to next handler
Handler->>GoCtx: read via FromContext(ctx any)
Handler->>Locals: or read from Locals / RequestCtx

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • sixcolors
  • ReneWerner87
  • efectn

Poem

🐰 I hopped from Locals into GoCtx bright,
I carried names and tokens through the night.
From Fiber, RequestCtx, or plain ctx any,
A little rabbit finds the value many.
Hooray — cross-context crumbs make me light!

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'expand middleware context helpers' accurately summarizes the main feature change of extending middleware helper functions to accept multiple context types.
Description check ✅ Passed The PR description covers motivation, detailed description of changes, documentation updates, and test additions. It clearly documents the key changes to middleware helper signatures and context handling.
Linked Issues check ✅ Passed The PR fully addresses issue #4066 by enabling retrieval of middleware values (requestid, session, csrf token/handler, basicauth username, keyauth token) from multiple context types (fiber.Ctx, *fasthttp.RequestCtx, context.Context) and storing values in both locals and Go context.
Out of Scope Changes check ✅ Passed All changes are directly related to the stated objective of expanding middleware context helpers. Minor comment updates to ctx_interface_gen.go align with the broader context handling improvements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch update-middleware-helpers-for-context-types

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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.

@ReneWerner87 ReneWerner87 added this to v3 Feb 9, 2026
@ReneWerner87 ReneWerner87 added this to the v3 milestone Feb 9, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @gaby, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the robustness and interoperability of middleware context handling within the Fiber framework. By allowing middleware helpers to gracefully handle various context types and ensuring values are consistently stored across both Fiber's internal locals and Go's standard context, the changes improve API flexibility and compatibility with diverse Go programming patterns. This makes it easier for developers to integrate Fiber middleware with existing codebases that might use different context implementations.

Highlights

  • Expanded Context Helper Compatibility: Middleware helper functions now accept a broader range of context types, including fiber.Ctx, *fasthttp.RequestCtx, and context.Context, preventing panics when an unexpected type is provided.
  • Consistent Value Storage: Values set by middleware are now mirrored into both Fiber's local context (c.Locals) and Go's standard context.Context (c.SetContext(context.WithValue(c.Context(), key, val))), ensuring consistent lookups across different APIs and compatibility with plain context.Context or raw fasthttp contexts.
  • Documentation and Test Updates: The official documentation for affected middleware has been updated to reflect the new any-typed helper signatures, and new tests have been added or adjusted to verify correct behavior across all three supported context types.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • ctx_interface_gen.go
    • Added comments to Request() and Response() methods to clarify they return nil if the context has been released.
    • Updated the comment for the Value() method to explain its behavior when the context is released.
  • docs/middleware/basicauth.md
    • Updated UsernameFromContext signature to accept ctx any.
    • Added a note clarifying that UsernameFromContext supports fiber.Ctx, *fasthttp.RequestCtx, or context.Context.
  • docs/middleware/csrf.md
    • Updated TokenFromContext and HandlerFromContext signatures to accept ctx any.
    • Added a note clarifying that these functions support fiber.Ctx, *fasthttp.RequestCtx, or context.Context.
  • docs/middleware/keyauth.md
    • Updated TokenFromContext signature to accept ctx any.
    • Added a note clarifying that TokenFromContext supports fiber.Ctx, *fasthttp.RequestCtx, or context.Context.
  • docs/middleware/requestid.md
    • Updated FromContext signature to accept ctx any.
    • Added a note clarifying that FromContext supports fiber.Ctx, *fasthttp.RequestCtx, or context.Context.
  • docs/middleware/session.md
    • Updated session.FromContext usage example to sess := session.FromContext(ctx).
    • Added a note clarifying that FromContext supports fiber.Ctx, *fasthttp.RequestCtx, or context.Context.
  • middleware/basicauth/basicauth.go
    • Imported context and github.com/valyala/fasthttp.
    • Modified New function to store the username in both Fiber locals and the Go context.Context.
    • Refactored UsernameFromContext to accept ctx any and use a type switch for fiber.Ctx, *fasthttp.RequestCtx, and context.Context.
  • middleware/basicauth/basicauth_test.go
    • Added Test_BasicAuth_UsernameFromContext_Types to verify UsernameFromContext works correctly with all supported context types.
  • middleware/csrf/csrf.go
    • Imported context and github.com/valyala/fasthttp.
    • Modified New function to store the CSRF handler and token in both Fiber locals and the Go context.Context.
    • Refactored TokenFromContext and HandlerFromContext to accept ctx any and use a type switch for fiber.Ctx, *fasthttp.RequestCtx, and context.Context.
  • middleware/csrf/csrf_test.go
    • Added assertions in Test_CSRF_FromContextMethods to confirm TokenFromContext and HandlerFromContext work with *fasthttp.RequestCtx and context.Context.
  • middleware/keyauth/keyauth.go
    • Imported context and github.com/valyala/fasthttp.
    • Modified New function to store the authentication token in both Fiber locals and the Go context.Context.
    • Refactored TokenFromContext to accept ctx any and use a type switch for fiber.Ctx, *fasthttp.RequestCtx, and context.Context.
  • middleware/keyauth/keyauth_test.go
    • Added Test_TokenFromContext_Types to verify TokenFromContext works correctly with all supported context types.
  • middleware/requestid/requestid.go
    • Imported context and github.com/valyala/fasthttp.
    • Modified New function to store the request ID in both Fiber locals and the Go context.Context.
    • Refactored FromContext to accept ctx any and use a type switch for fiber.Ctx, *fasthttp.RequestCtx, and context.Context.
  • middleware/requestid/requestid_test.go
    • Added Test_RequestID_FromContext_Types to verify FromContext works correctly with all supported context types.
  • middleware/session/middleware.go
    • Imported context and github.com/valyala/fasthttp.
    • Modified initialize function to store the session middleware instance in both Fiber locals and the Go context.Context.
    • Refactored FromContext to accept ctx any and use a type switch for fiber.Ctx, *fasthttp.RequestCtx, and context.Context.
  • middleware/session/middleware_test.go
    • Imported net/http and net/http/httptest.
    • Added Test_Session_FromContext_Types to verify FromContext works correctly with all supported context types.
Activity
  • The author gaby initiated this pull request to expand middleware context helpers.
  • The author ran make audit, which reported unrelated Go standard library vulnerabilities but did not block the PR.
  • The author successfully ran make generate, make betteralign, make modernize, and make format.
  • The author confirmed that make lint passed with 0 issues.
  • All 2679 tests in the repository passed after these changes, with 1 skipped test.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request expands the middleware context helpers to support fiber.Ctx, *fasthttp.RequestCtx, and context.Context, which is a great enhancement for flexibility. The changes are well-implemented, and the inclusion of tests for the new functionality is appreciated. My review includes a few suggestions to refactor the new FromContext helper functions across different middleware packages to reduce code duplication and improve maintainability.

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.

Caution

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

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

170-181: ⚠️ Potential issue | 🟡 Minor

Stale doc comment: parameter name and description don't match the new signature.

The godoc still references c: The Fiber context, but the function now accepts ctx any supporting three context types.

📝 Proposed doc update
-// FromContext returns the Middleware from the Fiber context.
+// FromContext returns the Middleware from the given context.
 //
 // Parameters:
-//   - c: The Fiber context.
+//   - ctx: The context to retrieve the middleware from (fiber.Ctx, *fasthttp.RequestCtx, or context.Context).
 //
 // Returns:
 //   - *Middleware: The middleware object if found; otherwise, nil.
 //
 // Usage:
 //
 //	m := session.FromContext(c)
 func FromContext(ctx any) *Middleware {
🧹 Nitpick comments (3)
middleware/session/middleware_test.go (1)

387-403: Consider using status codes instead of require inside the handler to match existing test conventions.

The other tests in this file communicate results via HTTP status codes and assert outside the handler. Using require inside a handler can misbehave if the handler runs on a different goroutine (e.g., t.FailNow() calls runtime.Goexit()). Since app.Test() appears to run synchronously in Fiber, this works today but is inconsistent with the surrounding style.

♻️ Optional: align with existing handler patterns
 	app.Get("/", func(c fiber.Ctx) error {
-		require.NotNil(t, FromContext(c))
-		require.NotNil(t, FromContext(c.RequestCtx()))
-		require.NotNil(t, FromContext(c.Context()))
+		if FromContext(c) == nil || FromContext(c.RequestCtx()) == nil || FromContext(c.Context()) == nil {
+			return c.SendStatus(fiber.StatusInternalServerError)
+		}
 		return c.SendStatus(fiber.StatusOK)
 	})

Based on learnings: "In the Fiber codebase, the linter does not allow require assertions from within HTTP handlers (including net/http-style handlers). Use t.Fatalf, t.Errorf, or similar testing.T methods for error handling inside handler functions instead."

middleware/keyauth/keyauth_test.go (1)

555-581: Same note: require inside the handler deviates from this file's conventions.

The adjacent Test_TokenFromContext (line 526) returns the token as the response body and asserts outside. Consider matching that pattern for consistency.

♻️ Optional: match existing test style
 	app.Get("/", func(c fiber.Ctx) error {
-		require.Equal(t, CorrectKey, TokenFromContext(c))
-		require.Equal(t, CorrectKey, TokenFromContext(c.RequestCtx()))
-		require.Equal(t, CorrectKey, TokenFromContext(c.Context()))
-		return c.SendStatus(fiber.StatusOK)
+		fromCtx := TokenFromContext(c)
+		fromReqCtx := TokenFromContext(c.RequestCtx())
+		fromGoCtx := TokenFromContext(c.Context())
+		if fromCtx != CorrectKey || fromReqCtx != CorrectKey || fromGoCtx != CorrectKey {
+			return c.SendStatus(fiber.StatusInternalServerError)
+		}
+		return c.SendStatus(fiber.StatusOK)
 	})
middleware/csrf/csrf.go (1)

228-264: Note: loss of compile-time type safety. Changing from fiber.Ctx to any means callers passing an unsupported type will silently get a zero value ("" / nil) instead of a compile error. This is an intentional trade-off for multi-context support and is consistent across all middleware in this PR. Consider documenting the accepted types in the GoDoc comments (lines 226–227 and 246–247) to compensate — currently they just say "found in the context" without listing the accepted types.

📝 Suggested GoDoc enhancement
-// TokenFromContext returns the token found in the context
-// returns an empty string if the token does not exist
+// TokenFromContext returns the token found in the context.
+// ctx can be a fiber.Ctx, *fasthttp.RequestCtx, or context.Context.
+// Returns an empty string if the token does not exist or ctx is an unsupported type.
 func TokenFromContext(ctx any) string {

-// HandlerFromContext returns the Handler found in the context
-// returns nil if the handler does not exist
+// HandlerFromContext returns the Handler found in the context.
+// ctx can be a fiber.Ctx, *fasthttp.RequestCtx, or context.Context.
+// Returns nil if the handler does not exist or ctx is an unsupported type.
 func HandlerFromContext(ctx any) *Handler {

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

Expands Fiber middleware “FromContext” helper APIs to support lookups from fiber.Ctx, *fasthttp.RequestCtx, and context.Context, and mirrors middleware-written values into both Fiber locals and the Go context.Context to keep lookups consistent across APIs.

Changes:

  • Updated multiple middleware helpers to accept ctx any and safely type-switch across supported context types.
  • Mirrored middleware values into c.Context() via c.SetContext(context.WithValue(...)) in addition to c.Locals(...).
  • Updated docs and added tests covering lookups from fiber.Ctx, *fasthttp.RequestCtx, and context.Context.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
middleware/session/middleware.go Mirrors session middleware into Go context; expands FromContext to accept any.
middleware/session/middleware_test.go Adds tests validating FromContext works for Fiber/Fasthttp/Go contexts.
middleware/requestid/requestid.go Mirrors request ID into Go context; expands FromContext to accept any.
middleware/requestid/requestid_test.go Adds tests validating request ID lookup across context types.
middleware/keyauth/keyauth.go Mirrors token into Go context; expands TokenFromContext to accept any.
middleware/keyauth/keyauth_test.go Adds tests validating token lookup across context types.
middleware/csrf/csrf.go Mirrors CSRF handler/token into Go context; expands context helpers to accept any.
middleware/csrf/csrf_test.go Extends tests to validate lookups via RequestCtx() and Context().
middleware/basicauth/basicauth.go Mirrors username into Go context; expands UsernameFromContext to accept any.
middleware/basicauth/basicauth_test.go Adds tests validating username lookup across context types.
docs/middleware/session.md Documents broadened FromContext signature (example updated).
docs/middleware/requestid.md Documents broadened FromContext signature.
docs/middleware/keyauth.md Documents broadened TokenFromContext signature.
docs/middleware/csrf.md Documents broadened helper signatures for token/handler.
docs/middleware/basicauth.md Documents broadened UsernameFromContext signature.
ctx_interface_gen.go Clarifies behavior of Request/Response/Value after context release.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.

Benchmark suite Current: 7ccc68c Previous: c64bda1 Ratio
Benchmark_Middleware_BasicAuth - B/op 112 B/op 48 B/op 2.33
Benchmark_Middleware_BasicAuth - allocs/op 5 allocs/op 3 allocs/op 1.67
Benchmark_Middleware_BasicAuth_Upper - B/op 112 B/op 48 B/op 2.33
Benchmark_Middleware_BasicAuth_Upper - allocs/op 5 allocs/op 3 allocs/op 1.67

This comment was automatically generated by workflow using github-action-benchmark.

@gaby
Copy link
Member Author

gaby commented Feb 9, 2026

Note to myself: Add support for CustomCtx

### Motivation
- Broaden middleware helper lookups so helpers can read stored values from multiple context types (`fiber.Ctx`, `*fasthttp.RequestCtx`, and `context.Context`) without panicking when an unexpected type is passed.
- Ensure middleware writes values into both Fiber locals and the Go `context.Context` to keep lookups consistent across APIs and compatibility with code that uses plain `context.Context` or raw fasthttp contexts.
- Update documentation and tests to reflect the new helper signatures and verify the three supported context types are handled.

### Description
- Changed helper signatures in middleware to accept `ctx any` and implemented a safe type switch supporting `fiber.Ctx`, `*fasthttp.RequestCtx`, and `context.Context` for `requestid.FromContext`, `session.FromContext`, `csrf.TokenFromContext`/`HandlerFromContext`, `basicauth.UsernameFromContext`, and `keyauth.TokenFromContext`.
- Mirrored values into both locals and the Go context inside middleware handlers by keeping `c.Locals(key, val)` and adding `c.SetContext(context.WithValue(c.Context(), key, val))` where values are set.
- Updated docs under `docs/middleware/*.md` to document the new `any`-typed helper signatures and added/adjusted tests to cover lookups from `fiber.Ctx`, `*fasthttp.RequestCtx`, and `context.Context`.
- Minor comment updates to `ctx_interface_gen.go` regarding `Value`/request release behavior and other small generated doc tweaks.

### Testing
- Ran `make audit` — failed: `govulncheck` reported Go stdlib vulnerabilities (summary: "Your code is affected by 12 vulnerabilities..."; exit status 3) indicating unrelated standard library issues with the current Go toolchain used in the environment.
- Ran `make generate` — succeeded (`go generate ./...` completed).
- Ran `make betteralign` — succeeded (betteralign applied without errors).
- Ran `make modernize` — succeeded (modernize ran with `-fix`).
- Ran `make format` — succeeded (`gofumpt` applied formatting).
- Ran `make lint` — succeeded (`golangci-lint` returned `0 issues`).
- Ran `make test` — succeeded: test run completed with `DONE 2679 tests, 1 skipped` and all tests in this repo passed (see test output with many `PASS` lines).
@codecov
Copy link

codecov bot commented Feb 10, 2026

Codecov Report

❌ Patch coverage is 97.82609% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 91.05%. Comparing base (562043e) to head (05d6ba8).
⚠️ Report is 34 commits behind head on main.

Files with missing lines Patch % Lines
middleware/basicauth/basicauth.go 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4079      +/-   ##
==========================================
+ Coverage   90.99%   91.05%   +0.06%     
==========================================
  Files         119      119              
  Lines       11337    11337              
==========================================
+ Hits        10316    10323       +7     
+ Misses        648      643       -5     
+ Partials      373      371       -2     
Flag Coverage Δ
unittests 91.05% <97.82%> (+0.06%) ⬆️

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.

### Motivation

- Ensure middleware helper functions can safely read values when given a `fiber.CustomCtx` in addition to `fiber.Ctx`, `*fasthttp.RequestCtx`, and `context.Context`.\
- Keep middleware behavior consistent by mirroring values into the Go `context.Context` when handlers set locals so helpers can find values from either API.

### Description

- Changed helper signatures to accept `ctx any` and added `fiber.CustomCtx` handling in `requestid`, `basicauth`, `keyauth`, `csrf`, and `session` helpers.\
- Middleware handlers now mirror locals into the Go context using `c.SetContext(context.WithValue(c.Context(), key, val))` when setting values (request id, username, token, csrf handler, session middleware).\
- Updated tests to assert lookups succeed for `fiber.Ctx`, `fiber.CustomCtx`, `*fasthttp.RequestCtx`, and `context.Context` for the affected helpers.\
- Updated middleware docs to list `fiber.CustomCtx` as an accepted argument type for the helpers and adjusted API signatures in docs.

### Testing

- `make audit` — failed: `govulncheck` reported standard library vulnerabilities (Go 1.25.1); summary: "Your code is affected by 12 vulnerabilities..." (exit status 3).\
- `make generate` — succeeded (`go generate ./...` completed).\
- `make betteralign` — succeeded (betteralign applied without errors).\
- `make modernize` — succeeded (`modernize` ran with `-fix`).\
- `make format` — succeeded (`gofumpt` applied formatting).\
- `make lint` — succeeded (`gocritic`/golangci-lint run returned `0 issues`).\
- `make test` — succeeded: test suite completed with "DONE 2679 tests, 2 skipped" (all tests in repo passed).
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.

Caution

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

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

170-181: ⚠️ Potential issue | 🟡 Minor

Stale parameter doc — still references c: The Fiber context.

The Parameters section in the docstring still describes c: The Fiber context, but the function now accepts ctx any. Update for consistency.

📝 Proposed doc fix
 // FromContext returns the Middleware from the Fiber context.
 // It accepts fiber.Ctx, fiber.CustomCtx, *fasthttp.RequestCtx, and context.Context.
 //
 // Parameters:
-//   - c: The Fiber context.
+//   - ctx: A fiber.Ctx, fiber.CustomCtx, *fasthttp.RequestCtx, or context.Context.
 //
 // Returns:
 //   - *Middleware: The middleware object if found; otherwise, nil.
🧹 Nitpick comments (2)
middleware/basicauth/basicauth.go (1)

130-139: Redundant CustomCtx sub-check — both branches call the same Locals method.

fiber.CustomCtx embeds fiber.Ctx without overriding the Locals method, so a value implementing CustomCtx will match case fiber.Ctx. Inside that case, both customCtx.Locals(usernameKey) (line 133) and typed.Locals(usernameKey) (line 137) dispatch to the identical Locals method on the embedded Ctx interface. The inner CustomCtx type-assert + Locals call is dead code.

♻️ Simplify by removing the redundant CustomCtx branch
 	switch typed := ctx.(type) {
 	case fiber.Ctx:
-		if customCtx, ok := typed.(fiber.CustomCtx); ok {
-			if username, ok := customCtx.Locals(usernameKey).(string); ok {
-				return username
-			}
-		}
 		if username, ok := typed.Locals(usernameKey).(string); ok {
 			return username
 		}
middleware/csrf/csrf.go (1)

229-276: Consider extracting the repeated type-switch pattern into a shared helper.

TokenFromContext, HandlerFromContext, requestid.FromContext, session.FromContext, and keyauth.TokenFromContext all implement the same four-way type switch (fiber.CtxCustomCtx check → *fasthttp.RequestCtxcontext.Context). A generic helper such as:

func valueFromContext[T any](ctx any, key any) (T, bool) { ... }

in an internal package could eliminate the duplication across five middleware packages. Not urgent — the current copy-paste is simple enough — but worth considering as the number of middleware helpers grows.

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: 1

🤖 Fix all issues with AI agents
In `@middleware/keyauth/keyauth.go`:
- Around line 102-124: TokenFromContext currently has an unreachable case
because the type switch checks case fiber.Ctx before case fiber.CustomCtx; move
the case fiber.CustomCtx to appear before case fiber.Ctx in the TokenFromContext
function so values implementing CustomCtx are handled by that branch, and apply
the same reorder fix in the analogous FromContext functions in requestid,
session, csrf, and basicauth so each checks fiber.CustomCtx before fiber.Ctx.
🧹 Nitpick comments (1)
middleware/csrf/csrf.go (1)

229-278: Consider extracting the multi-context type-switch into a shared generic helper to reduce duplication.

The exact same type-switch pattern (fiber.CtxLocals, *fasthttp.RequestCtxUserValue, fiber.CustomCtxLocals, context.ContextValue) is repeated in at least five middleware packages (csrf, keyauth, basicauth, requestid, session). A single generic helper in the fiber package would centralise this, making it easier to maintain and extend (e.g., adding new context types).

♻️ Example shared helper sketch
// In the fiber package (or an internal middleware util package):

// ValueFromContext retrieves a value stored under key from any supported
// context type (fiber.Ctx, *fasthttp.RequestCtx, or context.Context).
func ValueFromContext[T any](ctx any, key any) (val T, ok bool) {
	switch typed := ctx.(type) {
	case Ctx:
		val, ok = typed.Locals(key).(T)
	case *fasthttp.RequestCtx:
		val, ok = typed.UserValue(key).(T)
	case context.Context:
		val, ok = typed.Value(key).(T)
	}
	return
}

Each middleware would then become a one-liner:

func TokenFromContext(ctx any) string {
	token, _ := fiber.ValueFromContext[string](ctx, tokenKey)
	return token
}

Note: since fiber.CustomCtx embeds fiber.Ctx, any CustomCtx value already matches the fiber.Ctx interface case — the explicit fiber.CustomCtx arm is unreachable (which the nolint comment acknowledges). A shared helper eliminates the need to repeat and suppress this in every package.

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.

Caution

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

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

170-182: ⚠️ Potential issue | 🟡 Minor

Stale parameter documentation — name and type no longer match the signature.

The docstring still says c: The Fiber context but the parameter is now ctx any, accepting multiple context types.

Proposed fix
 // FromContext returns the Middleware from the Fiber context.
 // It accepts fiber.CustomCtx, fiber.Ctx, *fasthttp.RequestCtx, and context.Context.
 //
 // Parameters:
-//   - c: The Fiber context.
+//   - ctx: A supported context type (fiber.CustomCtx, fiber.Ctx, *fasthttp.RequestCtx, or context.Context).
 //
 // Returns:
 //   - *Middleware: The middleware object if found; otherwise, nil.
 //
 // Usage:
 //
-//	m := session.FromContext(c)
+//	m := session.FromContext(ctx)
 func FromContext(ctx any) *Middleware {
🧹 Nitpick comments (1)
middleware/csrf/csrf.go (1)

226-278: Consider extracting the repeated type-switch pattern into a shared generic helper.

The same four-case type switch (CustomCtxCtx*fasthttp.RequestCtxcontext.Context) is duplicated verbatim in TokenFromContext and HandlerFromContext here, and again in keyauth.TokenFromContext, requestid.FromContext, basicauth.UsernameFromContext, and session.FromContext — six copies total.

A single generic helper in the fiber package (or an internal package) would eliminate all duplication:

Example shared helper sketch
// In a shared location, e.g., fiber package or internal/ctxutil
package fiber

import (
	"context"
	"github.com/valyala/fasthttp"
)

// ValueFromContext retrieves a typed value from any supported context representation.
func ValueFromContext[T any](ctx any, key any) (val T, ok bool) {
	switch typed := ctx.(type) {
	case CustomCtx:
		val, ok = typed.Locals(key).(T)
	case Ctx:
		val, ok = typed.Locals(key).(T)
	case *fasthttp.RequestCtx:
		val, ok = typed.UserValue(key).(T)
	case context.Context:
		val, ok = typed.Value(key).(T)
	}
	return
}

Each middleware then becomes a one-liner:

func TokenFromContext(ctx any) string {
	token, _ := fiber.ValueFromContext[string](ctx, tokenKey)
	return token
}

Copy link
Member

@sixcolors sixcolors left a comment

Choose a reason for hiding this comment

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

Performance impact concerns

Looking at the benchmark results:

Benchmark_Middleware_BasicAuth
- B/op:        48 → 112  (+133%)
- allocs/op:    3 → 5    (+67%)

This hits every request to store values in context.Context, even though both *fasthttp.RequestCtx and context.Context support is for external library interop - not core Fiber usage.

The issue we're solving

From #4066: passing c.Context() to service layers that expect standard context.Context. Valid use case, but affects a subset of users.

Do we need to store in all three context types on every request?

  • fiber.Ctx - core, no debate
  • ⚠️ *fasthttp.RequestCtx - for fasthttp library interop (rare?)
  • ⚠️ context.Context - for standard library/service layer interop (#4066)

If you have fiber.Ctx, you already have access to both via c.RequestCtx() and c.Context(). The question is: should we eagerly store in all of them on every request?

Alternative: on-demand helpers

Zero overhead until you need it:

func ToContext(ctx context.Context, c fiber.Ctx) context.Context {
    return context.WithValue(ctx, requestIDKey, FromContext(c))
}

// Usage - only allocates when passing to service layers
service(requestid.ToContext(c.Context(), c))

// Zero overhead for handlers that don't use external libraries
id := requestid.FromContext(c)  // Just reads from Locals

Alternative: opt-in config

type Config struct {
    StoreInContext *bool  // default true for compat
}

Performance-sensitive apps can set to false and use helpers when needed. Gives users the choice.

Questions

  1. How many users actually pass c.Context() to service layers vs just using c in handlers?
  2. Is the allocation increase and performance degradation acceptable for all users to solve a library interop use case?
  3. Should this be opt-in (default true) vs always-on?

Not blocking the PR, but wanted to surface the perf trade-off for discussion. Thoughts @gaby @ReneWerner87 @efectn?

Copy link
Member

@sixcolors sixcolors left a comment

Choose a reason for hiding this comment

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

Follow-up: All middleware keys are unexported - helpers required anyway

Just realized something important: all middleware use unexported context keys, which means external services can't access the values directly even if they're stored in context.Context.

// All these are unexported (lowercase or private types)
requestid:   requestIDKey contextKey = iota
session:     middlewareContextKey middlewareKey = iota  
basicauth:   usernameKey contextKey = iota
keyauth:     tokenKey contextKey = iota
csrf:        tokenKey contextKey = iota

So in an external service layer, this won't work:

// ❌ Can't access - key is unexported
ctx.Value(requestIDKey)  // Compile error - requestIDKey not accessible

External services must import the middleware package:

// ✅ Required approach
import "github.com/gofiber/fiber/v3/middleware/requestid"

rid := requestid.FromContext(ctx)  // Must use this helper

This means: Whether we store in context.Context eagerly or on-demand, external services need the same import and helper call. The only difference is whether we pay the performance cost on every request vs only when needed.

If we're already requiring import + FromContext(), why not let users opt into the allocation cost instead of forcing it on everyone?

@sixcolors
Copy link
Member

Follow-up: All middleware keys are unexported - helpers required anyway

Just realized something important: all middleware use unexported context keys, which means external services can't access the values directly even if they're stored in context.Context.

// All these are unexported (lowercase or private types)
requestid:   requestIDKey contextKey = iota
session:     middlewareContextKey middlewareKey = iota  
basicauth:   usernameKey contextKey = iota
keyauth:     tokenKey contextKey = iota
csrf:        tokenKey contextKey = iota

So in an external service layer, this won't work:

// ❌ Can't access - key is unexported
ctx.Value(requestIDKey)  // Compile error - requestIDKey not accessible

External services must import the middleware package:

// ✅ Required approach
import "github.com/gofiber/fiber/v3/middleware/requestid"

rid := requestid.FromContext(ctx)  // Must use this helper

This means: Whether we store in context.Context eagerly or on-demand, external services need the same import and helper call. The only difference is whether we pay the performance cost on every request vs only when needed.

If we're already requiring import + FromContext(), why not let users opt into the allocation cost instead of forcing it on everyone?

Actually, thinking about this more - since the middleware keys are unexported anyway, why not just provide helper functions or example code that let users export values to their own context keys when needed?

Copy link
Member

@ReneWerner87 ReneWerner87 left a comment

Choose a reason for hiding this comment

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

lets discuss this feature in the maintainer round

@ReneWerner87
Copy link
Member

ReneWerner87 commented Feb 14, 2026

We have to strike a balance between performance and user experience here.

In internal discussions, we have come to the conclusion
that we do not want to impose these extra allocations on all users who use the middleware, thereby directly reducing performance
since users should normally have direct access to fiber.CTX and be able to use it

However, there is still the option of combining everything under one implementation -> by only filling the user context if the fiber user explicitly requests it via the app config setting or mw setting
f.e.

app := fiber.New(fiber.Config{
   StoreDataInUserContext: true, // <- best name ever .... TBD :D, default "false"
})

or direct in the specific mw

app.Use(requestid.New(requestid.Config{
    ...
    StoreDataInUserContext: true // default "false"
})

This allows us to strike a balance between performance and convenience.

The problem with the key not being exported does not exist here either, as access is only via helper functions that know about the key because they are part of the middleware solution code.

@gaby @sixcolors
I think we can proceed with this, or are there still concerns that are not mentioned in the text?

@gaby
Copy link
Member Author

gaby commented Feb 14, 2026

@ReneWerner87 Yeah, that's my plan. I'm adding the config option at the app level because some of the middleware do not have a New, for example proxy. That way we don't limit ourselfs in the future.

I have these changes on my To-Do list for this weekend.

@sixcolors
Copy link
Member

sixcolors commented Feb 14, 2026

I'm thinking through the goal here and realize we might be missing the actual problem.

The goal as I understand it (#4066) is to enable services that aren't Fiber-aware to access middleware values. But this PR doesn't achieve that—it just stores unexported keys in multiple contexts instead of one. External services still can't call ctx.Value(requestIDKey) because the key isn't exported, so they still need to import "fiber/middleware/requestid" and call requestid.FromContext().

So we're not giving services any real independence from Fiber.

If we want truly Fiber-agnostic services, we'd need to either:

  • Export the context keys (so services can access them directly, though it would still require a package import and is not Go best practice per context docs), or
  • Document that users should map middleware values to their own context keys at the app level (which is a single line of code in the handler)
app.Get("/test", func(c *fiber.Ctx) error {
    id := requestid.FromContext(c)
    service(context.WithValue(c.Context(), myRequestIDKey, id)) // Manual bridge.
    return c.SendStatus(200)
})

if services need to be fiber aware I’m not sure why users wouldn’t just pass the fiber ctx.

@ReneWerner87
Copy link
Member

Okay, the unexported keys are a problem if it has to be the case that the external tools are completely independent of the middleware itself and no helper can be used.
Do we know for sure that the user really doesn't want to use a helper?

Perhaps we need to clarify again exactly what needs to be achieved in order to be able to evaluate it again.
Maybe this manual bridge can also be simplified.

@ReneWerner87
Copy link
Member

Or we could do something like this

app.Use(requestid.New(requestid.Config{
    ...
    StoreInUserContext: "keyName" // default "" - off 
})

But let's find out the parameter for this implementation

@ReneWerner87 ReneWerner87 merged commit 87ce0f9 into main Feb 23, 2026
21 checks passed
@ReneWerner87 ReneWerner87 deleted the update-middleware-helpers-for-context-types branch February 23, 2026 08:58
@github-project-automation github-project-automation bot moved this to Done in v3 Feb 23, 2026
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.

🐛 [Bug]: No way of accessing requestid value other than from fiber.Ctx

4 participants