Usando el método PUT en forma HTML

175

¿Puedo usar un método PUT en un formulario HTML para enviar datos del formulario a un servidor?

Mi título
fuente

Respuestas:

128

Los formularios XHTML 1.x solo admiten GET y POST. GET y POST son los únicos valores permitidos para el atributo "método".

dqhendricks
fuente
55
XHTML está algo desactualizado. Todavía parece que los mismos dos valores son válidos en html5 developer.mozilla.org/en-US/docs/Web/HTML/Element/…
jakubiszon
194

De acuerdo con el estándar HTML , puede que no . Los únicos valores válidos para el atributo del método son gety post, correspondientes a los métodos HTTP GET y POST. <form method="put">es HTML no válido y será tratado como <form>, es decir, enviará una solicitud GET.

En cambio, muchos marcos simplemente usan un parámetro POST para tunelizar el método HTTP:

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

Por supuesto, esto requiere desenvolver del lado del servidor.

phihag
fuente
3
Ha estado vinculando un borrador, no un estándar final. Solo notando, las versiones HTML estables tampoco lo ofrecen.
Hakre
13
@hakre HTML5 ya es el estándar de facto y probablemente evolucionará con el tiempo. Lo que el W3C llama "Borrador" es un documento documentado desarrollado durante al menos 3 años con el aporte de proveedores de navegadores con más de> 99%, y ya ha sido implementado (al menos cuando se trata de esta y la mayoría de las secciones no esotéricas) por Todos ellos para siempre. Pero solo para nitpickers, aquí está la definición equivalente en HTML 4.01 (una solicitud técnica en los términos del W3C).
phihag
Por favor, no se sienta ofendido, ya escribí que es solo una nota y que las otras versiones HTML tampoco lo ofrecen (con una ligera excepción de XHTML 2, pero ahora es un borrador obsoleto).
Hakre
1
@hakre Tenga la seguridad de que no me ofende en absoluto. Nitpicking el nitpicker, debo comentar que XHTML técnicamente no es HTML, aunque uno podría encontrar una o dos similitudes;)
phihag
44

¿Puedo usar el método "Put" en formato html para enviar datos desde el formulario HTML al servidor?

Sí, puede, pero tenga en cuenta que no dará como resultado una PUT sino una solicitud GET. Si usa un valor no válido para el methodatributo de la <form>etiqueta, el navegador usará el valor predeterminado get.

Los formularios HTML (hasta HTML versión 4 (5 Draft) y XHTML 1) solo admiten GET y POST como métodos de solicitud HTTP. Una solución para esto es hacer un túnel de otros métodos a través de POST mediante el uso de un campo de formulario oculto que es leído por el servidor y la solicitud se despacha en consecuencia. XHTML 2.0 una vez planeó admitir GET, POST, PUT y DELETE para formularios, pero entrará en XHTML5 de HTML5 , que no planea admitir PUT. [actualización para]

Alternativamente, puede ofrecer un formulario, pero en lugar de enviarlo, cree y active un XMLHttpRequest utilizando el método PUT con JavaScript.

hakre
fuente
Una solicitud AJAX no puede reemplazar completamente una solicitud de formulario porque una solicitud de formulario redirige al usuario al recurso dado. Por ejemplo, en este momento no hay forma de mostrar en el navegador la página de la ruta PUT /resource.
JacopoStanchi
Es una mala idea hacer esto. Los marcos pueden ignorar los parámetros de formulario para PUT. El HTTPServlet de Java parece hacerlo. Tuvimos un error HttpRequest.getParameterMap()que no devolvió los parámetros del formulario.
DaBlick el
@DaBlick: ¿Pero no para XMLHttpRequests? Si es así, confiar en la API de recuperación debería estar más estandarizado.
Hakre
27

_method solución de campo oculto

La siguiente técnica simple es utilizada por algunos marcos web:

  • agregue un _methodparámetro oculto a cualquier formulario que no sea GET o POST:

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

    Esto se puede hacer automáticamente en marcos a través del método auxiliar de creación HTML.

  • arregle el método de formulario real a POST ( <form method="post")

  • procesa _methoden el servidor y hace exactamente como si ese método hubiera sido enviado en lugar de la POST real

Puedes lograr esto en:

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

Justificación / historia de por qué no es posible en HTML puro: /software/114156/why-there-are-no-put-and-delete-methods-in-html-forms

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
Laravel (php) tiene la misma característica al usar@method("PATCH")
santiago arizti
Parece una solución razonable, pero desafortunada, ya que dificulta la depuración. Por ejemplo, si necesita revisar los registros del servidor o hacer un análisis de red para verificar algunas cosas, no verá la salida correcta, ya que el método HTTP que se usa en los encabezados HTTP sigue siendo POSTy no lo que realmente necesitaba.
code_dredd
8

Desafortunadamente, los navegadores modernos no ofrecen soporte nativo para solicitudes HTTP PUT. Para evitar esta limitación, asegúrese de que el atributo de método de su formulario HTML sea "post", luego agregue un parámetro de anulación de método a su formulario HTML como este:

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

Para probar sus solicitudes, puede usar "Postman", una extensión de Google Chrome

Tofeeq
fuente
1
Debería funcionar para cualquier método, incluyendo ELIMINAR Y
REPARAR
1

Para configurar los métodos PUT y DELETE, realizo lo siguiente:

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

Entonces JS actúa para realizar los métodos deseados:

<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 estas funciones definidas, agrego un detector de eventos a los botones que realizan la solicitud del método de formulario:

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

Y para el botón Eliminar en el formulario PUT:

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

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

¡Este artículo https://blog.garstasio.com/you-dont-need-jquery/ajax/ me ayuda mucho!

Más allá de esto, puede configurar la función postMethod y getMethod para manejar los métodos de envío POST y GET como desee en lugar del comportamiento predeterminado del navegador. Puede hacer lo que quiera usar location.reload(), como mostrar un mensaje de cambios exitosos o eliminación exitosa.

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

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

Enrique René
fuente