我在 /find/Wrocław "\xC5" 从 ASCII-8BIT 到 UTF-8 得到 Encoding::UndefinedConversionError
出于某种神秘的原因,sinatra 将字符串作为 ASCII 而不是 UTF-8 传递,因为它应该。
我发现了某种丑陋的解决方法...我不知道为什么 Rack 假设编码是 ASCII-8BIT ...无论如何,一种方法是使用 string.force_encoding("UTF-8")... 但是做这对所有参数来说都很乏味
我在路由到“/protégés/:id”时遇到了一些类似的问题。我张贴到机架邮件列表,但反应不是很好。
我想出的解决方案并不完美,但它适用于大多数情况。首先,创建一个取消编码 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 或 Web 服务器中进行设置,具体取决于您在站点上使用的不同编码。
AFAIK 你不应该在 URL 中有原始的 UTF-8 字符,但必须对它们进行 % 编码,不这样做可能会导致各种问题,比如符合标准的代理。看起来这不是机架问题,而是应用程序发出无效 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 ”。