概要
開発環境とrspecで、APIレスポンスがなんか全然違う・・・開発環境だとステータスコード204なのに、rspecだと500どういうこと?
ということがあったので調査したことまとめ。
前提
参考: ActionController::ImplicitRender
以下のメソッドを使った明示的なレスポンスを返さないコントローラーのアクションメソッドに対して「暗黙的なレンダリング」がなされる。
- render
- respond_to
- redirect
- head
暗黙的なレンダリング
パターン①
https://railsguides.jp/api_app.html
でapiのアプリケーションを構築した場合(= ApplicationControllerをActionController::API から継承している場合)は、
204 No Content
が返るらしい
パターン②
そうでない多くの場合は、implicit_render.rbで定義されているモジュールによって、現状以下のように制御されるらしい。
上から順に優先度高
- テンプレートがある場合それをレンダリング
- 一部一致する?テンプレートがある場合これをレンダリング + ActionController::UnknownFormat 例外発生
- webブラウザからのアクセスと判断された(GETリクエスト & Content-typeがtext/html & リクエストヘッダHTTP_X_REQUESTED_WITHが"XMLHttpRequest")場合 ActionController::MissingExactTemplate 例外発生
- 上記いずれにも引っかからなかった 204 No Content を返す
原因
以下3要因が重なったこと
① APIで明示的なレスポンスをかえしていない
② APIだけど、ApplicationControllerをActionController::APIから継承する構成になってない
③ content-typeをAPIのリクエストヘッダで指定していない
③の場合Webサーバによって推測されたcontent-typeとなり、これが開発環境とrspecで違っていたことで、パターン②の3.になったり4.になったりしていた。
どう対応した?
そもそも「暗黙的なレンダリング」を通ること自体がのぞましくない。
implicit_render.rb自体が過去に色々とアップデートされて暗黙的レンダリングの挙動も変わってきているっぽい
なので、明示的なレスポンスをちゃんと返してやることで対応。