This project is archived and is in readonly mode.

#1904 ✓resolved
Eugene Pimenov

rack middleware parse request parameters twice

Reported by Eugene Pimenov | February 7th, 2009 @ 06:59 AM

Rack::MethodOverride parses request parameters, then forgets about it. Rails routes parse it again a bit later.

If I make an upload request, I'll end up with pairs of identical RackMultipart files.

Comments and changes to this ticket

  • josh

    josh February 7th, 2009 @ 10:14 PM

    • 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.

  • josh

    josh February 10th, 2009 @ 07:48 PM

    • State changed from “new” to “resolved”

    Appears to be fixed by a recent upgrade of rack.

  • Eugene Pimenov

    Eugene Pimenov February 10th, 2009 @ 08:05 PM

    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

    josh February 10th, 2009 @ 08:30 PM

    
        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
        end
    

    Rack caches the result from Request#POST to @env["rack.request.form_hash"].

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

People watching this ticket

Tags

Referenced by

Pages