views:

122

answers:

2

In Rails 2.3.4, the way Accept headers are handled has changed:

http://github.com/rails/rails/commit/1310231c15742bf7d99e2f143d88b383c32782d3

We won't Accept it

The way in which Rails handles incoming Accept headers has been updated. This was primarily due to the fact that web browsers do not always seem to know what they want ... let alone are able to consistently articulate it. So, Accept headers are now only used for XHR requests or single item headers - meaning they're not requesting everything. If that fails, we fall back to using the params[:format].

It's also worth noting that requests to an action in which you've only declared an XML template will no longer be automatically rendered for an HTML request (browser request). This had previously worked, not necessarily by design, but because most browsers send a catch-all Accept header ("/"). So, if you want to serve XML directly to a browser, be sure to provide the :xml format or explicitly specify the XML template (render "template.xml").

I have an active API which is being used by many clients who are all sending both a Content-Type and an Accept header, both set to application/xml. This works fine, but my testing under Rails 2.3.4 demonstrates that this no longer works -- I get a 403 Unauthorised response. Remove the Accept header and just sending Content-Type works, but this clearly isn't an acceptable solution since it will require that all my clients re-code their applications.

If I proceed to deploy to Rails 2.3.4 all the client applications which use the API will break. How can I modify my Rails app such that I can continue to serve existing API requests on Rails 2.3.4 without the clients having to change their code?

+2  A: 

If I understand correctly the problem is in the Request headers. You can simply add a custom Rack middleware that corrects it.

Quick idea:

class AcceptCompatibility
  def initialize(app)
    @app = app
  end

  def call(env)
    if env['Accept'] == "application/xml" && env['Content-Type'] == "application/xml"
      # Probably an API call
      env.delete('Accept')
    end
    @app.call(env)
  end
end

And then in your environment.rb

require 'accept_compatibility'
config.middleware.use AcceptCompatibility
Jan De Poorter
Won't this solution keep you from being able to POST XML data to a controller while asking for an XML response?
coderjoe
+2  A: 

Embarrassingly enough, this actually turned out to be an Apache configuration issue. Once I resolved this, everything worked as expected. Sorry about that.

As coderjoe correctly pointed out, setting the Content-Type header isn't necessary at all -- only setting the Accept header.

Olly
If you don't mind, posting a quick blurb about the Apache configuration might help future users running into the same problem. :) Glad you found the problem!
coderjoe