发送到服务器的Unicode字符作为垃圾返回

时间:2013-10-30 03:00:02

标签: ruby unicode utf-8 sinatra emoji

更新经过进一步调查后,我设法将问题缩小到了json编码器。直接传递输入工作正常,但通过MultiJson.encode是导致问题的原因。

我通过curl将以下内容发送到一个安静的网络服务:

$ curl -v -X POST "http://my/url" -d "{\"body\": \"\"}"

您可能无法看到的字符是Credit Card表情符号字符,即U + 1F4B3。

我从服务中得到的回复主要是:

< HTTP/1.1 200 OK
< Date: Wed, 30 Oct 2013 02:38:04 GMT
< Content-Type: application/json;charset=utf-8
< Content-Length: 266
< Connection: close
< 
{ [data not shown]
100   304  100   266  100    38    936    133 --:--:-- --:--:-- --:--:--   936
* Closing connection 0
{
  "body": "\uf4b3"
}

这个编码字符与我发送的字符不符,我希望它会在发送时返回(在这种情况下)。

我可以访问服务器的源代码。它建立在Ruby,Sinatra和ActiveRecord之上。在发送响应之前会进行一些处理:

  • 首先,内容通过ERB::Util.html_escape
  • 传递
  • 然后,通过str.gsub!(reg, " ### ")
  • 应用一系列正则表达式
  • 最后,通过MultiJson.encode
  • 返回回复

我不是Ruby人员,但可以在必要时提供其他详细信息。希望有人指点我正确的方向。谢谢!

2 个答案:

答案 0 :(得分:0)

要检查的第一件事是角色是否以您认为的方式“进入”应用程序的主体。 Ruby有一个默认的“内部”和“外部”编码的概念。一旦字符串通过各种IO进入,由于各种原因,它可能会或可能没有预期的编码,因为它传递。

这并不是说难以管理或混淆 - 这一切都非常简单,但我只是指出所有这些事情都可以配置/改变。

要查看您的内容,请在程序中尽快输入,检查其编码。

params[:foo].encoding
=> #<Encoding:UTF-8>

如果不是utf-8,那么您需要将环境和/或IO机制设置为使用utf-8。

从ruby 2.0开始,默认编码是 - 赞美众神 - utf8。因此,如果您不使用ruby 2.0并且能够从升级到此开始。

如果您没有该选项,则需要设置默认编码。虽然it seems sinatra sets it to utf-8

答案 1 :(得分:0)

我们能够通过迁移到不同的JSON编码引擎来解决这个问题:

get "/foo" do
    resp = ""

    puts MultiJson.adapter()
    puts MultiJson.dump(resp) # Fails

    MultiJson.engine = :jrjackson
    puts MultiJson.adapter()
    puts MultiJson.dump(resp) # Succeeds
end