Utilisation de la méthode PUT sous forme HTML

175

Puis-je utiliser une méthode PUT dans un formulaire HTML pour envoyer des données du formulaire à un serveur?

MyTitle
la source

Réponses:

128

Les formulaires XHTML 1.x ne prennent en charge que GET et POST. GET et POST sont les seules valeurs autorisées pour l'attribut "méthode".

dqhendricks
la source
5
XHTML est quelque peu obsolète. Pourtant, il semble que les deux mêmes valeurs soient valides dans html5 developer.mozilla.org/en-US/docs/Web/HTML/Element/…
jakubiszon
194

Selon la norme HTML , vous ne pouvez pas . Les seules valeurs valides pour l'attribut de méthode sont getet post, correspondant aux méthodes HTTP GET et POST. <form method="put">est du HTML invalide et sera traité comme <form>, c'est-à-dire envoyer une requête GET.

Au lieu de cela, de nombreux frameworks utilisent simplement un paramètre POST pour tunneliser la méthode HTTP:

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

Bien sûr, cela nécessite un déballage côté serveur.

Phihag
la source
3
Vous avez lié un brouillon, pas une norme finale. Notez simplement que les versions HTML stables ne l'offrent pas non plus.
hakre
13
@hakre HTML5 est déjà le standard de facto et évoluera probablement avec le temps. Ce que le W3C appelle "Draft" est un document développé sur au moins 3 ans avec la contribution de fournisseurs de navigateurs avec plus de 99%, et a déjà été implémenté (du moins en ce qui concerne cette section et la plupart des sections non ésotériques) par tous pour toujours. Mais juste pour les féroces, voici la définition équivalente en HTML 4.01 (une demande technique dans les termes du W3C).
phihag
S'il vous plaît ne vous sentez pas offensé, j'ai déjà écrit que c'est juste une note et que les autres versions HTML ne l'offrent pas non plus (à une légère exception de XHTML 2, mais c'est un brouillon obsolète maintenant).
hakre
1
@hakre Soyez assuré que je ne suis pas du tout offensé. Nitpicker le nitpicker, je dois dire que XHTML n'est techniquement pas du HTML, bien que l'on puisse trouver une ou deux similitudes;)
phihag
44

Puis-je utiliser la méthode "Put" sous forme html pour envoyer des données du formulaire HTML au serveur?

Oui, vous pouvez, mais gardez à l'esprit que cela n'entraînera pas une requête PUT mais une requête GET. Si vous utilisez une valeur non valide pour l' methodattribut de la <form>balise, le navigateur utilisera la valeur par défaut get.

Les formulaires HTML (jusqu'à la version HTML 4 (, 5 Draft) et XHTML 1) ne prennent en charge que GET et POST comme méthodes de requête HTTP. Une solution de contournement pour cela consiste à tunnel d'autres méthodes via POST en utilisant un champ de formulaire masqué qui est lu par le serveur et la demande distribuée en conséquence. XHTML 2.0 prévoyait autrefois de prendre en charge GET, POST, PUT et DELETE pour les formulaires, mais il va dans XHTML5 de HTML5 , qui ne prévoit pas de prendre en charge PUT. [mise à jour de]

Vous pouvez également proposer un formulaire, mais au lieu de le soumettre, créez et déclenchez une XMLHttpRequest en utilisant la méthode PUT avec JavaScript.

hakre
la source
Une demande AJAX ne peut pas remplacer complètement une demande de formulaire car une demande de formulaire redirige l'utilisateur vers la ressource donnée. Par exemple, il n'y a aucun moyen pour le moment d'afficher dans le navigateur la page de l'itinéraire PUT /resource.
JacopoStanchi
C'est une mauvaise idée de faire ça. Les cadres peuvent ignorer les paramètres de formulaire pour les PUT. Le HTTPServlet de Java semble le faire. Nous avons eu un bogue qui HttpRequest.getParameterMap()ne renvoyait pas les paramètres du formulaire.
DaBlick
@DaBlick: Mais pas pour XMLHttpRequests? Si tel est le cas, le recours à l'API fetch devrait être plus standardisé.
hakre
27

_method solution de contournement de champ masqué

La technique simple suivante est utilisée par quelques frameworks Web:

  • ajoutez un _methodparamètre masqué à tout formulaire qui n'est pas GET ou POST:

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

    Cela peut être fait automatiquement dans les frameworks via la méthode d'aide à la création HTML.

  • corrige la méthode de formulaire réelle à POST ( <form method="post")

  • processus _methodsur le serveur et faites exactement comme si cette méthode avait été envoyée au lieu du POST réel

Vous pouvez y parvenir en:

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

Raison d'être / historique des raisons pour lesquelles cela n'est pas possible en HTML pur: /software/114156/why-there-are-no-put-and-delete-methods-in-html-forms

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
Laravel (php) a la même fonctionnalité en utilisant@method("PATCH")
santiago arizti
Cela semble être une solution de contournement raisonnable, mais toujours malheureuse, car cela rend le débogage difficile. Par exemple, si vous devez parcourir les journaux du serveur ou effectuer une analyse de réseau pour vérifier certaines choses, vous ne verrez pas de sortie correcte, car la méthode HTTP utilisée dans les en-têtes HTTP est toujours POSTet non ce dont vous aviez réellement besoin.
code_dredd
8

Malheureusement, les navigateurs modernes ne fournissent pas de support natif pour les requêtes HTTP PUT. Pour contourner cette limitation, assurez-vous que l'attribut de méthode de votre formulaire HTML est «post», puis ajoutez un paramètre de remplacement de méthode à votre formulaire HTML comme ceci:

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

Pour tester vos demandes, vous pouvez utiliser "Postman" une extension Google Chrome

Tofeeq
la source
1
Cela devrait fonctionner pour n'importe quelle méthode, y compris DELETE AND PATCH, etc.
Tofeeq
1

Pour définir les méthodes PUT et DELETE, je fais comme suit:

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

Ensuite, JS agit pour exécuter les méthodes souhaitées:

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

Avec ces fonctions définies, j'ajoute un écouteur d'événement aux boutons qui font la demande de méthode de formulaire:

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

Et pour le bouton de suppression du formulaire PUT:

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

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

Cet article https://blog.garstasio.com/you-dont-need-jquery/ajax/ m'aide beaucoup!

Au-delà de cela, vous pouvez définir la fonction postMethod et getMethod pour gérer les méthodes d'envoi POST et GET comme vous le souhaitez à la place du comportement par défaut du navigateur. Vous pouvez faire ce que vous voulez à la placelocation.reload() , comme afficher le message des modifications réussies ou la suppression réussie.

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

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

Enrique René
la source