从Rails 3.0.3中的URL正确Unescape特殊字符

时间:2012-01-17 03:11:47

标签: ruby-on-rails ruby activerecord encoding escaping

我正在使用Rails 3.0.3和REE(Ruby 1.8.7)和gem'mysql2','0.2.6'

我的项目中有一个搜索功能,可以让人们使用URL或使用表单来使用GET方法,然后生成URL。

示例:

我想搜索:

起源城市:“Århus,丹麦”和目的地城市:“亚松森,巴拉圭

他们都有一个特殊字符:“Å”和“ó”,因此当有人点击搜索按钮时,会生成这样的URL。

?&origin=%C5rhus%2C%20Denmark&destination=Asunci%F3n%2C%20Paraguay

问题:

当我搜索那个城市时,它并没有像我想要的那样(我尝试使用像CGI,URI,甚至一些宝石)。

当我在控制台看到时,ActiveRecord收到了这样的查询:

Parameters: {"destination"=>"Asunci�n, Paraguay", "origin"=>"�rhus, Denmark", "sort"=>"newest"}
City Load (0.1ms)  SELECT `cities`.* FROM `cities` WHERE (`cities`.`name` = '�rhus') ORDER BY cities.name ASC
City Load (6.8ms)  SELECT `cities`.* FROM `cities` WHERE (`cities`.`name` = 'Asunci�n, Paraguay') ORDER BY cities.name ASC

结论:无法找到城市 :(

但是,我发现了一件有趣的事情:

  • 当我对与此函数关联的文件出错时,输出将如下:

    请求

    Parameters:
    {"destination"=>"Asunción,
    Paraguay",
    "origin"=>"Århus,
    Denmark",
    "sort"=>"newest"}
    

这是一个有效的!

问题:

你们有个想法如何解决这个问题吗?在此先感谢:)

1 个答案:

答案 0 :(得分:12)

你是对的,看起来你某处有编码问题。 0xC5字符在ISO-8859-1 (AKA Latin-1)中为“Å”,在UTF-8中,它在URL中为%C3%85

我怀疑您在客户端使用JavaScript并且您的JavaScript使用old escape函数来构建URL,escape存在一些非ASCII字符问题。如果是这种情况,那么您应该将JavaScript升级为使用encodeURIComponent。看看这个小小的演示,你会看到我在说什么:

  

http://jsfiddle.net/ambiguous/U5A3k/

如果您无法更改客户端脚本,那么您可以使用force_encodingencoding在Ruby中以艰难的方式执行此操作:

>> s = CGI.unescape('%C5rhus%2C%20Denmark')
=> "\xC5rhus, Denmark"
>> s.encoding
=> #<Encoding:UTF-8>
>> s.force_encoding('iso-8859-1')
=> "\xC5rhus, Denmark"
>> s.encoding
=> #<Encoding:ISO-8859-1>
>> s.encode!('utf-8')
=> "Århus, Denmark"
>> s.encoding
=> #<Encoding:UTF-8>

你应该从"\xC5rhus, Denmark"获得类似params的内容,你可以通过以下方式解决这个问题:

s = params[:whatever].force_encoding('iso-8859-1').encode('utf-8')

在服务器端处理此问题将是最后的手段,但如果您的客户端代码发送回错误编码的数据,那么您将在服务器上留下一堆猜测来确定实际编码是什么用于将其放入网址。