3

In my rails API, I have added an initialiser that will change the keys of the JSON input from snake-case to underscore-separated. Like so:

ActionDispatch::Request.parameter_parsers[:json] = -> (raw_post) {
    data = ActiveSupport::JSON.decode(raw_post)
    data = {:_json => data} unless data.is_a?(Hash)

    data.deep_transform_keys!(&:underscore)
}

Now, certain APIs will be passed with the header: content-type: multipart/form-data instead of application/json

I want to do the same for such APIs. That is add an initialiser that will convert the case of the keys in the parameters.

I tried ActionDispatch::Request.parameter_parsers[:form_data] but it dit not work.

How can I achieve this?

mridula
  • 3,203
  • 3
  • 32
  • 55
  • Did you manage to solve this? I added a parser as suggested in the answer below but it opened a can of worms :( – Chris Edwards Sep 01 '17 at 16:05
  • Yes, I did. Well, sort of. I could not make it work using `parameters_parsers`. It just doesn't work the way it works for JSON parameters. Let me show you my code by adding it as an answer. – mridula Sep 03 '17 at 08:56

2 Answers2

4

When you look at the DEFAULT_PARSERS, it uses the Mime class, so whatever we end up using will likely need to be recognizable by the Mime class. So we can check Mime::Types to see what's available.

On that page, we see that content-type: multipart/form-data is mapped to :multipart_form. Indeed, while using

ActionDispatch::Request.parameter_parsers[:multipart_form] = -> (raw_post) {
  raise "Parsing Parameters: #{raw_post}"
}

and then submitting a form with a file field, I can trigger the error.

Simple Lime
  • 10,790
  • 2
  • 17
  • 32
1

Although, according to Simple Lime's answer, :multipart_form is the right key for the default parser for requests with content-type: multipart/form-data, it does not work like the way it does for JSON.

This is the work around I implemented:

class ApplicationController < ActionController::API
    before_action :transform_params_if_multipart!

    private 
    def transform_params_if_multipart!
        params.deep_transform_keys!(&:underscore) if /^multipart\/form-data*/.match(request.headers['content-type'])
    end
end
mridula
  • 3,203
  • 3
  • 32
  • 55
  • 2
    This solution works on Rails 5 with a deprecation warning, but Rails 5.1 removes deep_transform_keys! from params, so it's not a good long term solution, and what we probably need is a modification of `ActionDispatch::Request.parameter_parsers[:multipart_form] = -> (raw_post) {` – Colton Voege Nov 17 '17 at 14:56