Menggunakan metode PUT dalam bentuk HTML

175

Bisakah saya menggunakan metode PUT dalam formulir HTML untuk mengirim data dari formulir ke server?

MyTitle
sumber

Jawaban:

128

Formulir XHTML 1.x hanya mendukung GET dan POST. GET dan POST adalah satu-satunya nilai yang diizinkan untuk atribut "metode".

dqhendricks
sumber
5
XHTML agak ketinggalan jaman. Namun sepertinya dua nilai yang sama berlaku di html5 developer.mozilla.org/en-US/docs/Web/HTML/Element/…
jakubiszon
194

Menurut standar HTML , Anda tidak bisa . Satu-satunya nilai yang valid untuk atribut metode adalah getdan post, sesuai dengan metode GET dan POST HTTP. <form method="put">tidak valid HTML dan akan diperlakukan seperti <form>, yaitu mengirim permintaan GET.

Sebagai gantinya, banyak kerangka kerja hanya menggunakan parameter POST untuk tunnel metode HTTP:

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

Tentu saja, ini membutuhkan pembukaan sisi server.

phihag
sumber
3
Anda telah menghubungkan draf, bukan standar akhir. Hanya mencatat, versi HTML yang stabil juga tidak menawarkannya.
hakre
13
@Hakre HTML5 sudah merupakan standar de-facto, dan mungkin akan berkembang seiring waktu. Apa yang disebut W3C "Draft" adalah dokumen yang dikembangkan lebih dari 3 tahun dengan masukan dari vendor peramban dengan lebih dari> 99%, dan telah diterapkan (setidaknya ketika sampai pada bagian ini dan sebagian besar non-esoterik) oleh semuanya selamanya. Tetapi hanya untuk nitpickers, inilah definisi yang setara dalam HTML 4.01 (Permintaan Teknis dalam istilah W3C).
phihag
Tolong jangan merasa tersinggung, saya sudah menulis bahwa itu hanya sebuah catatan dan bahwa versi HTML lainnya juga tidak menawarkannya (dengan sedikit pengecualian XHTML 2, tapi itu konsep usang sekarang).
hakre
1
@ HAKRE Yakinlah aku tidak tersinggung sama sekali. Nitpicking the nitpicker, saya harus berkomentar bahwa XHTML secara teknis bukan HTML, meskipun orang mungkin menemukan satu atau dua kesamaan;)
phihag
44

Bisakah saya menggunakan metode "Put" dalam bentuk html untuk mengirim data dari Formulir HTML ke server?

Ya Anda bisa, tetapi perlu diingat bahwa itu tidak akan menghasilkan PUT tetapi permintaan GET. Jika Anda menggunakan nilai yang tidak valid untuk methodatribut <form>tag, browser akan menggunakan nilai default get.

Formulir HTML (hingga HTML versi 4 (, 5 Draf) dan XHTML 1) hanya mendukung GET dan POST sebagai metode permintaan HTTP. Solusi untuk ini adalah untuk tunnel metode lain melalui POST dengan menggunakan bidang formulir tersembunyi yang dibaca oleh server dan permintaan dikirim sesuai. XHTML 2.0 pernah direncanakan untuk mendukung GET, POST, PUT dan DELETE untuk formulir, tetapi akan masuk ke XHTML5 dari HTML5 , yang tidak berencana untuk mendukung PUT. [perbarui ke]

Anda juga dapat menawarkan formulir, tetapi alih-alih mengirimkannya, buat dan jalankan XMLHttpRequest menggunakan metode PUT dengan JavaScript.

hakre
sumber
Permintaan AJAX tidak dapat sepenuhnya menggantikan permintaan formulir karena permintaan formulir mengarahkan pengguna ke sumber daya yang diberikan. Misalnya tidak ada cara pada saat ini untuk menampilkan di browser halaman rute PUT /resource.
JacopoStanchi
Itu ide yang buruk untuk melakukan ini. Kerangka kerja dapat mengabaikan parameter formulir untuk PUT. HTTPServlet Java tampaknya. Kami memiliki bug di mana HttpRequest.getParameterMap()tidak mengembalikan parameter formulir.
DaBlick
@ David Blick: Tapi tidak untuk XMLHttpRequests? Jika demikian maka mengandalkan fetch API harus lebih terstandarisasi.
hakre
27

_method solusi bidang tersembunyi

Teknik sederhana berikut digunakan oleh beberapa kerangka kerja web:

  • tambahkan _methodparameter tersembunyi ke formulir apa pun yang bukan GET atau POST:

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

    Ini dapat dilakukan secara otomatis dalam kerangka kerja melalui metode pembantu pembuatan HTML.

  • perbaiki metode form aktual ke POST ( <form method="post")

  • memproses _methoddi server dan melakukan persis seolah-olah metode yang telah dikirim bukan POST yang sebenarnya

Anda dapat mencapai ini di:

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

Dasar pemikiran / sejarah mengapa itu tidak mungkin dalam HTML murni: /software/114156/why-there-are-no-put-and-delete-methods-in-html-forms

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
Laravel (php) memiliki fitur yang sama dengan menggunakan@method("PATCH")
santiago arizti
Sepertinya solusi yang masuk akal, tetapi masih disayangkan, karena itu membuat debugging sulit. Misalnya, jika Anda perlu menelusuri log server atau melakukan analisis jaringan untuk memverifikasi beberapa hal, Anda tidak akan melihat output yang benar, karena metode HTTP yang digunakan dalam header HTTP masih POSTdan bukan apa yang sebenarnya Anda butuhkan.
code_dredd
8

Sayangnya, browser modern tidak menyediakan dukungan asli untuk permintaan HTTP PUT. Untuk mengatasi batasan ini, pastikan atribut metode formulir HTML Anda adalah "posting", lalu tambahkan metode override parameter ke formulir HTML Anda seperti ini:

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

Untuk menguji permintaan Anda, Anda dapat menggunakan "tukang pos" ekstensi google chrome

Tofik
sumber
1
Ini harus bekerja untuk metode apa pun termasuk HAPUS DAN PATCH dll
Tofeeq
1

Untuk mengatur metode PUT dan HAPUS saya lakukan sebagai berikut:

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

Kemudian JS bertindak untuk melakukan metode yang diinginkan:

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

Dengan fungsi-fungsi ini didefinisikan, saya menambahkan pendengar acara ke tombol-tombol yang membuat permintaan metode formulir:

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

Dan untuk tombol hapus pada formulir PUT:

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

_ - - - - - - - - - -

Artikel ini https://blog.garstasio.com/you-dont-need-jquery/ajax/ banyak membantu saya!

Di luar ini, Anda dapat mengatur fungsi postMethod dan getMethod untuk menangani metode POST dan GET mengirimkan yang Anda inginkan sebagai gantinya perilaku default browser. Anda dapat melakukan apa pun yang ingin Anda gunakan sebagai gantinya location.reload(), seperti menampilkan pesan perubahan yang berhasil atau penghapusan yang sukses.

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

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

Enrique René
sumber