EscapedPath() sometimes re-generates the escaped path, especially if the original path contains unencoded characters like Ñ or literal spaces. When it does this reconstruction, it works from the decoded path segments, which is likely why the original %2F encoding was lost in your example. This seems to be intentional—and probably a valid interpretation of RFC 3986, even if one with side effects.
I also came across a related issue, and the solution ended up being a major API change—switching to query parameters in our case. The cloud provider was escaping the path exactly as you described before it hit our backend. (So maybe reconsider whether you really want to use EscapedPath() if you're building a proxy or router.) That said, I'm sorry I only have a workaround to offer. Here's one: ```go func check(original string) { u, err := url.ParseRequestURI(original) noerr(err) escapedPath := u.EscapedPath() hasEncodedSlash := strings.Contains(strings.ToLower(original), "%2f") isCrafted := hasEncodedSlash && (original != escapedPath) fmt.Println("Original path: ", original) fmt.Println("Escaped path: ", escapedPath) fmt.Println("Anomaly Detected:", isCrafted) fmt.Println() } ``` If someone knows a better fix, I'd really appreciate hearing it. Am Mi., 30. Apr. 2025 um 00:08 Uhr schrieb Diego Augusto Molina < diegoaugustomol...@gmail.com>: > Errata: In the second HTTP example I gave: > > HTTP /x%2Fx HTTP/1.1 > Host example.com > > EscapedPath() will return "/x%2Fx", not "/%2F". > > Kind regards, > > On Tuesday, 29 April 2025 at 18:58:59 UTC-3 Diego Augusto Molina wrote: > >> Hi everyone, thank you in advance for reading. >> >> I was trying to use EscapedPath() to do path-based routing in an HTTP >> server, where some requests need to be forwarded to another service. I >> found that an invalid character in some parts of the path of the Request >> URI passed in the HTTP Request Line would not cause an error, but instead >> would be silently accepted and when I had to forward the request then I >> would be forwarding something I wasn't expecting to. >> >> When the path contains all valid path characters then using EscapedPath() >> and String() methods work as (I would have) expected, and I can do things >> like path.Clean to remove "..", ".", and "/////" from the path. But if I >> put something like "Ñ" in the path, then EscapedPath() (and String(), as it >> calls EscapedPath()) will interpret other %-encoded sequences in the passed >> path. So if I send an HTTP request like: >> >> HTTP /x%2Fx HTTP/1.1 >> Host example.com >> >> Then EscapedPath() will return "/%2F", which is to say a path with a >> single path element: "x/x". But if I send a request like: >> >> HTTP /Ñ%2FÑ HTTP/1.1 >> Host example.com >> >> Then EscapedPath() will return "/%C3%91/%C3%91", which is to say a path >> with two path elements: "Ñ" and "Ñ", whereas I would expect a parsing >> error and no handler being called. Note also that my "%2F" was interpreted. >> When forwarding the request to another service, this could be a problem >> because it's interpreting user input and the user could potentially >> traverse the proxied service. >> >> Here is a small Playground to illustrate: >> https://go.dev/play/p/ySJwVtvHHQF >> >> I thought of a few workarounds on the language-user side: >> >> 1. Manually writing a validator to know if the path is valid and >> return an error. Prone to error. >> 2. "go:linkname ...validEncoded" instead of writing my own. >> Definitely not on my plans. >> 3. Set RawPath to the empty string, and live with the fact that the >> user can send a %2F and that it will be interpreted as a literal "/" >> separating path elements, but as long as every part of the program and all >> systems that do something different based on the path see the same thing, >> then that's probably better. >> >> >> I read the code in Chi and Gin router libraries to see if others had the >> same problem, and both of them appear to have related issues reported, but >> so far it appears to be a contentious or otherwise unresolved subject. The >> following are probably related: >> >> - https://github.com/go-chi/chi/issues/641 >> - https://github.com/go-chi/chi/issues/642 >> - https://github.com/go-chi/chi/issues/832 >> - https://github.com/gin-gonic/gin/issues/4033 >> >> Here is also a related reddit thread: >> https://www.reddit.com/r/golang/comments/1gbcgpx/confused_about_urlpath_urlrawpath_and/?rdt=64426 >> >> Note that I took the assumption on what is "valid" based on my >> interpretation of RFC 3986 "Uniform Resource Identifier (URI): Generic >> Syntax" §3.3 (https://www.rfc-editor.org/rfc/rfc3986#section-3.3), which >> is also mentioned in the source code of the package. >> >> Please, let me know your thoughts, if I'm missing anything, or if there >> are better alternatives. >> >> Thank you. >> > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion visit > https://groups.google.com/d/msgid/golang-nuts/c4ffe669-cfbd-4774-a327-6ec8c974fdccn%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/c4ffe669-cfbd-4774-a327-6ec8c974fdccn%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/CAC4E5ZngBQ4KNJSQdaRsM80WpWDP_hdiL8hLF9NvzyTFvgVuuA%40mail.gmail.com.