Rails 路由约束和 UTF-8

Posted

技术标签:

【中文标题】Rails 路由约束和 UTF-8【英文标题】:Rails Routing Constraints and UTF-8 【发布时间】:2013-09-25 04:31:54 【问题描述】:

我需要处理像/:slug 这样的路由。蛞蝓被限制在其他地方以匹配:

\A[\pAlnum_.-]3,\z

明显的路线:

get '/:slug' => '...', :constraints =>  :slug => /[\pAlnum_.-]3,/ 
get '/:slug' => '...', :slug => /[\pAlnum_.-]3,/

使用/mu-is-too-short/where.is.pancakes.house 等ASCII URL 可以正常工作,但是当URL 为/µ-is-too-short 时,一切都会崩溃。浏览器将其发送到服务器:

/%C2%B5-is-too-short

Rails 正在尝试根据:slug 约束检查编码的%C2%B5-is-too-short 并失败,因为% 不是\pAlnum

我想出了两个组合:

get '/:slug' => '...', :slug => /.3,/
get '/:slug' => '...', :slug => /[^\/]+/, :constraints => lambda  |r| r.path_parameters[:slug].to_s =~ /\A[\pAlnum_.-]3,\z/ 

第二个中的:slug => /[^\/]+/ 用于防止Rails 认为a.b 中的.b 是格式扩展。

有没有办法让 Rails 表现得合理,并根据约束检查解码的:slug,还是我必须放松约束或手动执行?

【问题讨论】:

所以问题基本上是与约束匹配的参数没有被url解码,对吗? @MichaelSzyndel:是的。 Rails 确实在r.path_parameters[:slug] 中有解码值,但它似乎没有将它用于约束检查。我只需要在第二个中添加:slug => /[^\/]+/ 即可让Rails 正确提取带有. 的slug,这暗示了一些关于解析顺序的事情。 看你的问题很明显,但我只是想清除它。我尝试查看 Rails 路由代码并放弃了。 我正在考虑制作一个匹配所有允许的字母/符号的正则表达式,但在 utf-8 空间中太复杂了。黑名单看起来也不是很有希望。 你可能对 Rails 5 感兴趣,它接受路径名、文件名等中的 utf-8 字符。如果没有,则尝试查找 mew 字符的 HEX 转换,而 ruby​​ 会处理它 【参考方案1】:

您可以使用 lambda 作为约束,这样可以更改编码(来自 http://www.intridea.com/blog/2011/2/21/use-lambdas-for-rails3-route-constraints):

scope :constraints => lambda|req| !req.session[:user_id].blank?  do
  # all my logged in routes
end

【讨论】:

这只是我的第二个伪装 (:constraints => lambda |r| ... )。我正在寻找一种方法来说服 Rails 做出明智的行为,并根据它已经拥有的解码路径检查约束。

以上是关于Rails 路由约束和 UTF-8的主要内容,如果未能解决你的问题,请参考以下文章

从 Rails 6 中的 bin/rails 路由中省略操作邮箱、活动存储和导体路由?

7--Rails路由

Rails 3 的动态路由

Rails 路由接受 http 和 json 请求

GET 和 POST 请求的相同 Rails 4 路由

使用类型和值约束 约束路由