こんにちは、鈴木です。
リンククリック時に POST で送信したい
Rails の link_to で POST としてリクエストを送信したい場合、method オプションで post を指定すると思います。
1 |
link_to('POST で送信', 'http://example.com', method: :post) |
GET ではなく POST でリクエストを送りたい動機としては、次のようなものがあると思います。
- リンク先が POST しか受け付けてくれない。
- リンク先が POST しか受け付けてくれず、パラメータはリクエスト本文で指定したものだけが受け付けられる。(URL にクエリ文字列として含めても受け付けてくれない)。
- リクエストパラメータが多すぎで、URL の最大長を超えてしまう。
一つ目の「リンク先が POST しか受け付けれくれない」という場合は link_to の method オプションで post を指定すれば問題ありませんが、残り二つの場合は上手くいきません。
というのも、link_to の method オプションに post を指定したとしても、パラメータは URL に含まれてしまうからです。
パラメータはリクエスト本文に含めて POST で送信したい
パラメータをリクエスト本文に含めて POST 送信する必要がある場合は、リンクのクリックイベントをフックして、
- 内部的に form 要素を生成する。
- パラメータを <input type="hidden"> として form に追加する。
- form を submit する。
とする必要があります。
これを手軽に行う方法が無いようなので、jQuery プラグインを作成しました( jquery.post_link.js )。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
/** * * リンククリック時に POST でリクエストするようにフックする. * * [使い方] * * HTML で以下のようにリンクを設定しているとする. * * <a href="..." class="post">...</a> * * Javascript で次のように記述することで, 本プラグインを有効化することができる. * * $("a.post").toPostLink(); * * [詳細] * * GET でリクエストする場合に, URL が長すぎるとサーバ側でエラーとなる. * クエリ文字列が長くなりすぎる場合に, この問題が顕在化することが多い. * 対応としてはリクエストを POST で送信することで問題を回避することができる. * * Ruby on Rails では以下のように link_to メソッドのオプションで POST を指定できるが, * クエリ文字列は URL に含まれたままリクエストが送信されるため, この問題の解決にはならない. * * link_to('...', '...', method: :post) * * 本プラグインはリンククリック時に次の処理を行うことで問題を回避する. * * 1. 内部的に form 要素を作成する. * 2. クエリ文字列は <input type="hidden"> として追加する. * 3. 生成した form を submit する. * * MIT License * */ (function($) { $.fn.toPostLink = function() { var escapeHTML = function(html) { return $('<div>').text(html).html(); }; $(this).click(function() { var href = $(this).attr("href").split("#")[0].split("?", 2); var path = href[0]; var query = href[1] || ""; var form = $("<form method='post' action='" + escapeHTML(path) + "'>").appendTo($("body")); // query parameters. $.each(query.split("&"), function() { var pair = this.split("="); var name = decodeURIComponent(pair[0]); var value = decodeURIComponent(pair[1]); $("<input type='hidden' name='" + escapeHTML(name) + "' value='" + escapeHTML(value) + "' />").appendTo(form); }); // csrf token. var csrf_token = $('meta[name=csrf-token]').attr('content'); var csrf_param = $('meta[name=csrf-param]').attr('content'); if (csrf_param !== undefined && csrf_token !== undefined) { $("<input type='hidden' name='" + escapeHTML(csrf_param) + "' value='" + escapeHTML(csrf_token) + "' />").appendTo(form); } form.submit(); return false; }); }; })(jQuery); |
使い方はコメントに書いていますが、POST で送信したいリンクのクラスに post などと指定しておき、
1 |
<a href="..." class="post">...</a> |
Javascript でこのようにします。
1 |
$("a.post").toPostLink(); |
まとめ
検索フォームから一覧表示をする場合、検索結果をブックマークできるように GET で送信することが多いのですが、検索条件が多すぎると URL の最大長を超えてしまい悲しくなる、ということがありました。せっかく対応するのであれば、ということで再利用しやすいように jQuery プラグインとしてまとめました。