In Rails 4.2, how do I set a response content type header with media type parameters?

In earlier versions, this would work:

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

In 4.2.4, this causes the Content-Type header to be empty. However, the following works, that is, sets the Content-Type header to the string assigned to content_type:

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

Another approach that I know about setting the content_type in the render no longer has a result, i.e. render('foo', content_type: 'application/foo') does not set the title (it doesn't matter, try the application / foo; bar = 1.)

+5
source share
2 answers

First take a look at the documentation (section 2.2.13.1):

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

In the example that they cite, your alternative approach is used, setting content_type when using render :

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

I tested this strategy in vanilla Rails 4.2.4. This is how I defined the controller:

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

And here is what I see in the Chrome Network Inspector when I hit this action, pay attention to the Content-Type under the response headers:

General

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

Answer Headers

 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 
+4
source

Sean Huber is right, and the code in the question is correct. Except in cases of registration of the MIME type and subsequent playback of files of this type, for example,

 Mime::Type.register('application/foobar', :foobar) render('view') # where view is actually view.foobar.jbuilder 

In this case, the registered type string always overrides the approaches available to set the content type explicitly. This may lead to the idea that the media type parameters are erased, because, by coincidence, the ParamsParser choice seems to break when the media type parameters are set for the parser by default, that is, the analyzer registered for "application / foo"; bar = 1 'will not analyze the content provided by this type of content, forcing to use a string with no parameters for a string of type mime, and then try to redefine it with one parameter.

So, to get around this in 4.2, I unregistered ParamsParser and Render and went to the before_filter file on the parent controller and the content type header in after_filter, e.g.

 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 

Note: this is a pretty hack / workaround; not recommended for long term use.

+1
source

Source: https://habr.com/ru/post/1232494/


All Articles