HTMLフォームでのPUTメソッドの使用


175

HTMLフォームでPUTメソッドを使用して、フォームからサーバーにデータを送信できますか?

回答:



194

HTML標準によれば、これはできません。method属性の有効な値はgetand のみでありpost、GETおよびPOST HTTPメソッドに対応しています。<form method="put">は無効なHTMLであり、次のように扱われます<form>ます。つまり、GETリクエストを送信します。

代わりに、多くのフレームワークは単にPOSTパラメータを使用してHTTPメソッドをトンネルします。

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

もちろん、これにはサーバー側のアンラップが必要です。


3
最終基準ではなくドラフトをリンクしています。ただ注意してください。安定したHTMLバージョンはそれを提供しません。
ハクレ

13
@hakre HTML5はすでに事実上の標準であり、おそらく時間の経過とともに進化するでしょう。W3Cが「ドラフト」と呼んでいるものは、99%を超えるブラウザベンダーの入力により少なくとも3年間開発された文書であり、すでに実装されています(少なくとも、このセクションとほとんどの非難解なセクションに関して)。それらのすべてが永遠に。しかし、ちょうどnitpickers のために、これはHTML 4.01(W3Cの用語での技術的な要求)での同等の定義です。
phihag

気分を害さないでください。これは単なるメモであり、他のHTMLバージョンでも提供されないことを既に書いています(XHTML 2のわずかな例外はありますが、現在は古いドラフトです)。
ハクレ

1
@hakre気分を害さないので安心してください。つまらないものをひっくり返して、1つまたは2つの類似点があるかもしれませんが、XHTMLは技術的にはHTMLではないとコメントしなければなりません;)
phihag

44

HTMLフォームの「Put」メソッドを使用して、HTMLフォームからサーバーにデータを送信できますか?

はい、できますが、PUTで​​はなくGETリクエストになることに注意してください。タグのmethod属性に無効な値を使用する<form>と、ブラウザはデフォルト値を使用しますget

HTMLフォーム(HTMLバージョン4(5 Draft)およびXHTML 1まで)は、HTTP要求メソッドとしてGETおよびPOSTのみをサポートします。これの回避策は、サーバーによって読み取られる非表示のフォームフィールドを使用してPOSTを介して他のメソッドをトンネルし、それに応じて要求をディスパッチすることです。XHTML 2.0は、フォームのGET、POST、PUT、DELETEをサポートする予定でしたが、PUT をサポートする予定はないHTML5のXHTML5に入る予定です。[更新]

代わりにフォームを提供することもできますが、フォームを送信する代わりに、JavaScriptでPUTメソッドを使用してXMLHttpRequestを作成して起動します。



AJAX要求は、フォーム要求がユーザーを指定されたリソースにリダイレクトするため、完全にフォーム要求を置き換えることはできません。たとえば、現在のところ、ブラウザにルートのページを表示する方法はありませんPUT /resource
JacopoStanchi 2018

これを行うのは悪い考えです。フレームワークは、PUTのフォームパラメータを無視できます。JavaのHTTPServletのようです。HttpRequest.getParameterMap()フォームパラメータを返さないバグがありました。
DaBlick

@DaBlick:XML​​HttpRequestsは対象外ですか?その場合、フェッチAPIに依存することをより標準化する必要があります。
1

26

_method 隠しフィールドの回避策

次の簡単な手法は、いくつかのWebフレームワークで使用されています。

  • _methodGETまたはPOSTではないフォームに非表示パラメーターを追加します。

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

    これは、HTML作成ヘルパーメソッドを介してフレームワークで自動的に実行できます。

  • 実際のフォームメソッドをPOST(<form method="post")に修正します

  • _methodサーバーでプロセスを実行し、実際のP​​OSTの代わりにそのメソッドが送信された場合とまったく同じように処理します

これは次の方法で実現できます。

  • レール: form_tag
  • Laravel: @method("PATCH")

理論的根拠/純粋なHTMLでは不可能である理由の履歴:https : //softwareengineering.stackexchange.com/questions/114156/why-there-are-no-put-and-delete-methods-in-html-forms


Laravel(php)は同じ機能を使用しています@method("PATCH")
santiago arizti

これは合理的な回避策のように見えますが、デバッグが困難になるため、残念ながらまだ不幸です。たとえば、サーバーログを調べたり、ネットワーク分析を行っていくつかのことを確認したりする必要がある場合は、HTTPヘッダーで使用されているHTTPメソッドがまだPOST必要であり、実際に必要なものではないため、正しい出力が表示されません。
code_dredd

8

残念ながら、最近のブラウザーはHTTP PUT要求のネイティブサポートを提供していません。この制限を回避するには、HTMLフォームのmethod属性が「post」であることを確認してから、次のようにメソッドオーバーライドパラメーターをHTMLフォームに追加します。

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

リクエストをテストするには、Google Chrome拡張機能の「Postman」を使用できます


1
DELETE AND PATCHなどのすべてのメソッドで機能するはずです
Tofeeq 2017

1

メソッドPUTおよびDELETEを設定するには、次のように実行します。

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

次に、JSは必要なメソッドを実行するように動作します。

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

これらの関数を定義したら、フォームメソッドをリクエストするボタンにイベントリスナーを追加します。

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

そして、PUTフォームの削除ボタンの場合:

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

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

この記事https://blog.garstasio.com/you-dont-need-jquery/ajax/は私を大いに助けてくれ!

これ以外に、ブラウザのデフォルトの動作の代わりに、postMethod関数とgetMethodを設定して、POSTおよびGET送信メソッドを好きなように処理できます。代わりに使用したいことは何でもできますlocation.reload()、変更の成功や削除の成功を示すメッセージを表示、好きなます。

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.