{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/14815","repository_url":"https://api.github.com/repos/golang/go","labels_url":"https://api.github.com/repos/golang/go/issues/14815/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/14815/comments","events_url":"https://api.github.com/repos/golang/go/issues/14815/events","html_url":"https://github.com/golang/go/issues/14815","id":140696879,"number":14815,"title":"net/http: ServeMux uses URL.Path instead of URL.EscapedPath(), leading it to treat %2F as a path separator","user":{"login":"gelraen","id":654649,"avatar_url":"https://avatars.githubusercontent.com/u/654649?v=3","gravatar_id":"","url":"https://api.github.com/users/gelraen","html_url":"https://github.com/gelraen","followers_url":"https://api.github.com/users/gelraen/followers","following_url":"https://api.github.com/users/gelraen/following{/other_user}","gists_url":"https://api.github.com/users/gelraen/gists{/gist_id}","starred_url":"https://api.github.com/users/gelraen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gelraen/subscriptions","organizations_url":"https://api.github.com/users/gelraen/orgs","repos_url":"https://api.github.com/users/gelraen/repos","events_url":"https://api.github.com/users/gelraen/events{/privacy}","received_events_url":"https://api.github.com/users/gelraen/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/golang/go/milestones/6","html_url":"https://github.com/golang/go/milestones/Unplanned","labels_url":"https://api.github.com/repos/golang/go/milestones/6/labels","id":1055141,"number":6,"title":"Unplanned","description":"No plan to fix in any specific release.\r\n","creator":{"login":"rsc","id":104030,"avatar_url":"https://avatars.githubusercontent.com/u/104030?v=3","gravatar_id":"","url":"https://api.github.com/users/rsc","html_url":"https://github.com/rsc","followers_url":"https://api.github.com/users/rsc/followers","following_url":"https://api.github.com/users/rsc/following{/other_user}","gists_url":"https://api.github.com/users/rsc/gists{/gist_id}","starred_url":"https://api.github.com/users/rsc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rsc/subscriptions","organizations_url":"https://api.github.com/users/rsc/orgs","repos_url":"https://api.github.com/users/rsc/repos","events_url":"https://api.github.com/users/rsc/events{/privacy}","received_events_url":"https://api.github.com/users/rsc/received_events","type":"User","site_admin":false},"open_issues":1233,"closed_issues":306,"state":"open","created_at":"2015-04-06T20:47:19Z","updated_at":"2016-03-30T00:24:15Z","due_on":"2099-12-31T05:00:00Z","closed_at":null},"comments":7,"created_at":"2016-03-14T14:53:47Z","updated_at":"2016-03-30T13:52:04Z","closed_at":null,"body":"Please answer these questions before submitting your issue. Thanks!\r\n\r\n1. What version of Go are you using (`go version`)?\r\n`go version go1.6 darwin/amd64`\r\n\r\n3. What did you do?\r\nhttp://play.golang.org/p/60StDlOnw8\r\nIt doesn't work on play.golang.org, but when you run it on local machine it results in:\r\n```\r\n2016/03/14 14:40:10 http: panic serving 127.0.0.1:58546: /a/b\r\n```\r\n\r\n\r\n4. What did you expect to see?\r\nI 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`\r\n\r\nThis 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.\r\n\r\nI suggest one of these ways to fix this:\r\n1) Make `net/url` percent-decode only unreserved characters, making it compliant with RFC3986\r\n2) Use `EscapedPath()` in `http.ServeMux`, so it will see the data before `net/url` spoiled it\r\n\r\nBoth options (and probably any other) break API in one way or another.\r\n\r\nYes, I saw the response on https://github.com/golang/go/issues/8248 that this is documented behavior, but it directly contradicts relevant Internet standard, so it's worth to be changed."},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/203443273","html_url":"https://github.com/golang/go/issues/14815#issuecomment-203443273","issue_url":"https://api.github.com/repos/golang/go/issues/14815","id":203443273,"user":{"login":"rsc","id":104030,"avatar_url":"https://avatars.githubusercontent.com/u/104030?v=3","gravatar_id":"","url":"https://api.github.com/users/rsc","html_url":"https://github.com/rsc","followers_url":"https://api.github.com/users/rsc/followers","following_url":"https://api.github.com/users/rsc/following{/other_user}","gists_url":"https://api.github.com/users/rsc/gists{/gist_id}","starred_url":"https://api.github.com/users/rsc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rsc/subscriptions","organizations_url":"https://api.github.com/users/rsc/orgs","repos_url":"https://api.github.com/users/rsc/repos","events_url":"https://api.github.com/users/rsc/events{/privacy}","received_events_url":"https://api.github.com/users/rsc/received_events","type":"User","site_admin":false},"created_at":"2016-03-30T13:52:04Z","updated_at":"2016-03-30T13:52:04Z","body":"I understand the issue you are having, but I don't think we can change\nanything today. http.ServeMux is defined to issue certain redirects back to\nthe client and it is doing that (the request for /a/b%2f%2fc redirects the\nclient to /a/b/c; that second request is what your handler sees). If you\nneed to get in ahead of http.ServeMux and prevent the defined redirects,\nthe way to do that today is to define your own mux in front of it and pass\nthat to http.Serve or http.ListenAndServe.\n\nOn Wed, Mar 30, 2016 at 4:53 AM Maxim Ignatenko <notifications@github.com>\nwrote:\n\n> Okay, then what do you think about making http.ServeMux use EscapedPath()\n> ? Cause my issue right now is that after passing through http.ServeMux\n> information I need is not preserved even in RawPath.\n>\n> —\n> You are receiving this because you were mentioned.\n> Reply to this email directly or view it on GitHub\n> <https://github.com/golang/go/issues/14815#issuecomment-203328530>\n>\n"}}