-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net/http: ServeMux uses URL.Path instead of URL.EscapedPath(), leading it to treat %2F as a path separator #14815
Comments
This comes up repeatedly in various forms, but compatibility and not breaking old programs likely prevents us from doing anything here. Any such proposal needs to be thoroughly investigated to consider its impact on existing programs. /cc @rsc for any opinions. |
I can hardly imagine an application that would rely on %2F to be decoded and used as path separator. In most cases you either don't care about those weirdos sending you requests with %2F or want it to be preserved as is and not used as path separator. But that's just my opinion based on a very limited sample. |
You cannot just leave the %2F's in place, because that will encourage people to unescape the URL.Path again, which will lead to double-unescaping problems. And you do need to unescape the other things. You do want /%78yz to turn into /xyz. Also if you decide not to unescape %2F then you also can't unescape %252F, and because you're not unescaping that, you can't unescape %25252F, or %2525252F, and so on. It gets into a rathole pretty quickly. And if we started doing this all of a sudden then you'd have to worry about people seeing %2F and not knowing if it was a preserved %2F or a decoded %252F being process by an earlier version of Go. There are no good answers here. Fundamentally, the idea of 'Path string' is at odds with the "internet standard". It should have been 'Path []string' and people who wanted the full path would have to strings.Join(u.Path, "") or something like that. But obviously we can't do that now. For now I think we should just leave things alone. In the long term I think very limited wildcard support in ServeMux might help provide an API with the convenience of the single string form and still have the ability to pull out these kinds of mangled paths from individual elements. I wrote more about this at https://www.reddit.com/r/golang/comments/46bd5h/ama_we_are_the_go_contributors_ask_us_anything/d05lewi. The workaround is to pass your own handler to Serve or ListenAndServe and have that handler pick off the %2F paths you care about before handing the rest to ServeMux. One reason the root handler is just an http.Handler instead of a ServeMux is so that you can do this when it is necessary. (Sadly, this unexpected usage of REST has made it more necessary than we anticipated.) |
True. However, RFC3986 defines a concept of equivalence, which goes as far as unescaping unreserved characters. Problem with It is possible to preserve equivalence while mapping URL paths to string values by unescaping only unreserved characters (and "%" is not unreserved, it's funny^Wannoying that "reserved" + "unreserved" sets don't cover full ASCII), and then having
I totally agree that unescaping (more precisely – normalization https://tools.ietf.org/html/rfc3986#section-6 ) is very useful and simplifies user code, but it was taken a bit too far and now it's too late to fix it in-place without breaking someone's code.
In my case it doesn't mess the routing (i.e. it invokes the exact handler I want it to), but once it does, there's already no way to distinguish between
How about adding It's also possible to add it as
Yeah, for now I'm stuck with my own clone of |
I don't think we're going to add more complexity to url.URL now. RawPath suffices to preserve all the information one might need to derive or need control over. As of Go 1.5, clients in this (not everyday) situation can build what they need from the pieces provided. When it's time for a rethink of the overall big picture, we'll be sure to consider this. But I'd rather not add more piecemeal. |
Okay, then what do you think about making |
I understand the issue you are having, but I don't think we can change On Wed, Mar 30, 2016 at 4:53 AM Maxim Ignatenko [email protected]
|
Please answer these questions before submitting your issue. Thanks!
go version
)?go version go1.6 darwin/amd64
http://play.golang.org/p/60StDlOnw8
It doesn't work on play.golang.org, but when you run it on local machine it results in:
I expected HTTP handler to get a request with URL equivalent to URL in original request, i.e.
/a%2F%2Fb
. Per https://tools.ietf.org/html/rfc3986#section-2.2/a/b
and even/a//b
are NOT EQUIVALENT to/a%2F%2Fb
This happens because
http.ServeMux
uses URL.Path, which already contains wrong data/a//b
, does some normalization on that and issues a redirect to/a/b
, so user handler is never invoked during the initial request, only after this redirect.I suggest one of these ways to fix this:
net/url
percent-decode only unreserved characters, making it compliant with RFC3986EscapedPath()
inhttp.ServeMux
, so it will see the data beforenet/url
spoiled itBoth options (and probably any other) break API in one way or another.
Yes, I saw the response on #8248 that this is documented behavior, but it directly contradicts relevant Internet standard, so it's worth to be changed.
The text was updated successfully, but these errors were encountered: