tl;dr
Rails で "cannot parse Cookie header: invalid %-encoding" ってエラーが頻発したら、
morenocarullo/rack-cleancookies を使って不正な cookie を無視するようにすると解決します。
試してみよう
おもむろにブラウザであなたの Rails アプリを開き、コンソールから
document.cookie = "hi=%;"
と入力して、ページをリロードしてみましょう。
500 が出ましたか?
エラー出た?
はい、cookie に "%" という文字列が入ると Rack が 500 を返します。
この挙動に関する議論は
- "invalid %-encoding" error leaves rack.request.cookie_hash == nil · Issue #225 · rack/rack
- bad diagnostics for malformed cookies · Issue #2622 · rails/rails
などにあります。
あり得そうなストーリー
「なんで cookie に "%" いれなあかんねん」と感じるかもしれません。しかし、あり得るストーリーとしては、Google Analytics で流入元をトラッキングする際に、例えばキャンペーン名を「10%OFF」として、
http://example.com/?utm_source=...&utm_medium=...&utm_campaign=100%25OFF
なんて URL を載せてしまうかもしれません。
この URL にアクセスすると、Google Analytics は utm_campaign
の値を cookie に保存してしまい、その cookie を持ったままアクセスするとエラーが発生します。エラーが起きても cookie は勝手に消えないので、このリンクを踏んだブラウザでは恒常的にエラーが出続けます。
これ、ハマりそうな予感がしませんか。
対策
morenocarullo/rack-cleancookies という Rack ミドルウェアを使って、不正な cookie を無視するようにすると、エラーにはならなくなります。
Gemfile に
gem 'rack-cleancookies'
と書いて bundle install
し、
if defined?(Rails.configuration) && Rails.configuration.respond_to?(:middleware)
Rails.configuration.middleware.insert_before ActionDispatch::Cookies, Rack::CleanCookies::Middleware
end
というコードを config/initializers/clean_cookies.rb
あたりに仕込みます。
この Rack ミドルウェアでは、invalid %-encoding
が出る cookie を除外して、次の Rack ミドルウェアに渡します。
ActionDispatch::Cookies
の前に登録しているため、エラーを起こさないというわけです。
初 Qiita でした。