Parsing MessagePack to Rails params

Update ActionDispatch::ParamsParser has been deprecated in Rails 5.0.

Below solution works for Rails versions before 5.1 where ActionDispatch::ParamsParser got removed.

Checkout this post for similar implementation in current Rails versions.

Recently I had to develop Ruby on Rails app which would handle MessagePack formatted request bodies as well as JSON. By default Rails makes parsed JSON available at the params object, and I wanted MessagePack content to be handled just like that.

ActionDispatch::ParamsParser is a Rack middleware responsible for this behavior. Extending it to support other serialization formats could be done in following manner.

I started by including mgspack_rails to Gemfile and then wrote my custom middleware at app/middlewares/custom_params_parser.rb extending ParamsParser to preserve default behavior.

class CustomParamsParser < ActionDispatch::ParamsParser
  def initialize(app, parsers={}, &block)
    super app,
          parsers.merge({
            Mime[:msgpack] => lambda {|raw_post|
              data = ActiveSupport::MessagePack.decode(raw_post)
              data.is_a?(Hash) ? data : { _msgpack: data }
            }
          }),
          &block
  end
end

Then I replaced default ParamsParser in the middleware stack by including following to the config/application.rb:

config.middleware.swap 'ActionDispatch::ParamsParser', 'CustomParamsParser'

It should be noted while writing tests, that middleware stack is not available at the functional controller tests. Integration tests have to be used when it’s necessary to include request body data to params or to test custom middleware like the one above.