Today I Learned

A Hashrocket project

How Rails Responds to `*/*`

Yesterday I fixed a bug in TIL. This application has a Twittercard, but it's never worked. Twitter's card validator confusingly claims the site lacks Twitter meta tags.

After experimenting, I realized that when cURL-ing our site, the response type is application/json. Why is Rails giving me JSON?

When an HTTP request's accept headers equal */*, any MIME type is accepted. And, when a respond_to block is present:

Rails determines the desired response format from the HTTP Accept header submitted by the client.

Determined how? I learned that the first MIME type declared is used for */* requests.

Notice the difference (HTML first):

# app/controllers/posts_controller.rb
 def index
    @posts = Post.all
    respond_to do |format|
      format.html
      format.json { render json: @posts }
    end
  end

Request/response:

$ curl -vI localhost:3000/
...
> Accept: */*
>
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...

JSON first:

# app/controllers/posts_controller.rb
 def index
    @posts = Post.all
    respond_to do |format|
      format.json { render json: @posts }
      format.html
    end
  end

Request/response:

$ curl -vI localhost:3000/
...
> Accept: */*
>
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
...

Reversing the order (HTML first) solved the issue.

Looking for help? Hashrocket provides expert Ruby on Rails development. We’ve built hundreds of high–quality Ruby on Rails applications over the past decade. Contact us today and find out how we can help you.