This project is archived and is in readonly mode.
rack middleware parse request parameters twice
-
josh
- Milestone cleared.
- Assigned user set to josh
Can you please test on edge as well. Also, failing unit tests to prove the issue would be appreciated.
-
Eugene Pimenov
No, it's not.
Test something like:
Rack::Request.any_instance.expects(:POST).once.returns({}) @dispatcher.call({"REQUEST_METHOD" => "POST", "rack.input" => StringIO.new(""), "REQUEST_URI" => "/"})where dispatcher is ActionController::Dispatcher. I'll provide normal test case later.
The problem because of Rack::MethodOverride has that code
req = Request.new(env) method = req.POST[METHOD_OVERRIDE_PARAM_KEY] || env[HTTP_METHOD_OVERRIDE_HEADER]It uses Rack::Request, instead of ActionController::Request. ActionController::Request saves itself into rack env, so doesn't parse arguments twice. Rack::Request parses arguments every time POST is invoked.
To fix that problem locally, I monkey-patched Rack::MethodOverride to use ActionController::Request.
-
josh
def POST if @env["rack.request.form_input"].eql? @env["rack.input"] @env["rack.request.form_hash"] elsif form_data? @env["rack.request.form_input"] = @env["rack.input"] unless @env["rack.request.form_hash"] = Utils::Multipart.parse_multipart(env) form_vars = @env["rack.input"].read # Fix for Safari Ajax postings that always append \0 form_vars.sub!(/\0\z/, '') @env["rack.request.form_vars"] = form_vars @env["rack.request.form_hash"] = Utils.parse_query(form_vars) begin @env["rack.input"].rewind if @env["rack.input"].respond_to?(:rewind) rescue Errno::ESPIPE # Handles exceptions raised by input streams that cannot be rewound # such as when using plain CGI under Apache end end @env["rack.request.form_hash"] else {} end endRack caches the result from Request#POST to @env["rack.request.form_hash"].