Alter Rails params hash from Rack middleware

silatham99 picture silatham99 · Apr 25, 2014 · Viewed 7k times · Source

I am attempting to add a value to the Rails params hash from a custom Rack middleware object. My current approach is using

class PortalResolver

 def initialize(app)
   @app = app
 end

  def call(env)
    begin
      url = "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}"
      request = Rack::Request.new(env)
      portal_id = DomainService.domain(url) # DomainService is returning the expected value
      request.params['portal_id'] = portal_id
      status, headers, response = @app.call(env)
      [status, headers, response]
    rescue PortalNotFoundError => e
      [403, {'Content-Type' => 'text/html'}, ['']]
    end
  end
end

I'm currently adding the middleware after ActionDispatch::ParamsParser. The parameters don't show up in the Rails params hash from a controller, but do show up in the request.params hash (within the middleware object defined above.) Any ideas? Help much appreciated.

Answer

matt picture matt · Apr 25, 2014

The docs for Rack::Request#params say:

Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params.

When you use the line

request.params['portal_id'] = portal_id

you add the new parameter to the hash created for that instance of Rack::Request, but the env that is passed on to rails isn’t modified. To make the new value available further down the Rack stack use update_param as the docs suggest:

request.update_param('portal_id', portal_id)