This project is archived and is in readonly mode.

#2289 ✓stale
Greg DeVore

_method=put ignored for xhr and xml requests

Reported by Greg DeVore | March 18th, 2009 @ 06:11 PM | in 3.x

In previous versions of Rails you could do something like this:

curl -H "Accept: text/xml"

   -H "Content-type: application/xml"
    d "_method=put" 
    -X POST http://localhost.com:3000/posts/1

Rails would recognize the POST request as a put because of the _method=put param and your restful routes would work correctly.

In 2.3.2 this no longer works for xml requests. It does for html. So

curl d "_method=put" -X POST http://localhost.com:3000/posts/1

will hit the update action.

But if you add hte Accpet: "text/xml" header then will interpret the request as a post request and map the request to the create method.

This is a problem with Ajax forms that want to use restful routes but can only issue GET and POST requests.

Comments and changes to this ticket

  • Greg DeVore

    Greg DeVore March 18th, 2009 @ 07:50 PM

    Did some more investigating on this. If an xml request is made a _method=put in the params Rack::MethodOverride is never hit. You have to add an HTTP_X_HTTP_METHOD_OVERRIDE header.

    Is there is a reason why xml requests won't look at the _method param?

  • Greg DeVore

    Greg DeVore March 19th, 2009 @ 01:29 AM

    • Tag set to method, middleware, request, xml

    OK - I was going down the wrong path on this one. The real problem is that in previous versions of rails you could have from post data and pass _method=put as a query param. The routing would recognize it as a put request.

    In 2.3, if you don't put the _method=put into the form data, but into the query then it won't be recognized as a put request. I have made a small change to the Rack::MethodOverride module that fixes this but I am not sure if there are any negative consequences for including it.

  • Brian Lopez

    Brian Lopez March 23rd, 2009 @ 07:25 PM

    I have this same issue with posting JSON as the request body format. From what I could find, it seems that the check for the METHOD_OVERRIDE_PARAM_KEY (which is set to "_method") is being done on req.POST which is empty in my JSON request. Changing that req.POST check to use req.env['action_controller.request.request_parameters'] fixes the problem for me. I'm hesitant to submit this as a patch because I'm assuming it breaks the general nature of middleware that may want to avoid ActionController completely. But maybe this Rack::MethodOverride middleware comes so late in the chain it doesn't matter?

    Anyway, this is around line 15 of methodoverride.rb in the bundled Rack 1.0 in Rails 2.3.2.

  • Brian Lopez

    Brian Lopez March 23rd, 2009 @ 07:34 PM

    After thinking about it a little more, doing this change in Rack is a bad idea. I think the actual fixable issue is that ActionController::ParamsParser sets env["action_controller.request.request_parameters"] to the parsed params. But Rack sets up it's Request#POST hash based on env['rack.input'] (I think).

    It seems like two things might have to change... If ActionController::ParamsParser were to set the value of env["rack.request.form_hash"] instead of env["action_controller.request.request_parameters"], AND Rack were to check if env["rack.request.form_hash"] was already from other middleware in the chain?

  • Brian Lopez

    Brian Lopez March 23rd, 2009 @ 07:36 PM

    Forgot to mention, setting HTTP_X_HTTP_METHOD_OVERRIDE worked fine without any of my above mentioned changes as well. I think I like this better anyway.

  • Szymon Nowak

    Szymon Nowak April 2nd, 2009 @ 08:38 PM

    Do you still have this problem?

    Recently after upgrading to Rails 2.3.2 suddenly in place editing plugin that we use stopped working giving "only get, put and delete method allowed" when requesting JSON using PUT method.

    Thanks to you guys we managed to fix it by swapping Rack::MethodOverride with the patched version provided here (see http://guides.rubyonrails.org/ra... for swapping middlewares).

    But later it turned out that this problem was caused by facebooker gem that we were using - it was inserting its own Rack middleware into the stack that caused this problem - updating it to 1.0.25 fixed this problem and we could remove our patched version of Rack::MethodOverride middleware.

  • Rich

    Rich May 22nd, 2009 @ 06:14 AM

    I'm hitting up against this too, however, this just started happening when I created a metal app.

    http://gist.github.com/115937

    At first I thought it might be related to the paths I've defined in my metal app, but even if I just declare a bare bones metal app(i.e., class MyMetalApp;end;) all restful update actions are broken and I get this error:

    Only get, put, and delete requests are allowed.

    This seems to be the only ticket related to this issue. Not sure if I should file a new one.

  • Rich

    Rich May 22nd, 2009 @ 06:15 AM

    Forgot to mention this is happening for standard text/html requests.

  • Marcus Wyatt

    Marcus Wyatt June 4th, 2009 @ 05:16 AM

    I've also stumbled into this problem when we upgraded our product to Rails version 2.3.2. It's a worry, because our app utilizes XML extensively.

  • Andy Watts

    Andy Watts July 22nd, 2009 @ 09:41 PM

    This is also an issue when adding PUT links in active_scaffold

  • Sean Grove

    Sean Grove August 13th, 2009 @ 12:00 PM

    I'm having the same problem here with XHR requests. I'm working on developing the gwt-on-rails plugin, but we don't seem to be able to PUT anything as it's simply being ignored via either XHR JSON or XML requests.

  • joost baaij

    joost baaij December 19th, 2009 @ 08:16 PM

    Fwiw, the actual request header to send is called X-Http-Method-Override. So in curl, to simulate a JSON PUT request that would be:

    curl -H "X-Http-Method-Override: put" -H "Content-Type: application/json" -d "{blah@example.com"}}"">user www.example.com/users/username.json

    Took me a few hours of research. Including _method in the JSON hash had no effect whatsoever though.

  • Jeremy Kemper

    Jeremy Kemper May 4th, 2010 @ 06:48 PM

    • Milestone changed from 2.x to 3.x
  • Neeraj Singh

    Neeraj Singh June 28th, 2010 @ 06:12 PM

    • Importance changed from “” to “”

    In rails3 edge all the following three requests worked just fine for me.

    $ curl -X POST -d "user[name]=John" -d "_method=PUT" http://localhost:3000/users/1
    $ curl -X POST -d "user[name]=John2" "Content-Type: text/xml" -d "_method=PUT" http://localhost:3000/users/1
    $ curl -X POST -d "user[name]=John3" "Content-Type: application/json" -d "_method=PUT" http://localhost:3000/users/1
    
  • Mike (at coverallcrew)

    Mike (at coverallcrew) July 6th, 2010 @ 11:21 PM

    Neeraj,

    Those work for html requests, but if you try a JSON request _method=PUT param will fail. Although, sending the header HTTP_X_HTTP_METHOD_OVERRIDE=put does work for xhr.

  • Andrew White

    Andrew White July 7th, 2010 @ 04:56 AM

    Mike, how are you doing the request? Only POST requests will have their method overridden. Also the _put variable needs to be in the form data and not the query string. This is the simple Rack middleware that does the overriding:

    module Rack
      class MethodOverride
        HTTP_METHODS = %w(GET HEAD PUT POST DELETE OPTIONS)
    
        METHOD_OVERRIDE_PARAM_KEY = "_method".freeze
        HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE".freeze
    
        def initialize(app)
          @app = app
        end
    
        def call(env)
          if env["REQUEST_METHOD"] == "POST"
            req = Request.new(env)
            method = req.POST[METHOD_OVERRIDE_PARAM_KEY] ||
              env[HTTP_METHOD_OVERRIDE_HEADER]
            method = method.to_s.upcase
            if HTTP_METHODS.include?(method)
              env["rack.methodoverride.original_method"] = env["REQUEST_METHOD"]
              env["REQUEST_METHOD"] = method
            end
          end
    
          @app.call(env)
        end
      end
    end
    

    As you can see it's not a complicated bit of code so the way you build your JSON request is probably triggering the error. I think previously in the pre-Rack days the _method could either be in the query or the form data and that tends to catch people out.

  • Andrew White

    Andrew White August 20th, 2010 @ 06:43 AM

    • State changed from “new” to “needs-more-info”
  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:59 PM

    • State changed from “needs-more-info” to “open”

    This issue has been automatically marked as stale because it has not been commented on for at least three months.

    The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.

    Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.

  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:59 PM

    • State changed from “open” to “stale”
  • Michael Latta

    Michael Latta April 25th, 2011 @ 07:33 PM

    This is still an issue with 3.0.6 and query parameters with method=put for ajax requests. I just ran into this today with porting 2.x code to the 3.x version of a site. using jQuery.post to a URL that includes ?mthod=put&... does not get treated as a PUT request, but as a POST.

  • Michael Latta

    Michael Latta April 25th, 2011 @ 08:02 PM

    By changing the call from $.post to $.ajax with type 'PUT' this seems to resolve the issue.

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>

Attachments

Pages