0

我正在使用 JSON 响应的旧版 rails 1.2.6 应用程序中构建 Web 服务,并且我试图使其也接受 JSON,而不是 URL 编码参数。

我把它放在我的控制器中:

param_parsers[Mime::JSON] = lambda { |data| JSON.parse(data) }

这不起作用,因为表现良好的休息客户端发送:

Content-Type: application/json; charset=utf-8

如您所见,字符编码附加到 Content-Type 标头,但 rails 1.2 对整个“Content-Type”标头进行了简单的字符串比较,并被“charset=utf-8”部分丢弃。

rails-1.2/gems/gems/actionpack-1.13.6/lib/action_controller/request.rb

def content_type
  @content_type ||=
    begin
      content_type = @env['CONTENT_TYPE'].to_s.downcase

      if x_post_format = @env['HTTP_X_POST_DATA_FORMAT']
        case x_post_format.to_s.downcase
        when 'yaml'
          content_type = 'application/x-yaml'
        when 'xml'
          content_type = 'application/xml'
        end
      end

      Mime::Type.lookup(content_type)
    end
end

rails-1.2/gems/gems/actionpack-1.13.6/lib/action_controller/mime_type.rb

  def lookup(string)
    LOOKUP[string]
  end

在 mime_type.rb 文件的下方:

LOOKUP["application/json"]         = JSON
LOOKUP["text/x-json"]              = JSON

@env['CONTENT_TYPE'] 是 "application/json; charset=utf-8"

Mime::Type.lookup(content_type) 只是返回 LOOKUP[content_type],它不会匹配,因为当时内容类型仍然附加了“;charset=utf-8”。

content_type 应该在哪里去除 charset=utf-8?你会如何解决这个问题?它在 Rails3 上是如何工作的,因为从我的角度来看,它几乎与 mime_type.rb 相同?

4

1 回答 1

1

答案来自阅读 parse_formatted_pa​​rameters() 的代码。我使用 lambda 来创建块,这个 rails 代码专门寻找 Proc。

我刚变

param_parsers[Mime::JSON] = lambda { |data| JSON.parse(data) }

param_parsers[Mime::JSON] = Proc.new { |data| JSON.parse(data) }

现在一切都按预期工作。我把它改回 lambda,params 又变空了,然后回到 Proc 它又工作了。

奇怪,因为即使那个代码片段给了我有效的解决方案,它似乎也不是问题所在。

>> case Proc.new{}; when Proc; "a"; when :xml_simple; "b" end
"a"
>> case lambda{}; when Proc; "a"; when :xml_simple; "b" end 
"a"

rails-1.2/gems/gems/actionpack-1.13.6/lib/action_controller/cgi_ext/cgi_methods.rb

def parse_formatted_request_parameters(mime_type, raw_post_data)
  case strategy = ActionController::Base.param_parsers[mime_type]
    when Proc
      strategy.call(raw_post_data)
    when :xml_simple
      raw_post_data.blank? ? {} : Hash.from_xml(raw_post_data)
    when :yaml
      YAML.load(raw_post_data)
    when :xml_node
      node = XmlNode.from_xml(raw_post_data)
      { node.node_name => node }
  end
于 2012-04-30T21:24:11.270 回答