1

I have an app with a link to a controller like /something/orders.xml which uses RABL to construct an XML doc. Works, but it seems due to the browser's request header this is being returned as text/html in some browsers, for instance, Chrome:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

I want the response to have Content-type: text/xml because that's what it is! So, according to many howtos and the Rails Guides, you can do

config.action_controller.use_accept_header = false

in application.rb. But this is currently resulting in undefined method use_accept_header=:

/home/sbeam/.rvm/gems/ruby-1.9.3-p194@global/gems/actionpack-3.2.6/lib/action_controller/railtie.rb:41:in `block (3 levels) in <class:Railtie>': undefined method `use_accept_header=' for ActionController::Base:Class (NoMethodError)
sbeam
  • 4,622
  • 6
  • 33
  • 43

1 Answers1

3

You should be able to override the content type in the action of your controller by setting response.headers:

respond_to do |format|
  format.html
  format.json { render :json => @orders }
  format.xml do
    response.headers['content-type'] = 'text/xml'
    render :xml => @orders
  end
end

Edit

The option to set use_accept_header was deprecated after Rails 3.0.

If you can't override the format in your actions, you could try modifying your mime types directly. You could put the following into an initializer in Rails:

Mime.send(:remove_const, :xml)
Mime::Type.register "text/xml", :xml

Also if you are using JQuery and retrieving the XML via ajax, you can explicitly set the content-type you require. See this question: Cannot properly set the Accept HTTP header with jQuery

Edit 2

If all else fails, you can use:

ActionDispatch::Request.ignore_accept_header = true

in your configuration to turn off content negotiation entirely. You may want to control what the data formats you do want to receive via ajax requests as I mentioned above. If so, then instead you can implement the rack middleware changes at https://github.com/econsultancy/rack-strip_http_accept_headers.

Community
  • 1
  • 1
mccannf
  • 16,619
  • 3
  • 51
  • 63
  • yes, but I guess the point is that I shouldn't have to (and because this method is actually in an Engine, it's kind of a pain to do this). The client has requested a .xml file, so why do I have to add this boilerplate to force Rails to respond with a header that matches? – sbeam Oct 21 '12 at 01:11
  • If you want to avoid the boilerplate take a look at respond_with http://apidock.com/rails/ActionController/MimeResponds/respond_with – alexpls Oct 21 '12 at 10:22
  • @max_w the same thing happens with `respond_with`: Rails sends `Content-type: text/html` for all formats. – sbeam Oct 21 '12 at 18:47
  • @mccannf changing the Mime::Type registry had no effect, it was already `application/xml` to begin with. Seems that Rails ignores it, deferring to the Accept: header. And this isn't a AJAX call, it's more of an API. In any case, again I'd say that we shouldn't have to depend on headers on the client side either - who knows what some 3rd party will send? – sbeam Oct 21 '12 at 18:53
  • @sbeam - added something to try if all else fails ;) – mccannf Oct 21 '12 at 19:57
  • yep, I did eventually find the new `ignore_accept_header` setting and tried it, but... had no effect. It may be some other piece of the stack, I'll have to try and reproduce this on a vanilla Rails app. – sbeam Oct 22 '12 at 14:30
  • I think you gave the best answer anyone could give to this; even though the problem must lie elsewhere. Thanks for your help – sbeam Oct 26 '12 at 20:13