15

I'm just wondering how rails knows the format of the request as to correctly enter in the famous:

respond_to do |format|
  format.html
  format.xml
  format.json
end

As an example consider this situation I have faced up. Suppose that via javascript (using jQuery) I make a POST request expliciting dataType: json

$.ajax({
      type: 'POST',
      url: 'example.com',
      data: data,
      dataType: 'json'
    });

When this request reach controller action, standing inside it with ruby debugger, I inspect @request.format and I can see that content-type is application/json. Then the controller respond to json format as expected.

But I'm confused with the format symbol especified in the routes. Suppose that a request is made to example.com/parts.json but in the request the content type is application/html or application/xml. Is the controller responding to json format or html or xml??

Thanks!

flyer88
  • 1,073
  • 3
  • 15
  • 33

2 Answers2

10

From ActionController::MimeResponds: "Rails determines the desired response format from the HTTP Accept header submitted by the client."

Prakash Murthy
  • 12,923
  • 3
  • 46
  • 74
mikewilliamson
  • 24,303
  • 17
  • 59
  • 90
  • 1
    Thanks! But I can't already understand what means the :format symbol that appears in routes.rb for example. Because if I send a request to my server (for example GET /entities.xml) and in my controller I have a xml respond_to handler, the accept header says application/XML in google chrome inspector. There's something in the middle that I haven't understood already. Is rack the one that sees .xml in the url and according to this it builds the appropiate REQUEST with appropiate accept headers? Thanks again! – flyer88 Jun 06 '11 at 17:50
  • 2
    Basically the :xml is one of the mime types registered here https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/http/mime_types.rb That is where you connect the mime type with the :format symbol. That symbol is used to call the the appropriate renderer, which is registered with ActionController::Renderers. – mikewilliamson Jun 07 '11 at 20:53
4

The incoming Content-Type only affects the way the request is parsed. It doesn't affect the response format.

Since Rails 5.0, the response format is determined by checking for:

  1. A format parameter (e.g. /url?format=xml)
  2. The HTTP Accept header (e.g. Accept: application/json)
  3. The path extension (e.g. /url.html)

You can see this in the implementation of ActionDispatch::Http::MimeNegotation#formats. Here is an excerpt from Rails v6.1:

if params_readable?
  Array(Mime[parameters[:format]])
elsif use_accept_header && valid_accept_header
  accepts
elsif extension_format = format_from_path_extension
  [extension_format]
elsif xhr?
  [Mime[:js]]
else
  [Mime[:html]]
end
Hosam Aly
  • 41,555
  • 36
  • 141
  • 182