web-dev-qa-db-fra.com

Utilisation de la méthode PUT sous forme HTML

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

144
MyTitle

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

105
dqhendricks

Selon le HTML standard , vous pouvez ne pas . Les seules valeurs valides pour l'attribut de méthode sont get et post, correspondant aux méthodes HTTP GET et POST. <form method="put"> est un code HTML non valide et sera traité comme <form>, c'est-à-dire envoyer une demande GET.

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

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

Bien entendu, cela nécessite un décompression côté serveur.

174
phihag

Puis-je utiliser la méthode "Put" au format HTML pour envoyer des données d'un formulaire HTML au serveur?

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

Les formulaires HTML (jusqu'à HTML version 4 (, 5 brouillon) et XHTML 1) ne prennent en charge que GET et POST en tant que méthodes de requête HTTP. Une solution consiste à faire passer d'autres méthodes par le biais de POST en utilisant un champ de formulaire masqué qui est lu par le serveur et la demande envoyée en conséquence. XHTML 2. une fois prévu de prendre en charge GET, POST, PUT et DELETE pour les formulaires, mais il entre dans XHTML5 sur HTML5 , qui ne prévoit pas soutenir PUT. [update to]

Vous pouvez également proposer un formulaire, mais au lieu de le soumettre, créez et déclenchez un XMLHttpRequest à l'aide de la méthode PUT avec JavaScript.

40
hakre

_method solution de contournement du champ caché

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

  • ajoutez un paramètre _method masqué à tout formulaire autre que GET ou POST:

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

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

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

  • traite _method sur le serveur et fait comme si cette méthode avait été envoyée à la place du POST réel

Vous pouvez y parvenir en:

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

Justification/historique des raisons pour lesquelles cela n’est pas possible en HTML pur: https://softwareengineering.stackexchange.com/questions/114156/why-there-are-no-put-and-delete-methods-in-html -forms

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 substitution de méthode à votre formulaire HTML, comme suit:

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

Pour tester vos demandes, vous pouvez utiliser "Postman" une extension google chrome

8
Tofeeq

Pour définir les méthodes PUT et DELETE, procédez 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 Supprimer 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à, vous pouvez définir la fonction postMethod et getMethod pour gérer POST et les méthodes d'envoi GET comme vous le souhaitez, à la place du comportement par défaut du navigateur. Vous pouvez faire ce que vous voulez à la place, utilisez location.reload(), comme afficher le message indiquant que les modifications ou la suppression ont été effectuées avec succès.

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

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

0
Enrique René

tu peux utiliser ça

var form = document.querySelector('#myForm');
var request = new XMLHttpRequest();
request.open('PATCH', url , false);
var get_data = JSON.stringify(form.serializeArray());
request.onload = function() {
    if (this.status >= 200 && this.status < 400) {
        return this.response;
    } else{
        return this.status;
    }
};
request.send(get_data);
console.log(request.response);
0
asmanp2012