Sinatra / Rack在url中使用非ascii字符失败

时间:2009-12-22 18:17:34

标签: ruby sinatra rack

我在/ find /Wrocław得到了Encoding :: UndefinedConversionError “\ xC5”从ASCII-8BIT到UTF-8

出于某种神秘的原因,sinatra将字符串传递为ASCII而不是UTF-8。

我找到了某种丑陋的解决方法......我不知道为什么Rack假设编码是ASCII-8BIT ...无论如何,一种方法是使用string.force_encoding(“UTF-8”)..但是对所有参数都这样做很乏味

2 个答案:

答案 0 :(得分:3)

我在路由到“/protégés/:id”时遇到了类似的问题。我posted到了Rack邮件列表,但响应不是很好。

我提出的解决方案并不完美,但它适用于大多数情况。首先,创建一个不使用UTF-8编码的中间件:

# in lib/fix_unicode_urls_middleware.rb:
require 'cgi'
class FixUnicodeUrlsMiddleware
  ENVIRONMENT_VARIABLES_TO_FIX = [
    'PATH_INFO', 'REQUEST_PATH', 'REQUEST_URI'
  ]

  def initialize(app)
    @app = app
  end

  def call(env)
    ENVIRONMENT_VARIABLES_TO_FIX.each do |var|
      env[var] = CGI.unescape(env[var]) if env[var] =~ /%[A-Za-z0-9]/
    end
    @app.call(env)
  end
end 

然后在config/environment.rb(Rails 2.3)或config/application.rb(Rails 3)中使用该中间件。

您还必须确保设置正确的HTTP标头编码:

Content-type: text/html; charset=utf-8

您可以在Rails,Rack或网络服务器中进行设置,具体取决于您在网站上使用的编码数量。

答案 1 :(得分:2)

AFAIK你不应该在URL中有原始的UTF-8字符,但必须对它们进行%编码 不这样做可能会导致标准兼容代理的所有问题。看起来它不是Rack问题,而是应用程序发出无效URL的问题。 HTTP标头中的字符集和编码信息适用于内容而不是标头本身。

引用RFC 3986

  

当新的URI方案定义表示由通用字符集[UCS]中的字符组成的文本数据的组件时,应首先根据UTF-8字符编码[STD63]将数据编码为八位字节;那么只有那些与未保留集合中的字符不对应的八位字节应该进行百分比编码。例如,字符A将表示为“A”,字符LATIN CAPITAL LETTER A WITH GRAVE将表示为“%C3%80”,字符KATAKANA LETTER A将表示为“%E3%82%A2 ”