Rails JSON请求未正确解析为post参数

col*_*lin 16 internet-explorer json cors ruby-on-rails-3

我正在尝试调试Rails没有解码JSON POST数据的问题.

服务器日志显示:

2011-12-14T06:44:44+00:00 app[web.2]: Started POST 
2011-12-14T06:44:44+00:00 app[web.2]:   Processing by PostsController#create as */*
2011-12-14T06:44:44+00:00 app[web.2]:   Parameters: {"{\"athlete_id\":\"\",\"known_as\":\"abc\",\"email\":\"abc@defg.com\",\"result\":\"112233\",\"rx\":false,\"mods\":\"thkjth\",\"notes\":\"\"}"=>nil, "affiliate_id"=>"testaffiliate", "wod_id"=>"12345"}
Run Code Online (Sandbox Code Playgroud)

请注意,JSON字符串未被解析--Rails将其指定为散列中的键,指向nil值.在我写一个尝试JSON.parse所有params键的before_filter之前,有没有人有任何想法?

我不认为这是相关的,因为我发送和接收数据没问题,但是这个问题发生在来自IE的CORS请求期间(使用XDomainRequest).

小智 17

您可以通过将Content-Type标头设置为"application/json"来解决此问题.您可以让Accept控制器知道它要返回的内容,并将Accept标头设置为"application/json".

以下命令包含两个标头:

curl -d '{ "company": { "name": "acme", "address": "123 Carrot Street" } }' http://0.0.0.0:3000/mysite --header "Accept: application/json" --header "Content-Type: application/json"
Run Code Online (Sandbox Code Playgroud)

在日志中生成:

Started POST "/mysite" for 127.0.0.1 at 2012-01-11 16:09:48 -0800
  Processing by MyController#create as JSON
  Parameters: {"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "wassup"=>{"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "controller"=>"wassup", "action"=>"create"}}
Completed 200 OK in 5ms (Views: 2.0ms | ActiveRecord: 0.0ms)
Run Code Online (Sandbox Code Playgroud)

带有Accept标头的此命令:

curl -d '{ "company": { "name": "acme", "address": "123 Carrot Street" } }' http://0.0.0.0:3000/mysite --header "Accept: application/json"
Run Code Online (Sandbox Code Playgroud)

生成这些日志:

Started POST "/mysite" for 127.0.0.1 at 2012-01-11 16:07:26 -0800
  Processing by MyController#create as JSON
  Parameters: {"{ \"company\": { \"name\": \"acme\", \"address\": \"123 Carrot Street\" } }"=>nil}
Completed 200 OK in 7ms (Views: 5.0ms | ActiveRecord: 0.0ms)
Run Code Online (Sandbox Code Playgroud)

最后这个带有Content-Type标头的命令:

curl -d '{ "company": { "name": "acme", "address": "123 Carrot Street" } }' http://0.0.0.0:3000/mysite --header "Content-Type: application/json"
Run Code Online (Sandbox Code Playgroud)

生成这些日志:

Started POST "/mysite" for 127.0.0.1 at 2012-01-11 16:08:11 -0800
  Processing by MyController#create as */*
  Parameters: {"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "wassup"=>{"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "controller"=>"wassup", "action"=>"create"}}
Completed 200 OK in 4ms (Views: 2.0ms | ActiveRecord: 0.0ms)
Run Code Online (Sandbox Code Playgroud)

请注意,解析的参数和处理消息会随着每种标头类型的变化而细微变化.

  • 非常感谢您的回答!不幸的是,使用XDomainRequest我无法控制标头.(参见[本文]中的第3和第4项(http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx).)所以我认为这可能是正确的答案,但并不能解决我的问题.你知道是否有办法告诉控制器假设一切都是JSON请求?或者至少将默认内容类型设置为JSON? (3认同)

col*_*lin 9

before_filter :fix_ie_params, only: [:create, :update]
Run Code Online (Sandbox Code Playgroud)

对于Thin:

def fix_ie_params
  if request.format == '*/*'
    # try to JSON decode in case of IE XDR
    begin

      params.merge! ActiveSupport::JSON.decode(request.body.string)

    rescue Exception=>e
      # todo: log exception
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

对于UnicornPhusion Passenger:

def fix_ie_params
  if request.format == '*/*'
    # try to JSON decode in case of IE XDR
    begin

      request.body.rewind
      params.merge! ActiveSupport::JSON.decode(request.body.read)

    rescue Exception=>e
      # todo: log exception
    end
  end
end
Run Code Online (Sandbox Code Playgroud)