ボクココ

個人開発に関するテックブログ

rails-api は デフォルトの middleware に要注意

いや〜ハマったハマった。 rails-api っていうフルスタックのRailsからAPIに特化した構成に削ぎ落としてくれるGemがあるんだけど、これで「何が削られているのか」をちゃんと把握してないとハマる。

基本的なRailsアプリとrails-api の Middleware 比較

rake タスクを実行すれば見れる。

フルスタック

$ bundle exec rake middleware

use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fe29f9cc6e0>
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use BetterErrors::Middleware
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
run MyApp::Application.routes

rails-api

use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fac42102e08>
use Rack::Runtime
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
run MyApp::Application.routes

今回ハマったのは use Rack::MethodOverride。これは putとかpatchとかのリクエスト送るときにformのmethodは"post”にしておいて、hiddenパラメータで_method="patch"ってのを指定することで擬似的にPATCHリクエストを実現するための仕組み。 なんと、rails-apiではデフォルトではこのRack::MethodOverrideが搭載されていないのだ。

てことで config/application.rb に

    config.middleware.use Rack::MethodOverride

を追加して解決した。

今回自分がやりたかったのは、作ったAPIを実験するためのhtml集を作っていて(もちろんテストコードも書いてます)、そこで _methodをpatchにしても全部 post として解釈されてしまって3時間くらいハマった。

ソースコードで _method でgrepしてrails コアの該当箇所を見つけて原因を特定して頑張った。 一件落着。