Ruby on Railsで記述したWebアプリケーションでは,ERBファイルに<%= link_to '/hogehoge', method: :put %>
などと記述することにより,aタグがクリックされたときにPUTリクエストを投げることができます.POST,DELETEに関しても同様の記述でリクエストを投げることができます.
本記事では,Sinatraで記述したWebアプリケーションについても同様に,aタグがクリックされたときに任意のHTTPメソッドでリクエストを投げる方法を解説します.
やりかた
app.rb
を↓のように書き、
require 'sinatra' class Rack::MethodOverride ALLOWED_METHODS=%w[POST GET] def method_override(env) req = Rack::Request.new(env) method = req.params[METHOD_OVERRIDE_PARAM_KEY] || env[HTTP_METHOD_OVERRIDE_HEADER] method.to_s.upcase end end enable :method_override put '/hoge' do # do awesome things end
htmlの方で↓のように a
タグを書きます。
<a href='/hoge?_method=PUT&hoge=fuga'>PUTを投げる</a>
このリンクをクリックすると、hoge=fuga
という内容のPUTリクエストが飛びます。
注意 :クローラがやってくるとPOST/PUT/DELETEリクエストが飛びまくります。クローラがやってくるWebアプリケーションでこれをやるのは絶対にやめたほうが良いでしょう。
解説
enable :method_override
によってRack::MethodOverrideミドルウェアを有効にし、その挙動を変えています。
以下でこれを説明します。
Rack::MethodOverride とはなにか
Rack::MethodOverrideとは、 リクエストに含まれる _method
というパラメータを読み取って、HTTPのmethodを書き換えてくれるRack middlewareです。
例えば _method=PUT
という値をリクエストに入れると、PUTリクエストとして処理されるわけです。
しかし、Rack::MethodOverrideが「method書き換え」をしてくれるのは、元々のmethodが POSTの場合だけ です。
従って、GETリクエストで_method
パラメータを指定してもmethod書き換えは起こりません。
また、 _method
という値はPOSTパラメータに入っている必要があります。
このため、Query Stringに _method=PUT
と書いてリクエストを投げてもPUTリクエストにならないというわけです。
Rack::MethodOverride の挙動を変更する
では、目的であるところの「 a
タグがクリックされたときに POST/PUT/DELETE のリクエストを投げる」を実現するためには、 Rack::MethodOverrideの挙動をどのように変更すれば良いでしょうか。
これは簡単で、
- GETリクエストについても「method書き換え」をするようにする
_method
パラメータをQuery Stringからも読み取るようにする
の2点について変更すれば良いわけです。
前者に関しては、Rack::MethodOverride::ALLOWED_METHODS
の値を %w[POST]
から %w[POST GET]
に変更してやれば良いです。
また、後者に関しては、Rack::MethodOverride#method_override
をオーバーライドして、↓のように1 req.params
2 から _method
パラメータを取得するようにすれば良いです。
# before method = req.POST[METHOD_OVERRIDE_PARAM_KEY] || env[HTTP_METHOD_OVERRIDE_HEADER] # afrer method = req.params[METHOD_OVERRIDE_PARAM_KEY] || env[HTTP_METHOD_OVERRIDE_HEADER]
参考
- Rack::MethodOverrideを少しいじった話 - 【旧】PerlerのRuby日記->はてなブログに移行しました
- Class: Rack::MethodOverride — Documentation for rack (2.0.6)
はじめてのRuby Sinatra入門: 軽量RubyフレームワークSinatraとPaizaCloudを使って10分でWebサービスを作る
- 作者: 吉岡恒夫
- 発売日: 2018/03/11
- メディア: Kindle版
- この商品を含むブログを見る
- 作者: Paolo Perrotta,角征典
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/10/10
- メディア: 大型本
- この商品を含むブログ (3件) を見る
-
実際のコードはエラー処理が入っており、もう少し複雑である(https://github.com/rack/rack/blob/bfd4c155a9ba2fb1fcee8daab433fbdef582cce2/lib/rack/method_override.rb#L27)↩
-
req.params
はQuery Stringのパラメータとrequest bodyのパラメータが合成されたもの↩