Why does rails not recognize `Accept: application/json` in the request header?
Asked Answered
H

1

9

I have some frontend javascript that makes an asynchronous http request to my backend rails server. On the frontend I am not using XHR (I use axios, although that's not entirely relevant to the question).

In the request, I set the following to tell the server I'm sending JSON and to make sure I get JSON back:

const config = {
  headers: {
    "Content-Type": "application/json",
    "Accept": "application/json"
  }
};

In my backend Rails controller if inspect the request I can verify the Accept header:

> request.headers
"HTTP_ACCEPT"=>"application/json, text/plain, */*"

However ActionPack/Rails still does not respect that and defaults to the format being :html

> request.format
=> #<Mime::Type:0x00007fe223919f80 @hash=-1773238723920954657, @string="text/html", @symbol=:html, @synonyms=["application/xhtml+xml"]>

Why is that?

I know I can append .json to my request URL to "force" it to specify that format, but is that the only option? I can append it easily but it seems like an implementation specific to Rails and not really the "right" approach.

Additionally, the source code for the request.format method explicitly sets :json as the format on XHR requests - does rails only respect XHR requests at the moment?

Thanks!

Hutcherson answered 20/9, 2019 at 3:43 Comment(0)
S
-1

What you are doing is correct, but sending the Axios/Fetch API requests from browser will show "CORS" error from the browser end(you can see it in your browser dev tools console). You can know more about it from MDN Docs

To resolve this, You'll need to send the Access-Control-Allow-Origin Header to the requests you receive on your web server. You can do it manually by adding this header in application_controller.rb or Simply use a gem like rack-cors. I'll show you how to do using rack-cors gem:

  • Add gem 'rack-cors' in your Gemfile
  • Run the command bundle i
  • In your config/application.rb file, add the following lines:

    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins '*'
        resource '*', headers: :any, methods: [:get, :post, :options]
      end
    end
    
  • Now restart your rails server

  • You can also see above instructions and more details here

Now make the API call again without forcing .json at the end of the URL and it should work.

Schultz answered 20/9, 2019 at 9:11 Comment(4)
I've found a good recent article about CORS - dev.to/miguelmota/…Schultz
Thanks for the explanation! But my request is not cross-origin. My front end and backend are under the same domain.Hutcherson
Can you update the code of your axios request? Do you see any errors in console? Any thing specific in rails server logs?Schultz
I've just tested in a test app - react + rails(one app), I used Fetch API and it's working fine.Schultz

© 2022 - 2024 — McMap. All rights reserved.