233

Can I use a PUT method in an HTML form to send data from the form to a server?

WelcomeTo
  • 19,843
  • 53
  • 170
  • 286

10 Answers10

254

According to the HTML standard, you can not. The only valid values for the method attribute are get and post, corresponding to the GET and POST HTTP methods. <form method="put"> is invalid HTML and will be treated like <form>, i.e. send a GET request.

Instead, many frameworks simply use a POST parameter to tunnel the HTTP method:

<form method="post" ...>
  <input type="hidden" name="_method" value="put" />
...

Of course, this requires server-side unwrapping.

KęstutisV
  • 61
  • 1
  • 7
phihag
  • 278,196
  • 72
  • 453
  • 469
  • 5
    You have been linking a draft, not a final standard. Just noting, the stable HTML versions don't offer it either. – hakre Nov 08 '11 at 17:12
  • 16
    @hakre HTML5 is the de-facto standard already, and will probably evolve over time. What the W3C calls "Draft" is a documented developed over at least 3 years with the input of browser vendors with more than >99%, and has already been implemented (at least when it comes to this and most non-esoteric sections) by all of them forever. But just for nitpickers, [here's the equivalent definition](http://www.w3.org/TR/html401/interact/forms.html#adef-method) in HTML 4.01 (a Technical Request in the W3C's terms). – phihag Nov 08 '11 at 17:19
  • 2
    Please don't feel offended, I already wrote that it's just a note and that [the other HTML versions don't offer it either](http://stackoverflow.com/questions/8054165/using-put-method-in-html-form/8054444#8054444) (with a slight exception of XHTML 2, but that's an obsolete draft now). – hakre Nov 08 '11 at 17:27
  • 3
    @hakre Rest assured I'm not offended at all. Nitpicking the nitpicker, I must comment that XHTML is technically not HTML, although one might find one or two similarities ;) – phihag Nov 08 '11 at 17:29
154

XHTML 1.x forms only support GET and POST. GET and POST are the only allowed values for the "method" attribute.

Danubian Sailor
  • 1
  • 38
  • 145
  • 223
dqhendricks
  • 19,030
  • 11
  • 50
  • 83
  • 10
    XHTML is somewhat outdated. Still it looks like same two values are valid in html5 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-method – jakubiszon Dec 07 '17 at 22:31
51

Can I use "Put" method in html form to send data from HTML Form to server?

Yes you can, but keep in mind that it will not result in a PUT but a GET request. If you use an invalid value for the method attribute of the <form> tag, the browser will use the default value get.

HTML forms (up to HTML version 4 (, 5 Draft) and XHTML 1) only support GET and POST as HTTP request methods. A workaround for this is to tunnel other methods through POST by using a hidden form field which is read by the server and the request dispatched accordingly. XHTML 2.0 once planned to support GET, POST, PUT and DELETE for forms, but it's going into XHTML5 of HTML5, which does not plan to support PUT. [update to]

You can alternatively offer a form, but instead of submitting it, create and fire a XMLHttpRequest using the PUT method with JavaScript.

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • 1
    [Supporting PUT and DELETE with HTML FORMS](http://amundsen.com/examples/put-delete-forms/) – Eugen Konkov Feb 19 '17 at 17:18
  • 1
    An AJAX request cannot replace completely a form request because a form request redirects the user to the given resource. For example there is no way as of right now to show in the browser the page of the route `PUT /resource`. – JacopoStanchi Jul 05 '18 at 07:45
  • It's a bad idea to do this. Frameworks can ignore form parameters for PUTs. Java's HTTPServlet seems to. We had a bug where `HttpRequest.getParameterMap()` did not return form parameters. – DaBlick Jan 09 '19 at 17:00
  • @DaBlick: But not for XMLHttpRequests? If so then relying on the fetch API should be more standardized. – hakre Jan 10 '19 at 14:37
41

_method hidden field workaround

The following simple technique is used by a few web frameworks:

  • add a hidden _method parameter to any form that is not GET or POST:

    <input type="hidden" name="_method" value="PUT">
    

    This can be done automatically in frameworks through the HTML creation helper method.

  • fix the actual form method to POST (<form method="post")

  • processes _method on the server and do exactly as if that method had been sent instead of the actual POST

You can achieve this in:

  • Rails: form_tag
  • Laravel: @method("PATCH")

Rationale / history of why it is not possible in pure HTML: https://softwareengineering.stackexchange.com/questions/114156/why-there-are-no-put-and-delete-methods-in-html-forms

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • Laravel (php) has the same feature by using `@method("PATCH")` – santiago arizti Jun 21 '19 at 14:32
  • It seems like a reasonable workaround, but still unfortunate, since it makes debugging difficult. For example, if you need to go through server logs or do network analysis to verify some things, you won't see correct output, since the HTTP method being used in the HTTP headers is still `POST` and not what you actually needed. – code_dredd Aug 15 '19 at 22:59
14

for people using laravel

<form method="post" ...>
@csrf
@method('put')
...
</form>
MemeDeveloper
  • 6,457
  • 2
  • 42
  • 58
CodeToLife
  • 3,672
  • 2
  • 41
  • 29
  • 2
    The code is not only solution. Please add description too. Thanks. – Rayees AC Sep 20 '20 at 14:13
  • 1
    @Rayees AC, this is a solution for them who does work in Laravel framework, fyi. Had written that bolded on the top of the post. Didnt get what youre about otherwise – CodeToLife Sep 20 '20 at 16:05
  • 4
    Although SO sensibly encourages people not to post code only answers, sometimes... like this case... it's all you need. – MemeDeveloper Jan 21 '21 at 15:43
11

Unfortunately, modern browsers do not provide native support for HTTP PUT requests. To work around this limitation, ensure your HTML form’s method attribute is “post”, then add a method override parameter to your HTML form like this:

<input type="hidden" name="_METHOD" value="PUT"/>

To test your requests you can use "Postman" a google chrome extension

Tofeeq
  • 2,523
  • 1
  • 23
  • 20
2

To set methods PUT and DELETE I perform as following:

<form
  method="PUT"
  action="domain/route/param?query=value"
>
  <input type="hidden" name="delete_id" value="1" />
  <input type="hidden" name="put_id" value="1" />
  <input type="text" name="put_name" value="content_or_not" />
  <div>
    <button name="update_data">Save changes</button>
    <button name="remove_data">Remove</button>
  </div>
</form>
<hr>
<form
  method="DELETE"
  action="domain/route/param?query=value"
>
  <input type="hidden" name="delete_id" value="1" />
  <input type="text" name="delete_name" value="content_or_not" />
  <button name="delete_data">Remove item</button>
</form>

Then JS acts to perform the desired methods:

<script>
   var putMethod = ( event ) => {
     // Prevent redirection of Form Click
     event.preventDefault();
     var target = event.target;
     while ( target.tagName != "FORM" ) {
       target = target.parentElement;
     } // While the target is not te FORM tag, it looks for the parent element
     // The action attribute provides the request URL
     var url = target.getAttribute( "action" );

     // Collect Form Data by prefix "put_" on name attribute
     var bodyForm = target.querySelectorAll( "[name^=put_]");
     var body = {};
     bodyForm.forEach( element => {
       // I used split to separate prefix from worth name attribute
       var nameArray = element.getAttribute( "name" ).split( "_" );
       var name = nameArray[ nameArray.length - 1 ];
       if ( element.tagName != "TEXTAREA" ) {
         var value = element.getAttribute( "value" );
       } else {
       // if element is textarea, value attribute may return null or undefined
         var value = element.innerHTML;
       }
       // all elements with name="put_*" has value registered in body object
       body[ name ] = value;
     } );
     var xhr = new XMLHttpRequest();
     xhr.open( "PUT", url );
     xhr.setRequestHeader( "Content-Type", "application/json" );
     xhr.onload = () => {
       if ( xhr.status === 200 ) {
       // reload() uses cache, reload( true ) force no-cache. I reload the page to make "redirects normal effect" of HTML form when submit. You can manipulate DOM instead.
         location.reload( true );
       } else {
         console.log( xhr.status, xhr.responseText );
       }
     }
     xhr.send( body );
   }

   var deleteMethod = ( event ) => {
     event.preventDefault();
     var confirm = window.confirm( "Certeza em deletar este conteúdo?" );
     if ( confirm ) {
       var target = event.target;
       while ( target.tagName != "FORM" ) {
         target = target.parentElement;
       }
       var url = target.getAttribute( "action" );
       var xhr = new XMLHttpRequest();
       xhr.open( "DELETE", url );
       xhr.setRequestHeader( "Content-Type", "application/json" );
       xhr.onload = () => {
         if ( xhr.status === 200 ) {
           location.reload( true );
           console.log( xhr.responseText );
         } else {
           console.log( xhr.status, xhr.responseText );
         }
       }
       xhr.send();
     }
   }
</script>

With these functions defined, I add a event listener to the buttons which make the form method request:

<script>
  document.querySelectorAll( "[name=update_data], [name=delete_data]" ).forEach( element => {
    var button = element;
    var form = element;
    while ( form.tagName != "FORM" ) {
      form = form.parentElement;
    }
    var method = form.getAttribute( "method" );
    if ( method == "PUT" ) {
      button.addEventListener( "click", putMethod );
    }
    if ( method == "DELETE" ) {
      button.addEventListener( "click", deleteMethod );
    }
  } );
</script>

And for the remove button on the PUT form:

<script>
  document.querySelectorAll( "[name=remove_data]" ).forEach( element => {
    var button = element;
    button.addEventListener( "click", deleteMethod );
</script>

_ - - - - - - - - - - -

This article https://blog.garstasio.com/you-dont-need-jquery/ajax/ helps me a lot!

Beyond this, you can set postMethod function and getMethod to handle POST and GET submit methods as you like instead browser default behavior. You can do whatever you want instead use location.reload(), like show message of successful changes or successful deletion.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

JSFiddle: https://jsfiddle.net/enriquerene/d6jvw52t/53/

Enrique René
  • 510
  • 1
  • 5
  • 19
2

If you are using nodejs, you can install the package method-override that lets you do this using a middleware. Link to documentation: http://expressjs.com/en/resources/middleware/method-override.html

After installing this, all I had to do was the following:

var methodOverride = require('method-override')
app.use(methodOverride('_method'))
Kade
  • 901
  • 13
  • 18
1

I wrote an npm package called 'html-form-enhancer'. By dropping it into your HTML source, it takes over submission of forms with methods aside from GET and POST, and also adds application/json serialization.

<script type=module" src="html-form-enhancer.js"></script>

<form method="PUT">
...
</form>
Evert
  • 93,428
  • 18
  • 118
  • 189
0

In simple words - No.

I have tried to fire a put request in the HTML form, but it sends the POST request to the server. To add the PUT request -

We can do it by listening to the submit action in the script, then fire the put request to a particular endpoint.

Screenshot from the http-server env. test enter image description here