現象
Railsで500エラーが発生し、エラーログにはActionView::MissingTemplateと書かれていました。
media/ads/show.erbは存在し、これまで問題なく表示できていたURLだったので、なぜ??となりました。
エラーログの:formats=>["image/*"]を見る限り画像のテンプレートを探しに行ってしまっているようなのですが、URLに.png
や.jpg
などの拡張子が付いている訳でもありませんでした。
ActionView::MissingTemplate (Missing template media/ads/show, media/application/show, application/show with {:locale=>[:ja], :formats=>["image/*"], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder]}. Searched in:
結論
acceptヘッダーにimage/*
を指定することで再現しました。
おそらく、リンク先の画像を一括ダウンロードするようなブラウザ拡張の対象URLに引っかかってしまったのだと思います。
curl '<URL>' -H 'accept: image/*;'
解決方法(方針)
画像のformatを弾く方針で考えてますが、formatが指定されている訳ではないのでできるか不明です。
対応完了したら追記します。
詳細
formatsを取得している処理はactionpackライブラリのmine_negotiation.rb
に書かれていました。
(actionpack-5.0.2を使用しています。)
def formats
fetch_header("action_dispatch.request.formats") do |k|
params_readable = begin
parameters[:format]
rescue ActionController::BadRequest
false
end
v = if params_readable
Array(Mime[parameters[:format]])
elsif use_accept_header && valid_accept_header
accepts
elsif extension_format = format_from_path_extension
[extension_format]
elsif xhr?
[Mime[:js]]
else
[Mime[:html]]
end
set_header k, v
end
end
今回、拡張子が指定されていないのでparams_readable
はnilになります。
そして、HTTPリクエストのacceptヘッダーにimage/*
を指定したので、use_accept_headerメソッドとvalid_accept_header
メソッドは共にtrue
を返します。
結果、accepts
メソッドが呼び出され、image/*
をもつMine.Typeインスタンスがformatsの結果として返されます。