#642·chi

URL 参数转义的问题以及修复建议

作者: nawa创建于 2021年7月22日更新于 2025年12月10日
标签url-params

The initial issue

I faced issues with URL param escaping. I can show them using two examples, but there could be more. So, clients can send two requests to the server with the following path

  • /api/first%25%20second - it is a usual path in which all symbols that need to be escaped are escaped
  • /api/first%20(second) - it is the case of how Chrome/Firefox/Safari escape URL in the address bar or using encodeURI(). Parentheses are not escaped, but Go escaping algo expects that they are Then I'm trying to read the variable param using the pattern /api/{param} with URLParam(r, name) and expecting that
    request URL Expected param Actual param
    /api/first%25%20second first% second first% second
    /api/first%20(second) first (second) first%20(second)

The first case passed correctly but in the second case I read first%20(second) instead of first (second). The main misunderstanding - what I need to do in handlers, do I need to unescape params myself or not, why sometimes params are still escaped?

Example: https://GitHub.com/nawa/chi/commit/b0c424038f640e0d72035edea75ed06589dc5ce0 Having escaped params, I'm assuming that I have to unescape them myself and trying to do that https://GitHub.com/nawa/chi/commit/11ccf398f5bea11486dfbc10f3777f508ba385f7 After that, I see opposite results - the second case passed because first%20(second) is unescaped to first (second) correctly. But the first case failed at all because the string first% second is incorrect to unescape and url.PathUnescape(URLParam(r, name)) returns error So, as you can see client can't easily determine how to read the correct value

Workaround for the initial issue

Seems that I found a workaround that I'm using now in my handlers to read all URL params

go
value := URLParam(r, name)
if r.URL.RawPath != "" {
	value, _ = url.PathUnescape(value) // it is better to handle error
}

return value

See full workaround and more test cases - https://GitHub.com/nawa/chi/commit/00f16715671c0749031abb98468af44d1192ff19

Solutions resolving the issues

Described inconsistency should be resolved in chi and it should give a clear understanding to the client - does he always need to unescape params or not

1. All URL params are UNESCAPED in the router and client doesn't need to unescape them. All methods impact benchmarks and contain breaking changes

First method

https://GitHub.com/nawa/chi/commit/92c5ba66d2b99e8799c5a93b5088322b2b6ed1ee Benchmarks comparison

enchmark                                               old ns/op     new ns/op     delta
BenchmarkMux/route:/-8                                  345           353           +2.44%
BenchmarkMux/route:/hi-8                                368           380           +3.29%
BenchmarkMux/route:/sup/123/and/this-8                  479           584           +21.94%
…