title: Ruby on Rails: setting content-type in `responds_to { |f| f.any`
body: <p>Using Rails API I had a <code>/events</code> endpoint that could be called without specifying the format; no <code>/events.json</code> needed. The route:</p>
  <pre><code>resources :events, defaults: { format: :json }
  </code></pre>
  <p>The controller:</p>
  <pre><code>def index
    @events = get_events
    render json: @events
  end
  </code></pre>
  <p>Now I want to respond to <code>/events.csv</code> with a CSV file, but otherwise keep the behavior unchanged. Before getting to the CSV, I add a <code>respond_to</code> block:</p>
  <pre><code>def index
    @events = get_events
    respond_to do |format|
      format.any { render json: @events }
    end
  end
  </code></pre>
  <p>This has <em>almost</em> the same behavior as the previous approach, except that requests to <code>/events</code> now have a header <code>Content-Type: application/html</code> rather than <code>application/json</code>.</p>
  <p>I find this surprising, given that I specify <code>json</code> in that block! But looking at the Rails source code, I see that they indeed <a href="https://github.com/rails/rails/blob/914caca2d31bd753f47f9168f2a375921d9e91cc/actionpack/lib/action_controller/metal/mime_responds.rb#L212" rel="nofollow noreferrer">skip setting the Content-Type header for <code>any</code> responses</a>. This makes it always set <code>Content-Type</code> to whatever the user requested, rather than matching <code>Content-Type</code> to the actual response. If someone requests XML, it returns JSON but calls it XML. If someone requests HTML, as I am in my tests without <code>format: :json</code> and when I test without the <code>.json</code> in my browser, it returns JSON but calls it HTML.</p>
  <p>Why? And how to I override this and force the Content-Type/mime type to match the actual response?</p>