iOSアプリからリクエストヘッダーに情報を追加して送る、みたいなことをやろうとして少しはまりました。

受け取る人はRailsアプリです。ローカルで開発しているときには問題なかったのにAWS上のapache + passengerの環境にデプロイしたら当該ヘッダー情報が抜けてました。

環境依存っぽいのでapacheかpassengerを疑って色々調べていると、最終的には

Starting with version 2.4, Apache is more strict about how HTTP headers are converted to environment variables in mod_cgi and other modules: Previously any invalid characters in header names were simply translated to underscores. This allowed for some potential cross-site-scripting attacks via header injection (see Unusual Web Bugs, slide 1920).

という、Apacheのドキュメントに到達。

該当箇所をGoogle翻訳するとこんな感じ。

2.4より、Apacheはmod_cgiや他のモジュールでHTTPヘッダーを環境変数に変換する方が厳密です。以前はヘッダ名の無効な文字はすべて下線に変換されていました。 これにより、ヘッダインジェクションによるいくつかのクロスサイトスクリプティング攻撃が可能になりました(Unusual Web Bugs、slide 19/20を参照)。

まあつまりアンダースコアが入ってるのはおかしいと判定するみたいですね。まさにアンダースコアをうっかり使っちゃってたのでRailsまで届いてないのは当然っちゃ当然だったわけです。

ちなみに、Rails側でちゃんとヘッダーが来ているかどうかを見るために↓のURLを参考にしてログに出力して確認しました。

Rails でリクエストの HTTP ヘッダを取得してログに出力する - xykのブログ
環境:rails 4.2.0 Rails でリクエストの HTTP ヘッダはrequest.headersから取得できる。 すべてログに出力するなら # すべてログに出力する request.headers.sort.map { |k, v| logger.info "#{k}:#{v}" } 個別に取得するなら # ユーザーエージェントを取得する request.headers[:HTTP_USER_AGENT] request.envからでも取得できる。 # ユーザーエージェントを取得する request.env['HTTP_USER_AGENT'] 今回やりたいことはクライアント側から …

request.headers.sort.map { |k, v| Rails.logger.info "#{k}:#{v}" }