Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding the default Content-Type

I have a Rails API which accepts only JSON as input. If I fail to include a header of Content-Type: application/json, then request.headers['Content-Type'] defaults to application/x-www-form-urlencoded and the params do not get parsed properly. The whole json body becomes a key in the params. The result is a 422, which is confusing to API users.

How can I change this to default to parsing as json if no Content-Type header is supplied?

Lots of other questions answer how to do this with the response format. To change this default, you can specify it in the controller with:

 request.format = :json

Or in a route namespace with something like:

 namespace :api, defaults: {format: :json} do

This, however, changes the default response format and does not change the default request format. What I need to do is to change the default request format for parsing parameters.

like image 812
davidgyoung Avatar asked Oct 27 '25 03:10

davidgyoung


1 Answers

Here is my admittedly terrible solution derived from the suggestion in Micael Nussbaumer's answer. I'd love it if some Rubyists could magically turn this ugly hack into a pithy one liner.

module Api
  class BaseApiController < ActionController::API

  private
    # This is an ugly hack needed to make it default to json if you do not
    # specify a Content-Type.  If you see this and know of a better way please
    # say so!
    def params
      if !@params
        if request.headers["Content-Type"]=="application/x-www-form-urlencoded"
          body_string = request.body.read
          begin
            hash = JSON.parse(body_string)
            @params = ActionController::Parameters.new(hash)
          rescue
            # do nothing
          end
        end
        if !@params
          @params = super
        end
      end
      @params
    end

    ...

end
like image 100
davidgyoung Avatar answered Oct 28 '25 21:10

davidgyoung