Utilizzo del metodo PUT in formato HTML


175

Posso utilizzare un metodo PUT in un modulo HTML per inviare dati dal modulo a un server?

Risposte:



194

Secondo il codice HTML standard , è possibile non . Gli unici valori validi per l'attributo method sono gete post, corrispondenti ai metodi GET e POST HTTP. <form method="put">non è un codice HTML valido e verrà trattato come <form>, ovvero invia una richiesta GET.

Al contrario, molti framework utilizzano semplicemente un parametro POST per eseguire il tunneling del metodo HTTP:

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

Ovviamente, questo richiede il wrapping sul lato server.


3
Hai collegato una bozza, non uno standard finale. Solo notando, le versioni HTML stabili non lo offrono neanche.
Hakre,

13
@hakre HTML5 è già lo standard di fatto e probabilmente si evolverà nel tempo. Quello che il W3C chiama "Bozza" è un documento sviluppato in almeno 3 anni con l'input dei fornitori di browser con oltre il> 99% ed è già stato implementato (almeno quando si tratta di questa e la maggior parte delle sezioni non esoteriche) da tutti per sempre. Ma solo per i nitpicker, ecco la definizione equivalente in HTML 4.01 (una richiesta tecnica nei termini del W3C).
phihag

Per favore, non sentirti offeso, ho già scritto che è solo una nota e che le altre versioni HTML non lo offrono neanche (con una leggera eccezione di XHTML 2, ma ora è una bozza obsoleta).
Hakre,

1
@hakre State tranquilli che non mi offendo affatto. Nitpicker il nitpicker, devo commentare che XHTML non è tecnicamente HTML, sebbene si possano trovare una o due somiglianze;)
phihag

44

Posso usare il metodo "Put" in formato html per inviare dati dal modulo HTML al server?

Sì, puoi, ma tieni presente che non si tradurrà in un PUT ma in una richiesta GET. Se si utilizza un valore non valido per l' methodattributo del <form>tag, il browser utilizzerà il valore predefinito get.

I moduli HTML (fino alla versione HTML 4 (, 5 Draft) e XHTML 1) supportano GET e POST solo come metodi di richiesta HTTP. Per ovviare a questo problema, eseguire il tunneling di altri metodi tramite POST utilizzando un campo modulo nascosto che viene letto dal server e la richiesta inviata di conseguenza. XHTML 2.0 una volta pianificato per supportare GET, POST, PUT e DELETE per i moduli, ma sta andando in XHTML5 di HTML5 , che non prevede di supportare PUT. [aggiorna a]

In alternativa puoi offrire un modulo, ma invece di inviarlo, crea ed esegui XMLHttpRequest usando il metodo PUT con JavaScript.



Una richiesta AJAX non può sostituire completamente una richiesta di modulo poiché una richiesta di modulo reindirizza l'utente a una determinata risorsa. Ad esempio, al momento non è possibile mostrare nel browser la pagina del percorso PUT /resource.
JacopoStanchi,

È una cattiva idea farlo. I frame possono ignorare i parametri del modulo per i PUT. HTTPServlet di Java sembra. Si è verificato un errore in cui HttpRequest.getParameterMap()non sono stati restituiti parametri del modulo.
DaBlick

@DaBlick: ma non per XMLHttpRequests? In tal caso, fare affidamento sull'API di recupero dovrebbe essere più standardizzato.
Hacre,

27

_method soluzione al campo nascosto

La seguente semplice tecnica viene utilizzata da alcuni framework Web:

  • aggiungi un _methodparametro nascosto a qualsiasi modulo che non sia GET o POST:

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

    Questo può essere fatto automaticamente nei framework tramite il metodo helper di creazione HTML.

  • correggere il metodo del modulo effettivo su POST ( <form method="post")

  • si elabora _methodsul server e fa esattamente come se quel metodo fosse stato inviato al posto del POST effettivo

Puoi farlo in:

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

Razionale / storia del perché non è possibile in puro HTML: /software/114156/why-there-are-no-put-and-delete-methods-in-html-forms


Laravel (php) ha la stessa funzione usando@method("PATCH")
santiago arizti il

Sembra una soluzione ragionevole, ma comunque sfortunata, poiché rende difficile il debug. Ad esempio, se è necessario esaminare i log del server o eseguire analisi di rete per verificare alcune cose, non verrà visualizzato l'output corretto, poiché il metodo HTTP utilizzato nelle intestazioni HTTP è ancora POSTe non quello di cui si ha effettivamente bisogno.
code_dredd,

8

Sfortunatamente, i browser moderni non forniscono supporto nativo per le richieste HTTP PUT. Per aggirare questa limitazione, assicurarsi che l'attributo del metodo del modulo HTML sia "post", quindi aggiungere un parametro di sostituzione del metodo al modulo HTML in questo modo:

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

Per testare le tue richieste puoi utilizzare "Postman" un'estensione di Google Chrome


1
Dovrebbe funzionare con qualsiasi metodo incluso DELETE AND PATCH ecc.
Tofeeq

1

Per impostare i metodi PUT e DELETE eseguo come segue:

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

Quindi JS agisce per eseguire i metodi desiderati:

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

Con queste funzioni definite, aggiungo un listener di eventi ai pulsanti che richiedono il metodo del modulo:

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

E per il pulsante Rimuovi sul modulo PUT:

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

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

Questo articolo https://blog.garstasio.com/you-dont-need-jquery/ajax/ mi aiuta molto!

Oltre a ciò, puoi impostare la funzione postMethod e getMethod per gestire i metodi di invio POST e GET come preferisci invece il comportamento predefinito del browser. Puoi fare quello che vuoi invece usare location.reload(), come mostrare il messaggio di modifiche riuscite o cancellazione riuscita.

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

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.