av501
av501

Reputation: 6739

respond to only json in rails

In my rails app which is json only, I want to send a 406 code whenever someone calls my rails app with accept header set to anything except application/json. I also want it to send a 415 when I get the content type set to anything except application / json

My controllers have respond_to :json put on them. I only render json in all actions. However how do I ensure that I return error code 406/415 for all calls for anything that is called for all other accept headers/content-type and with format set to anything except json.

Eg. If I my resource is books/1 I want to allow books/1.json or books/1 with application/json in accept header and content type

Any ideas on how I can do these two actions?

Upvotes: 15

Views: 21454

Answers (3)

bluehallu
bluehallu

Reputation: 10285

On rails 4.2+ respond_to has been removed, so unless you want to import the full responders gem just for this, your best bet is to roll your own. This is what I'm using in my rails 5 api:

    class ApplicationController < ActionController::API
      before_action :force_json

      private
      def force_json
        # if params[_json] it means request was parsed as json 
        # if body.read.blank? there was no body (GET/DELETE) so content-type was meaningless anyway
        head :not_acceptable unless params['_json'] || request.body.read.blank?
      end
    end

Upvotes: -1

pdu
pdu

Reputation: 10423

Basically, you can limit your responses in two ways.

First, there is respond_to for your controllers. This would automatically trigger a 406 Not Acceptable if a request for a format is made which is not defined.

Example:

class SomeController < ApplicationController
  respond_to :json


  def show
    @record = Record.find params[:id]

    respond_with @record
  end
end

The other way would be to add a before_filter to check for the format and react accordingly.

Example:

class ApplicationController < ActionController::Base
  before_filter :check_format


  def check_format
    render :nothing => true, :status => 406 unless params[:format] == 'json' || request.headers["Accept"] =~ /json/
  end
end

Upvotes: 37

Erez Rabih
Erez Rabih

Reputation: 15788

You can do it with a before_filter in ApplicationController

before_filter :ensure_json_request

def ensure_json_request
  return if params[:format] == "json" || request.headers["Accept"] =~ /json/
  render :nothing => true, :status => 406
end

Upvotes: 10

Related Questions