在Rails 4.2中,如何设置具有媒体类型参数的响应内容类型标头?

时间:2015-09-29 02:31:31

标签: ruby-on-rails http-headers

在早期版本中,这可行:

ActionController::Renderers.add(:foo) do | data, options |
  self.content_type = 'application/foo; bar=1'
end

在4.2.4中,这会导致Content-Type标头为空。但是,以下工作,即将Content-Type标头设置为分配给content_type的字符串:

ActionController::Renderers.add(:foo) do | data, options |
  self.content_type = 'application/foo'
end

我知道的另一种方法是,在渲染上设置content_type,似乎没有结果,即render('foo', content_type: 'application/foo')没有设置标题(不要介意尝试application / foo; bar = 1。 )

2 个答案:

答案 0 :(得分:8)

首先看一下文档(第2.2.13.1节):

http://guides.rubyonrails.org/layouts_and_rendering.html#using-render

他们提供的示例使用您的替代方法,在使用content_type时设置render

render file: filename, content_type: "application/rss"

我在vanilla Rails 4.2.4应用程序中测试了这个策略。这就是我定义控制器的方式:

class WelcomeController < ApplicationController
  def index
    render inline: 'Hello World', content_type: 'application/foo; bar=1'
  end
end

以下是我在点击该操作时在Chrome的网络检查器中看到的内容,请注意响应标题下的Content-Type

常规

Remote Address:[::1]:3000
Request URL:http://localhost:3000/
Request Method:GET
Status Code:200 OK

响应标题

Cache-Control:max-age=0, private, must-revalidate
Connection:Keep-Alive
Content-Length:11
Content-Type:application/foo; bar=1; charset=utf-8
Date:Tue, 29 Sep 2015 02:53:39 GMT
Etag:W/"b10a8db164e0754105b7a99be72e3fe5"
Server:WEBrick/1.3.1 (Ruby/2.2.2/2015-04-13)
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
X-Request-Id:3825d446-44dc-46fa-8aed-630dc7f001ae
X-Runtime:0.022774
X-Xss-Protection:1; mode=block

答案 1 :(得分:1)

Sean Huber是正确的,问题中的代码是正确的。除了已注册MIME类型然后呈现该类型的文件的情况,例如,

Mime::Type.register('application/foobar', :foobar)

render('view') # where view is actually view.foobar.jbuilder

在这种情况下,注册的类型字符串似乎总是覆盖可用于显式设置内容类型的方法。这可能导致认为媒体类型参数被剥离,因为巧合的是,ParamsParser选择似乎是&#34; break&#34;当为默认解析器指定媒体类型参数时,即,为&#39; application / foo注册的解析器;巴= 1&#39;不会解析随该内容类型提供的内容,导致一个人使用无参数字符串作为mime类型字符串,然后尝试覆盖包含参数的字符串。

因此,为了解决4.2中的问题,我已经删除了ParamsParser和Render注册并移动到父控制器上的before_filter和内容类型头到after_filter,例如,

class BaseController < ApplicationController
  before_filter :parse_body
  after_filter :set_content_type

  attr_accessor :parsed

  def parse_body
    self.parsed = JSON.load(request.body)
  end

  def set_content_type
    self.content_type = "application/foo; bar=1; charset=utf-8"
  end
end

注意:这是黑客/解决方法;不建议长期使用。