1つのform要素でGET/POSTのsubmitを共存

HTMLJavaScriptLaravel

TL;DR

  • formmethod, formaction 属性使え
  • GETリクエストにCSRFトークンが乗ってしまう問題は、2019時点でJSなしではたぶん解決不可能
  • ajax?なにそれおいしいの?

経緯

  • 「条件を入力して帳票出力する」系の機能で、同一form内に複数のsubmitを共存させたくなった

    • HTMLプレビュー

      • ブクマしたいのでGET /preview?検索条件
    • CSVダウンロード

      • ブクマする必要はなく、慣例的にも POST /download
  • POSTが絡むのでCSRFトークン必須
  • 何も考えずに実装すると、GETリクエストにもCSRFトークンが乗ってしまう

やったこと

  • formとCSRFトークンはWebフレームワーク(Laravel 5.5 LTS)に作らせる

    • CSRFトークンはinput[type=hidden][name=_token]
  • formの中にbutton[type=submit]を複数配置し、下記属性を設定

    • formmethod属性: 所属しているformタグのmethod属性値をオーバライド
    • formaction属性: 所属しているformタグのaction属性値をオーバライド
  • このままではGETリクエストにも_tokenが乗ってしまうので、submitボタン押下時に除去するように
 $(function () {
     // GETリクエスト時はCSRFトークン除去
     $('[formaction]').on('click', function (event) {
         if (event.target.getAttribute('formmethod') === 'get') {
             $('[name=_token]').remove()
         }
     });
 });

考えうる別解

所感

  • emacsのeww(テキストブラウザ)をけっこう利用している民としては、これくらいJSに頼らずHTMLだけで完結できてほしいものである

    • HTML5でformmethod属性を策定するときに気づかなかったのかなあ