fix: set Request.Pattern from RoutePattern()#1097
Merged
VojtechVitek merged 1 commit intoMay 20, 2026
Merged
Conversation
Use the composed RoutePattern() value instead of the per-router routePattern field so nested routes populate http.Request.Pattern correctly on Go 1.23+. Fixes go-chi#1089
c6f5183 to
f01166b
Compare
ptman
approved these changes
May 20, 2026
VojtechVitek
approved these changes
May 20, 2026
| r.SetPathValue(key, value) | ||
| } | ||
| r.Pattern = rctx.routePattern | ||
| r.Pattern = rctx.RoutePattern() |
Contributor
There was a problem hiding this comment.
LGTM.
I realized that chi's route pattern might not map 1:1 with stdlib's (regex, * wildcards, no method prefix). But that's not a regression in this PR.
Thank you!
eleboucher
pushed a commit
to eleboucher/apoci
that referenced
this pull request
May 22, 2026
…(#49) This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) | `v5.2.5` → `v5.3.0` |  |  | --- ### Release Notes <details> <summary>go-chi/chi (github.com/go-chi/chi/v5)</summary> ### [`v5.3.0`](https://github.com/go-chi/chi/releases/tag/v5.3.0) [Compare Source](go-chi/chi@v5.2.5...v5.3.0) #### What's Changed - Use strings.ReplaceAll where applicable by [@​JRaspass](https://github.com/JRaspass) in [#​1046](go-chi/chi#1046) - Propagate inline middlewares across mounted subrouters by [@​LukasJenicek](https://github.com/LukasJenicek) in [#​1049](go-chi/chi#1049) - add go 1.26 to ci by [@​pkieltyka](https://github.com/pkieltyka) in [#​1052](go-chi/chi#1052) - Remove last uses of io/ioutil by [@​JRaspass](https://github.com/JRaspass) in [#​1054](go-chi/chi#1054) - Simplify chi.walk with slices.Concat by [@​JRaspass](https://github.com/JRaspass) in [#​1053](go-chi/chi#1053) - Apply the stringscutprefix modernizer by [@​JRaspass](https://github.com/JRaspass) in [#​1051](go-chi/chi#1051) - Bump minimum Go to 1.23, always use request.Pattern by [@​JRaspass](https://github.com/JRaspass) in [#​1048](go-chi/chi#1048) - middleware: fix httpFancyWriter.ReadFrom double-counting bytes with Tee by [@​alliasgher](https://github.com/alliasgher) in [#​1085](go-chi/chi#1085) - Fix typo in Route doc comment by [@​gouwazi](https://github.com/gouwazi) in [#​1073](go-chi/chi#1073) - fix: set Request.Pattern from RoutePattern() by [@​leno23](https://github.com/leno23) in [#​1097](go-chi/chi#1097) - feat: middleware.ClientIP, a replacement for middleware.RealIP by [@​VojtechVitek](https://github.com/VojtechVitek) in [#​967](go-chi/chi#967) #### New Contributors - [@​LukasJenicek](https://github.com/LukasJenicek) made their first contribution in [#​1049](go-chi/chi#1049) - [@​alliasgher](https://github.com/alliasgher) made their first contribution in [#​1085](go-chi/chi#1085) - [@​gouwazi](https://github.com/gouwazi) made their first contribution in [#​1073](go-chi/chi#1073) - [@​leno23](https://github.com/leno23) made their first contribution in [#​1097](go-chi/chi#1097) #### SECURITY: middleware.ClientIP, a replacement for middleware.RealIP PR [#​967](go-chi/chi#967) introduced `middleware.ClientIP`, a replacement for `middleware.RealIP` that closes the three open spoofing advisories: - [GHSA-9g5q-2w5x-hmxf](GHSA-9g5q-2w5x-hmxf) — IP spoofing via XFF in `RemoteAddr` resolution (convto) - [GHSA-rjr7-jggh-pgcp](GHSA-rjr7-jggh-pgcp) — RealIP allows IP spoofing via unvalidated XFF (rezmoss) - [GHSA-3fxj-6jh8-hvhx](GHSA-3fxj-6jh8-hvhx) — IP spoofing in `middleware.RealIP` (Saku0512, Critical / 9.3) It also addresses issues outlined at: - [#​708](go-chi/chi#708) - <https://adam-p.ca/blog/2022/03/x-forwarded-for/> - [#​711](go-chi/chi#711) - [#​453](go-chi/chi#453) - [#​908](go-chi/chi#908) `middleware.RealIP` is deprecated in this PR with pointers to the new API. The deprecation only adds a `// Deprecated:` doc comment; the function keeps working for backward compatibility. ##### Why a new middleware (not "fix RealIP in place") `RealIP` has two unfixable design choices: it mutates `r.RemoteAddr`, and it tries to be a one-size-fits-all default by walking a hard-coded list of headers any client can supply. Per [adam-p's "The perils of the 'real' client IP"](https://adam-p.ca/blog/2022/03/x-forwarded-for/) (which calls chi out by name on this), there is no safe default — the user must pick their trust source explicitly. ##### The new API Four middlewares, two accessors. Pick exactly one middleware based on your infrastructure, read the result with one of the two accessors: ```go // One of the four. There is no safe default — pick exactly one. func ClientIPFromHeader(trustedHeader string) func(http.Handler) http.Handler func ClientIPFromXFF(trustedIPPrefixes ...string) func(http.Handler) http.Handler func ClientIPFromXFFTrustedProxies(numTrustedProxies int) func(http.Handler) http.Handler func ClientIPFromRemoteAddr(h http.Handler) http.Handler // Read the result. func GetClientIP(ctx context.Context) string // for logs, rate-limit keys func GetClientIPAddr(ctx context.Context) netip.Addr // for typed work ``` #### Example usage: ```go // Pick a single ClientIP middleware based on your deployment // Cloudflare. r.Use(middleware.ClientIPFromHeader("CF-Connecting-IP")) // Nginx with ngx_http_realip_module. r.Use(middleware.ClientIPFromHeader("X-Real-IP")) // Apache with mod_remoteip. r.Use(middleware.ClientIPFromHeader("X-Client-IP")) // AWS CloudFront, or any proxy fleet with known CIDRs. r.Use(middleware.ClientIPFromXFF( "13.32.0.0/15", // CloudFront IPv4 "52.46.0.0/18", // CloudFront IPv4 "2600:9000::/28", // CloudFront IPv6 )) // Behind exactly 2 trusted proxies with dynamic IPs (autoscaling pools, // ephemeral containers, dynamic CDN edges). r.Use(middleware.ClientIPFromXFFTrustedProxies(2)) // Server directly on the public internet, no proxy in front. r.Use(middleware.ClientIPFromRemoteAddr) ``` And in your handler or downstream middleware: ```go clientIP := middleware.GetClientIP(r.Context()) // log it, use it as a rate-limit key, etc. ``` *** Thanks to [@​adam-p](https://github.com/adam-p), [@​c2h5oh](https://github.com/c2h5oh), [@​rezmoss](https://github.com/rezmoss), [@​Saku0512](https://github.com/Saku0512), [@​convto](https://github.com/convto), [@​Dirbaio](https://github.com/Dirbaio), [@​jawnsy](https://github.com/jawnsy), [@​lrstanley](https://github.com/lrstanley), [@​mfridman](https://github.com/mfridman), [@​n33pm](https://github.com/n33pm), [@​pkieltyka](https://github.com/pkieltyka) for the prior discussions, detailed reviews, advisory reports, and test contributions that shaped this PR. **Full Changelog**: <go-chi/chi@v5.2.5...v5.3.0> </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJ0eXBlL21pbm9yIl19--> Reviewed-on: https://git.erwanleboucher.dev/eleboucher/apoci/pulls/49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On Go 1.23+,
http.Request.Patternis now populated with the full composed route pattern fromRouteContext.RoutePattern()instead of the per-sub-routerroutePatternfield.Tests
TestPatternwith a nested sub-router case (/accounts/{accountID}/hi).Fixes #1089
Made with Cursor