Skip to content

🔥 feat: Add URL() method to Route for generating URLs with parameters#4195

Open
Claude wants to merge 15 commits intomainfrom
claude/fix-getroute-path-param
Open

🔥 feat: Add URL() method to Route for generating URLs with parameters#4195
Claude wants to merge 15 commits intomainfrom
claude/fix-getroute-path-param

Conversation

@Claude
Copy link
Copy Markdown
Contributor

@Claude Claude AI commented Apr 7, 2026

Description

Adds a new Route.URL(params Map) (string, error) API for generating relative URLs directly from named routes with parameter substitution.

This change lets users construct URLs programmatically from app.GetRoute(name) without going through Ctx.GetRouteURL(), while keeping behavior aligned with existing named-route URL generation. Follow-up review feedback refined the implementation so URL generation is deterministic, respects route-level case sensitivity, handles mounted sub-app routes correctly, prefers the matching greedy token type for + vs *, gracefully falls back to route.Path when a route has no parsed segments, avoids per-call allocations in greedy fallback lookup by using precomputed string key orders, and uses a value receiver so the common call pattern app.GetRoute(name).URL(params) compiles directly.

app.Get("/user/:name/:id", handler).Name("user")

url, err := app.GetRoute("user").URL(fiber.Map{"name": "john", "id": "123"})
// Returns: "/user/john/123"

Changes introduced

  • Benchmarks: The implementation continues to use bytebufferpool for efficient string building with minimal allocations, and the greedy fallback lookup now uses precomputed string key orders to avoid repeated hot-path string conversions and extra allocations.
  • Documentation Update: Added public documentation for generating URLs from routes via app.GetRoute(name) in docs/api/app.md, added a release-note entry in docs/whats_new.md, and refined the router.go godoc for Route.URL() to reflect direct app.GetRoute(name).URL(params) usage.
  • Changelog/What's New: Documented that named routes retrieved with app.GetRoute(name) now support route.URL(params) for parameterized URL generation, including named, wildcard (*), and plus (+) segments.
  • Migration Guide: Not required. This is a non-breaking additive API.
  • API Alignment with Express: Route.URL() complements Fiber’s existing named-route helpers in an Express-like style by letting callers generate route URLs directly from route metadata.
  • API Longevity: The method signature matches existing c.GetRouteURL() conventions by returning (string, error). The implementation was refactored to a shared buildRouteURL(route, params) helper used by both Route.URL() and DefaultRes.getLocationFromRoute() so behavior stays consistent across APIs, and Route.URL() now uses a value receiver to match app.GetRoute() returning a Route value.
  • Examples: Supports standard params, wildcard params, greedy plus params, deterministic exact-match precedence, direct app.GetRoute(name).URL(params) calls, and route fallback behavior when only Path is available.

Additional adjustments included in this PR:

  • Added caseSensitive handling to Route so Route.URL() respects route registration and mounted sub-app behavior.
  • Parameter resolution is deterministic: exact match → case-insensitive lexicographically-smallest fallback (when !caseSensitive) → greedy fallback.
  • Greedy fallback now prefers + for plus params and * for wildcard params before falling back to the alternate token for compatibility.
  • Greedy fallback lookup uses precomputed default and preferred string key orders to avoid per-call bytestring conversions in URL generation hot paths.
  • Route.URL() returns ErrNotFound for empty/zero-value routes and returns route.Path when a route has no parsed segments.
  • Added and expanded tests covering direct app.GetRoute(name).URL(...) usage, case-sensitive and case-insensitive behavior, exact-match precedence, greedy + handling, default greedy fallback selection, and no-parser fallback routes.

Type of change

  • New feature (non-breaking change which adds functionality)
  • Enhancement (improvement to existing features and functionality)
  • Documentation update (changes to documentation)
  • Performance improvement (non-breaking change which improves efficiency)
  • Code consistency (non-breaking change which improves code reliability and robustness)

Checklist

Before you submit your pull request, please make sure you meet these requirements:

  • Followed the inspiration of the Express.js framework for new functionalities, making them similar in usage.
  • Conducted a self-review of the code and provided comments for complex or critical parts.
  • Updated the documentation in the /docs/ directory for Fiber's documentation.
  • Added or updated unit tests to validate the effectiveness of the changes or new features.
  • Ensured that new and existing unit tests pass locally with the changes.
  • Verified that any new dependencies are essential and have been agreed upon by the maintainers/community.
  • Aimed for optimal performance with minimal allocations in the new code.
  • Provided benchmarks for the new code to analyze and improve upon.

Commit formatting

Please use emojis in commit messages for an easy way to identify the purpose or intention of a commit. Check out the emoji cheatsheet here: CONTRIBUTING.md

@Claude Claude AI assigned Claude and gaby Apr 7, 2026
@Claude Claude AI linked an issue Apr 7, 2026 that may be closed by this pull request
3 tasks
@ReneWerner87 ReneWerner87 added this to v3 Apr 7, 2026
@ReneWerner87 ReneWerner87 added this to the v3 milestone Apr 7, 2026
This implements the feature requested in the issue to allow generating URLs from
named routes with parameter substitution. Users can now do:

  route := app.GetRoute("a-name")
  url, err := route.URL(Map{"name": "name-val"})
  // Returns: "/a/name-val"

The implementation:
- Added Route.URL() method that generates URLs by filling in route parameters
- Uses case-insensitive parameter matching (matching Fiber's default behavior)
- Supports all parameter types: named params, wildcards, and greedy params
- Added comprehensive test coverage with 11 test cases
- All quality checks pass (format, lint, test)

Agent-Logs-Url: https://github.com/gofiber/fiber/sessions/7256ea7c-dddf-4096-bb79-2fa6c3eefe39

Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
@Claude Claude AI changed the title [WIP] Fix GetRoute method to support path parameters 🔥 feat: Add URL() method to Route for generating URLs with parameters Apr 7, 2026
@Claude Claude AI requested a review from gaby April 7, 2026 05:20
Claude finished work on behalf of gaby April 7, 2026 05:20
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 7, 2026

Codecov Report

❌ Patch coverage is 91.37931% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.26%. Comparing base (676b2f7) to head (9b47da0).
⚠️ Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
router.go 92.85% 2 Missing and 2 partials ⚠️
res.go 50.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4195      +/-   ##
==========================================
+ Coverage   91.23%   91.26%   +0.02%     
==========================================
  Files         123      123              
  Lines       11847    11877      +30     
==========================================
+ Hits        10809    10839      +30     
  Misses        653      653              
  Partials      385      385              
Flag Coverage Δ
unittests 91.26% <91.37%> (+0.02%) ⬆️

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.

Copy link
Copy Markdown
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

Adds a new Route.URL(params Map) (string, error) API to generate relative URLs from a route’s parsed path segments by substituting route parameters, aligning with existing named-route URL generation patterns in the codebase.

Changes:

  • Introduces (*Route).URL() to build URLs from routeParser segments with parameter substitution (including wildcards/greedy params).
  • Adds unit tests for Route.URL() covering common parameter and wildcard cases.
  • Updates generated Ctx/Res interface docs for End() with a streaming-related note.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
router.go Adds Route.URL() implementation using routeParser segments and bytebuffer pooling.
router_test.go Adds Test_Route_URL subtests for parameter substitution behavior.
res_interface_gen.go Updates generated Res interface docs for End().
ctx_interface_gen.go Updates generated Ctx interface docs for End().

@gaby
Copy link
Copy Markdown
Member

gaby commented Apr 7, 2026

@copilot apply changes based on the comments in this thread

…ase sensitivity, revert generated files

Agent-Logs-Url: https://github.com/gofiber/fiber/sessions/b7a53bed-4d39-487b-8e01-9ecfe5d38b64

Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 7, 2026

@copilot apply changes based on the comments in this thread

Applied all review feedback in commit 26faa1d:

  1. Case sensitivity: Added caseSensitive field to Route, set at registration time from app.config.CaseSensitive and copied in copyRoute(). Route.URL() now respects this setting, consistent with getLocationFromRoute()/GetRouteURL().

  2. Deterministic lookup: Refactored to: exact key match → case-insensitive fallback (when !caseSensitive) → greedy parameter fallback (*/+). No more non-deterministic map iteration for matching.

  3. Case-sensitive test: Added "case sensitive" subtest using Config{CaseSensitive: true} that verifies exact match succeeds and mismatched case does not match.

  4. Generated files: Reverted unintended changes to ctx_interface_gen.go and res_interface_gen.go.

Copy link
Copy Markdown
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

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

@gaby
Copy link
Copy Markdown
Member

gaby commented Apr 7, 2026

@copilot apply changes based on the comments in this thread

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 7, 2026

@copilot apply changes based on the comments in this thread

Applied all three review comments in commit 6b37d8d:

  1. Nil guard (router.go:82): Route.URL() now checks r == nil before accessing fields, returning ErrNotFound — consistent with getLocationFromRoute().

  2. Deterministic case-insensitive fallback (router.go:105-115): When multiple keys case-fold to the same param name, the lexicographically-smallest key wins (via key < matchedKey), eliminating non-determinism from map iteration.

  3. Mounted route caseSensitive (router.go:442): addPrefixToRoute() now sets route.caseSensitive = app.config.CaseSensitive, so cloned sub-app routes adopt the parent app's case-sensitivity when re-parsed/registered.

Also added a "nil route" test case.

Copilot AI and others added 2 commits April 7, 2026 14:53
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 7, 2026

@copilot apply changes based on the comments in this thread

Applied the latest review feedback through commit 2e241ed.

This updates Route.URL/buildRouteURL to prefer + for plus segments before falling back to *, return route.Path when a route has no parsed segments, use route.caseSensitive consistently in getLocationFromRoute, add tests for plus/default greedy fallback behavior, and update the public docs in docs/api/app.md and docs/whats_new.md.

Copy link
Copy Markdown
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

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

@gaby
Copy link
Copy Markdown
Member

gaby commented Apr 8, 2026

@copilot apply changes based on the comments in this thread

Copilot AI and others added 2 commits April 8, 2026 11:25
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 8, 2026

@copilot apply changes based on the comments in this thread

Applied in 9b47da0. The greedy fallback lookup now uses precomputed string keys instead of converting bytes to strings inside the hot-path loop, and the default fallback order was renamed for clarity.

Copy link
Copy Markdown
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

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Copilot finished work on behalf of gaby April 8, 2026 13:43
@gaby gaby marked this pull request as ready for review April 8, 2026 13:48
@gaby gaby requested a review from a team as a code owner April 8, 2026 13:48
@gaby
Copy link
Copy Markdown
Member

gaby commented Apr 8, 2026

@copilot Your latest changes broke unit tests.

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 8, 2026

@copilot Your latest changes broke unit tests.

I investigated this before making any speculative changes. The exact workflow-style unit run (gotestsum -- ./... -race -count=1 -shuffle=on) passes locally on afc8c17, so the latest Route.URL receiver change does not reproduce a deterministic unit failure here. The only failure I could reproduce is in the repeated stress run (-count=15 -shuffle=on), where a pre-existing flaky test in the root package (Test_App_Test_Goroutine_Leak_Compare) trips intermittently; the CI logs also showed unrelated intermittent failures in other packages. I haven’t changed code based on this comment because I couldn’t tie a stable failing test to the Route.URL change.

Copilot finished work on behalf of gaby April 8, 2026 14:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

🤗 [Question]: app.GetRoute need set path param

5 participants