🔥 feat: Add support for DisableAutoRegister of HEAD routes#3817
🔥 feat: Add support for DisableAutoRegister of HEAD routes#3817ReneWerner87 merged 9 commits intomainfrom
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughAdds automatic HEAD route generation for GET routes (marked with Changes
Sequence Diagram(s)sequenceDiagram
participant Startup as Startup
participant App as App
participant Router as Router
participant Tree as RouteTree
Startup->>App: startupProcess()
App->>Router: ensureAutoHeadRoutesLocked()
Router->>Tree: scan GET routes
alt DisableHeadAutoRegister == false
Tree-->>Router: GET route(s) found
Router->>Tree: clone GET -> HEAD (autoHead=true)
Tree->>Tree: insert HEAD route (suppress body)
Router->>Router: update handlersCount & hooks
end
Note over App,Router: For mounted sub-apps with non-root prefix
App->>Router: subApp.ensureAutoHeadRoutes()
Note over Router,Tree: On add/delete lifecycle
Router->>Tree: addRoute / deleteRoute
Router->>Tree: pruneAutoHeadRouteLocked(path) when HEAD added or GET removed
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Potential focus areas:
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
Summary of ChangesHello @ReneWerner87, 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 introduces a significant enhancement to how Fiber handles Highlights
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
Pull Request Overview
This PR enhances Fiber's routing system by automatically registering HEAD routes for every GET route, ensuring HEAD requests mirror GET behavior (status codes and headers) without sending a response body. The implementation adds a new configuration option to disable this feature and properly handles explicit HEAD registrations that override auto-generated ones.
Key changes:
- Introduced
DisableAutoRegisterconfig option to control automatic HEAD route generation - Added
autoHeadflag to Route struct to identify auto-generated HEAD routes - Implemented
pruneAutoHeadRouteLockedhelper to remove auto-HEAD routes when explicit HEAD handlers are registered
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| router.go | Core auto-HEAD logic: added ensureAutoHeadRoutes functions and pruning helpers |
| router_test.go | Comprehensive test suite covering auto-HEAD behavior in various scenarios |
| app.go | Added DisableAutoRegister config field and integrated auto-HEAD generation into startup |
| app_test.go | Updated existing tests to account for auto-generated HEAD routes |
| mount_test.go | Adjusted handler count assertions for mounted apps with auto-HEAD routes |
| docs/whats_new.md | Documented the new automatic HEAD routes feature |
| docs/guide/routing.md | Added routing guide section explaining auto-HEAD behavior |
| docs/api/fiber.md | Documented the DisableAutoRegister configuration option |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3817 +/- ##
==========================================
+ Coverage 91.91% 92.25% +0.34%
==========================================
Files 115 115
Lines 12377 9734 -2643
==========================================
- Hits 11376 8980 -2396
+ Misses 729 480 -249
- Partials 272 274 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new feature to automatically register HEAD routes for every GET route, which is a great enhancement for REST API compliance. The implementation is thorough, including configuration options to disable the feature, and updates to documentation and tests. My review focuses on ensuring the new logic correctly handles different router configurations, specifically case-insensitivity. I've found a couple of places where using the original path instead of the normalized path could lead to incorrect behavior, such as creating duplicate routes. I've provided suggestions to address these issues. Additionally, I recommend adding test cases for case-insensitive routing to ensure the feature is robust.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (5)
router.go (2)
481-503: Normalize path when pruning to avoid trailing-slash/case variants.Comparing by raw Route.Path can miss pruning when HEAD/GET are registered with equivalent paths that differ by casing or trailing slashes under non-strict/case-insensitive configs. Compare against the normalized route.path instead.
Apply this diff:
func (app *App) pruneAutoHeadRouteLocked(path string) { - headIndex := app.methodInt(MethodHead) + headIndex := app.methodInt(MethodHead) if headIndex == -1 { return } - headStack := app.stack[headIndex] + // Normalize for consistent comparison with route.path + norm := app.normalizePath(path) + headStack := app.stack[headIndex] for i := len(headStack) - 1; i >= 0; i-- { headRoute := headStack[i] - if headRoute.Path != path || headRoute.mount || headRoute.use || !headRoute.autoHead { + if headRoute.mount || headRoute.use || !headRoute.autoHead || headRoute.path != norm { continue } app.stack[headIndex] = append(headStack[:i], headStack[i+1:]...) app.routesRefreshed = true atomic.AddUint32(&app.handlersCount, ^uint32(len(headRoute.Handlers)-1)) //nolint:gosec // Not a concern return } }
620-674: De-dup and lookup by normalized path to avoid duplicate auto HEADs.Use route.path (normalized) instead of Route.Path (raw) when tracking existing HEADs and checking GETs. Prevents duplicates when GET/HEAD are registered with equivalent-but-different raw strings (e.g., "/users" vs "/users/").
Apply this diff:
func (app *App) ensureAutoHeadRoutesLocked() { @@ - headStack := app.stack[headIndex] - existing := make(map[string]struct{}, len(headStack)) - for _, route := range headStack { + headStack := app.stack[headIndex] + existing := make(map[string]struct{}, len(headStack)) + for _, route := range headStack { if route.mount || route.use { continue } - existing[route.Path] = struct{}{} + existing[route.path] = struct{}{} } @@ - for _, route := range app.stack[getIndex] { + for _, route := range app.stack[getIndex] { if route.mount || route.use { continue } - if _, ok := existing[route.Path]; ok { + if _, ok := existing[route.path]; ok { continue } @@ headStack = append(headStack, headRoute) - existing[route.Path] = struct{}{} + existing[route.path] = struct{}{} app.routesRefreshed = trueConsider adding a small test for trailing-slash/case-insensitive variants to lock this in.
router_test.go (2)
320-543: Auto-HEAD suite: strong coverage; add two edge cases for path normalization.Great end-to-end validations. To catch trailing-slash and case-insensitive variants, add focused tests so pruning/dedup works when raw paths differ but normalize to the same value.
Suggested additions:
+func TestAutoHead_PruneTrailingSlashVariant(t *testing.T) { + t.Parallel() + app := New(Config{StrictRouting: false}) + app.Get("/trail/", func(c Ctx) error { return c.SendString("ok") }) + // Ensure auto HEAD exists + app.startupProcess() + // Add explicit HEAD without trailing slash; should prune auto one + app.Head("/trail", func(c Ctx) error { + c.Set("X-Explicit", "1") + return c.SendStatus(StatusAccepted) + }) + resp, err := app.Test(httptest.NewRequest(MethodHead, "/trail", nil)) + require.NoError(t, err) + defer resp.Body.Close() + require.Equal(t, StatusAccepted, resp.StatusCode) + require.Equal(t, "1", resp.Header.Get("X-Explicit")) +} + +func TestAutoHead_CaseInsensitiveMatch(t *testing.T) { + t.Parallel() + app := New(Config{CaseSensitive: false}) + app.Get("/Users", func(c Ctx) error { return c.SendString("ok") }) + app.startupProcess() + // Explicit HEAD with different casing should override auto HEAD + app.Head("/users", func(c Ctx) error { return c.SendStatus(StatusNoContent) }) + resp, err := app.Test(httptest.NewRequest(MethodHead, "/USERS", nil)) + require.NoError(t, err) + defer resp.Body.Close() + require.Equal(t, StatusNoContent, resp.StatusCode) +}
1872-1873: Make Allow header assertion order-agnostic.RequestMethods order can be customized; assert membership instead of exact order.
Apply this diff:
- app.ensureAutoHeadRoutes() + app.ensureAutoHeadRoutes() app.RebuildTree() @@ - require.Equal(t, "GET, HEAD", allow) + parts := strings.Split(strings.ReplaceAll(allow, " ", ""), ",") + require.ElementsMatch(t, []string{"GET", "HEAD"}, parts)Also applies to: 1886-1887
docs/whats_new.md (1)
359-390: Consider adding fasthttp context to clarify the safety of HEAD route copying.The documentation explains that the response body "remains empty" for auto-generated HEAD routes, but doesn't explicitly mention that this behavior is guaranteed by fasthttp (which omits bodies for HEAD responses per HTTP spec). The PR objectives include documenting this technical detail and the safety rationale for copying GET handlers.
Consider adding a brief technical note clarifying that fasthttp handles body omission automatically:
Fiber now auto-registers a `HEAD` route whenever you add a `GET` route. The generated handler chain matches the `GET` chain so status codes and headers stay in sync while the response body remains empty, ensuring HEAD clients observe the same metadata as a GET consumer. + +This approach is safe because fasthttp automatically omits response bodies for HEAD requests, eliminating the need for handler-specific HEAD logic.This addition would more explicitly satisfy the PR objective to "document that fasthttp omits bodies for HEAD responses" and clarify why copying GET handlers for HEAD is safe.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
app.go(2 hunks)app_test.go(3 hunks)docs/api/fiber.md(1 hunks)docs/guide/routing.md(1 hunks)docs/whats_new.md(1 hunks)mount_test.go(5 hunks)router.go(5 hunks)router_test.go(7 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
**/*.go: Apply formatting using gofumpt (Make target: format)
Optimize struct field alignment using betteralign (Make target: betteralign)
Modernize code using gopls modernize (Make target: modernize)
Files:
mount_test.goapp.goapp_test.gorouter_test.gorouter.go
docs/**
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Review and update the contents of the
docsfolder if necessary when modifying code
Files:
docs/guide/routing.mddocs/whats_new.mddocs/api/fiber.md
🧠 Learnings (1)
📚 Learning: 2025-10-16T07:15:26.529Z
Learnt from: grivera64
PR: gofiber/fiber#3807
File: adapter_test.go:118-144
Timestamp: 2025-10-16T07:15:26.529Z
Learning: In Fiber v3, net/http handlers (http.Handler, http.HandlerFunc, or raw func(http.ResponseWriter, *http.Request)) can be passed directly to routing methods like app.Get(), app.Post(), etc. The framework automatically detects and wraps them internally via toFiberHandler/collectHandlers. The github.com/gofiber/fiber/v3/middleware/adaptor package is legacy and should not be suggested for tests or code using native net/http handler support.
Applied to files:
docs/guide/routing.mddocs/whats_new.md
🧬 Code graph analysis (3)
app_test.go (1)
constants.go (4)
HeaderAllow(231-231)MethodPatch(9-9)MethodGet(5-5)MethodHead(6-6)
router_test.go (4)
app.go (2)
New(521-634)Config(113-424)middleware/static/static.go (1)
New(83-229)ctx_interface_gen.go (1)
Ctx(18-426)constants.go (7)
MethodHead(6-6)StatusOK(52-52)MethodGet(5-5)StatusMethodNotAllowed(78-78)StatusNoContent(56-56)StatusNotFound(77-77)StatusAccepted(54-54)
router.go (2)
constants.go (2)
MethodGet(5-5)MethodHead(6-6)app.go (1)
App(68-110)
🪛 GitHub Actions: markdownlint
docs/api/fiber.md
[error] 56-56: markdownlint: MD055 table pipe style violation. Expected leading_and_trailing pipes; found leading_only; missing trailing pipe.
🪛 GitHub Check: markdownlint
docs/api/fiber.md
[failure] 57-57: Code block style
docs/api/fiber.md:57 MD046/code-block-style Code block style [Expected: fenced; Actual: indented] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md046.md
[failure] 56-56: Tables should be surrounded by blank lines
docs/api/fiber.md:56 MD058/blanks-around-tables Tables should be surrounded by blank lines [Context: "| <Reference id="disablekeepal..."] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md058.md
[failure] 56-56: Table column count
docs/api/fiber.md:56:96 MD056/table-column-count Table column count [Expected: 4; Actual: 2; Too few cells, row will be missing data] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md056.md
[failure] 56-56: Table pipe style
docs/api/fiber.md:56:96 MD055/table-pipe-style Table pipe style [Expected: leading_and_trailing; Actual: leading_only; Missing trailing pipe] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md055.md
🪛 LanguageTool
docs/api/fiber.md
[grammar] ~60-~60: Use a hyphen to join words.
Context: ... | Will not pre parse Multipart Form data if set to true...
(QB_NEW_EN_HYPHEN)
⏰ 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). (5)
- GitHub Check: Compare
- GitHub Check: unit (1.25.x, windows-latest)
- GitHub Check: unit (1.25.x, macos-13)
- GitHub Check: lint
- GitHub Check: repeated
🔇 Additional comments (7)
router.go (5)
57-64: Route.autoHead flag: clear intent and minimal footprint.Field addition is appropriate and constrained to routing metadata. Keep as is.
371-376: copyRoute correctly preserves autoHead.Good call keeping autoHead in sync across copies.
473-476: Prune auto HEAD when deleting a GET route.Correct invocation point and lock context; avoids stale auto HEADs.
588-591: Prune before adding explicit HEAD.Good prevention of duplicate handler chains on HEAD overrides.
613-619: Thread-safe helper wrapper looks good.Locking discipline is clear; wrapper keeps callsites tidy.
router_test.go (2)
1194-1194: Updated handler counts look consistent with auto-HEAD registrations.Numbers align with added HEAD routes and merges. No change requested.
Also applies to: 1198-1198, 1201-1201, 1203-1203, 1206-1206
1312-1315: startupProcess invocation and counts: OK.Ensures auto-HEAD setup before assertions; counts match expectations.
Also applies to: 1314-1314, 1338-1338
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
router.go (1)
659-662: Doc comment on fasthttp HEAD behavior is preciseWording matches transmission‑phase suppression; no body while preserving headers/length.
router_test.go (1)
15-16: Run project formatters after import changeAfter adding path/filepath, run make format to enforce gofumpt import ordering.
🧹 Nitpick comments (4)
router.go (3)
390-404: Path normalization helper matches register semanticsnormalizePath mirrors register’s casing and trailing‑slash rules and removes escapes. Consider reusing this helper inside register to reduce duplication and drift risk.
480-503: Pruning logic is correct and case/strict aware
- Normalizes the incoming path, then removes only mount=false,use=false,autoHead=true entries.
- Updates routesRefreshed and handlersCount.
Nit: the comment could mention it’s also used when a GET route is deleted, not only when an explicit HEAD is registered.
-// pruneAutoHeadRouteLocked removes an automatically generated HEAD route so a -// later explicit registration can take its place without duplicating handler -// chains. The caller must already hold app.mutex. +// pruneAutoHeadRouteLocked removes an automatically generated HEAD route. +// Used when (a) an explicit HEAD is registered, allowing it to take precedence, +// or (b) the originating GET route is removed, to avoid stale HEAD entries. +// The caller must already hold app.mutex.
621-679: Auto‑HEAD generation uses normalized keys and respects config
- Skips when DisableAutoRegister is true.
- Uses route.path (normalized) for de‑duplication in existing map — correct for case‑insensitive/strict routing setups.
- Updates handlersCount, routesRefreshed, latestRoute, and onRoute hooks.
Minor: assigning headStack back only when added is a micro‑optimization; setting unconditionally is also fine.
router_test.go (1)
320-562: Excellent coverage for auto‑HEAD lifecycleCovers enable/disable, override with explicit HEAD, groups, static files, 404, precedence, route listing, and no‑body semantics.
Optional enhancement: add a case‑insensitive scenario to guard against duplicates (e.g., Config{CaseSensitive:false}: GET /foo + explicit HEAD /Foo → single HEAD, no auto‑HEAD).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
docs/guide/routing.md(1 hunks)router.go(5 hunks)router_test.go(8 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- docs/guide/routing.md
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
**/*.go: Apply formatting using gofumpt (Make target: format)
Optimize struct field alignment using betteralign (Make target: betteralign)
Modernize code using gopls modernize (Make target: modernize)
Files:
router.gorouter_test.go
🧠 Learnings (1)
📚 Learning: 2025-07-19T15:13:10.652Z
Learnt from: CR
PR: gofiber/fiber#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-19T15:13:10.652Z
Learning: Run `make format` to format the project when modifying code
Applied to files:
router_test.go
🧬 Code graph analysis (2)
router.go (2)
constants.go (2)
MethodGet(5-5)MethodHead(6-6)app.go (1)
App(68-110)
router_test.go (2)
app.go (2)
New(521-634)Config(113-424)constants.go (7)
MethodHead(6-6)StatusOK(52-52)MethodGet(5-5)StatusMethodNotAllowed(78-78)StatusNoContent(56-56)StatusNotFound(77-77)StatusAccepted(54-54)
⏰ 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). (5)
- GitHub Check: Compare
- GitHub Check: lint
- GitHub Check: unit (1.25.x, macos-13)
- GitHub Check: unit (1.25.x, windows-latest)
- GitHub Check: repeated
🔇 Additional comments (11)
router.go (6)
59-64: Good addition: explicit marker for auto‑generated HEAD routesThe autoHead flag is the right minimal state to distinguish generated vs explicit HEAD entries. Keeps pruning safe.
371-376: copyRoute now preserves autoHeadPropagation of autoHead avoids misclassifying cloned routes later. LGTM.
410-416: RemoveRoute compares normalized, private pathUsing app.normalizePath and r.path ensures consistency with CaseSensitive/StrictRouting.
473-476: Prune auto HEAD when a GET route is removedThis avoids orphaned auto HEAD routes. Explicit HEAD remains untouched, as intended.
Please confirm we also want to prune auto HEAD when deleting GET via RemoveRouteFunc matchers; current call site covers it because prune is inside deleteRoute loop.
589-591: Head registration prunes stale auto HEAD firstDefensive and idempotent. Prevents duplicate HEAD stacks.
614-620: Thread‑safe wrapper is fineensureAutoHeadRoutes acquires app.mutex and delegates.
router_test.go (5)
1214-1227: Updated handler counts reflect auto‑HEAD generationNumbers now include the additional HEAD handlers. Keep these assertions in sync if RequestMethods or auto‑register defaults change.
1332-1335: Explicit startupProcess ensures auto‑HEADs exist before assertionsGood call to avoid flakiness in tests that inspect app state (GetRoutes/handlersCount).
1476-1478: Allow header now includes HEADExpectation "GET, HEAD" aligns with next() behavior after auto‑HEAD registration.
1892-1893: ensureAutoHeadRoutes before RebuildTree for Allow headerThis guarantees HEAD is advertised in MethodNotAllowed path for custom ctx.
1230-1301: normalizePath tests are thoroughExercising empty path, leading slash, strict routing, case sensitivity, and escape removal validates parity with register rules.
app.go
Outdated
| // every GET route. | ||
| // | ||
| // Default: false | ||
| DisableAutoRegister bool `json:"disable_auto_register"` |
There was a problem hiding this comment.
Maybe more explicit naming like DisableHeadAutoRegister or DisableHeadAutoRegistration?
| // Fasthttp automatically omits response bodies when transmitting | ||
| // HEAD responses, so the copied GET handler stack can execute | ||
| // unchanged while still producing an empty body on the wire. | ||
|
|
There was a problem hiding this comment.
[nitpick] While the comment explains fasthttp's body omission behavior, it should also clarify that this means Content-Length and other headers calculated by the GET handler remain accurate even though no body is transmitted.
| // Note: Headers such as Content-Length and others calculated by the GET handler | |
| // remain accurate and are transmitted, even though no body is sent. |
|
@coderabbitai suggest alternative names to config option DisableAutoRegister |
|
Tip For best results, initiate chat on the files or code changes. @gaby, here are some alternative names for the More specific negative options (disable/suppress):
Positive boolean options (inverted logic): My recommendation: I'd suggest
Alternatively, if you prefer positive boolean logic (which often reads more intuitively), Would any of these work better for your use case? |
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
docs/whats_new.md (1)
359-395: Backticks + example look goodBackticks for “
HEAD” and “GET” and the definedhandlermake this section copy/paste‑safe.docs/guide/routing.md (1)
19-55: Section reads wellBackticks and examples are consistent; override/disable behavior is clear.
🧹 Nitpick comments (5)
docs/whats_new.md (1)
359-395: Clarify HEAD body omission (fasthttp) and headersAdd a short note that fasthttp omits bodies on HEAD responses while preserving headers like Content-Length computed by the GET chain. Improves copy/paste confidence.
- Fiber now auto-registers a `HEAD` route whenever you add a `GET` route. The generated handler chain matches the `GET` chain so status codes and headers stay in sync while the response body remains empty, ensuring `HEAD` clients observe the same metadata as a `GET` consumer. + Fiber now auto-registers a `HEAD` route whenever you add a `GET` route. The generated handler chain matches the `GET` chain so status codes and headers stay in sync while the response body remains empty. Fasthttp automatically suppresses response bodies for `HEAD` responses during transmission, so headers (including `Content-Length`) computed by the `GET` chain are still sent while the payload is omitted.router.go (1)
621-679: Auto-HEAD generation logic: solid; tiny comment polishImplementation looks correct: skips
use/mount, uses normalizedroute.pathfor case-insensitive apps, updates counts, and triggers hooks. Consider expanding the fasthttp note to mention header accuracy.- // Fasthttp automatically omits response bodies when transmitting - // HEAD responses, so the copied GET handler stack can execute - // unchanged while still producing an empty body on the wire. + // Fasthttp automatically omits response bodies when transmitting HEAD responses, + // so the copied GET handler stack can execute unchanged while still producing + // an empty body on the wire. Headers (e.g., Content-Length, ETag) computed + // by the GET chain remain accurate and are sent.Also optional: keeping
Nameidentical meansRemoveRouteByName(name)without methods will remove both GET and generated HEAD. If this is undesirable, consider suffixing or omittingNamefor auto routes.Would you like a follow-up patch to differentiate route names for auto-generated HEAD entries?
docs/guide/routing.md (1)
19-55: Add one sentence on fasthttp HEAD behaviorMirror the “What’s New” note so readers know headers remain while the body is suppressed by fasthttp.
-Fiber automatically registers a `HEAD` route for every `GET` route you add. The generated handler chain mirrors the `GET` chain, so `HEAD` requests reuse middleware, status codes, and headers while the response body is suppressed. +Fiber automatically registers a `HEAD` route for every `GET` route you add. The generated handler chain mirrors the `GET` chain, so `HEAD` requests reuse middleware, status codes, and headers while the response body is suppressed. Fasthttp omits bodies for `HEAD` responses during transmission, so headers like `Content-Length` computed by the `GET` chain are still sent.router_test.go (2)
1475-1476: Make Allow header assertion order-insensitiveRequestMethods order could change; compare as a set to avoid flaky failures.
- require.Equal(b, MethodGet+", "+MethodHead, string(c.Response.Header.Peek("Allow"))) + allow := string(c.Response.Header.Peek("Allow")) + parts := strings.Split(allow, ", ") + require.ElementsMatch(b, []string{MethodGet, MethodHead}, parts)- require.Equal(t, "GET, HEAD", allow) + parts := strings.Split(allow, ", ") + require.ElementsMatch(t, []string{MethodGet, MethodHead}, parts)Remember to import
stringsin the test file scope if not already.Would you like me to push a patch updating both sites?
Also applies to: 1904-1905
384-388: Optional: Assert Allow header in 405 caseYou can assert
AllowincludesGETwhen auto-register is disabled to strengthen the contract.resp, err := app.Test(httptest.NewRequest(MethodHead, "/", nil)) require.NoError(t, err) registerCleanup(t, resp.Body) require.Equal(t, StatusMethodNotAllowed, resp.StatusCode) +require.Contains(t, resp.Header.Get("Allow"), MethodGet)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
app.go(2 hunks)docs/api/fiber.md(1 hunks)docs/guide/routing.md(1 hunks)docs/whats_new.md(1 hunks)router.go(5 hunks)router_test.go(7 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- docs/api/fiber.md
- app.go
🧰 Additional context used
📓 Path-based instructions (2)
docs/**
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Review and update the contents of the
docsfolder if necessary when modifying code
Files:
docs/guide/routing.mddocs/whats_new.md
**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
**/*.go: Apply formatting using gofumpt (Make target: format)
Optimize struct field alignment using betteralign (Make target: betteralign)
Modernize code using gopls modernize (Make target: modernize)
Files:
router.gorouter_test.go
🧠 Learnings (2)
📚 Learning: 2025-10-16T07:15:26.529Z
Learnt from: grivera64
PR: gofiber/fiber#3807
File: adapter_test.go:118-144
Timestamp: 2025-10-16T07:15:26.529Z
Learning: In Fiber v3, net/http handlers (http.Handler, http.HandlerFunc, or raw func(http.ResponseWriter, *http.Request)) can be passed directly to routing methods like app.Get(), app.Post(), etc. The framework automatically detects and wraps them internally via toFiberHandler/collectHandlers. The github.com/gofiber/fiber/v3/middleware/adaptor package is legacy and should not be suggested for tests or code using native net/http handler support.
Applied to files:
docs/guide/routing.mddocs/whats_new.md
📚 Learning: 2025-07-19T15:13:10.652Z
Learnt from: CR
PR: gofiber/fiber#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-19T15:13:10.652Z
Learning: Run `make format` to format the project when modifying code
Applied to files:
router_test.go
🧬 Code graph analysis (2)
router.go (2)
constants.go (2)
MethodGet(5-5)MethodHead(6-6)app.go (1)
App(68-110)
router_test.go (2)
app.go (2)
New(521-634)Config(113-424)constants.go (7)
MethodHead(6-6)StatusOK(52-52)MethodGet(5-5)StatusMethodNotAllowed(78-78)StatusNoContent(56-56)StatusNotFound(77-77)StatusAccepted(54-54)
⏰ 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). (5)
- GitHub Check: Compare
- GitHub Check: unit (1.25.x, macos-13)
- GitHub Check: repeated
- GitHub Check: unit (1.25.x, windows-latest)
- GitHub Check: unit (1.25.x, macos-latest)
🔇 Additional comments (9)
router.go (6)
57-64: Route flag addition is appropriate
autoHeadclearly distinguishes generated HEAD routes from explicit ones; used correctly in pruning.
371-376: Copy includesautoHeadGood to keep parity when cloning; later overrides to
truefor generated HEAD are explicit.
473-476: Prune auto HEAD on GET removalCorrectly avoids pruning for
use/mount; ensures counts/routesRefreshed update.
480-503: Path normalization respected; safe pruningNormalizing the incoming
pathand checkingautoHeadavoids deleting explicit HEAD routes and respectsCaseSensitive/StrictRouting.
589-592: Prune before explicit HEAD addPrevents duplicate handler chains when an explicit HEAD overrides an auto one.
614-619: Thread-safe wrapper
ensureAutoHeadRoutes()correctly gates the locked variant.router_test.go (3)
319-560: Great coverage of auto-HEAD behaviorTable-driven runners hit the key paths (default, disabled, override, groups, static, 404, ordering, listings, 204). Nice.
1330-1333: Handler count expectations updated for auto-HEADCounts account for generated HEAD routes after
startupProcess(); looks consistent. If RequestMethods is customized (e.g., without HEAD), these assertions will change—consider gating by config in future refactors.Also applies to: 1356-1357, 1213-1225
1891-1891: Explicit ensure before tree rebuildCalling
ensureAutoHeadRoutes()prior toRebuildTree()in this custom-ctx test removes order ambiguity.
Summary
pruneAutoHeadRouteLockedand document its purposeTesting
https://chatgpt.com/codex/tasks/task_e_68f8f6f6db7c83268b3ab6a8adabddc8