HTTPヘッダーはどのようにnginxからRubyアプリへ渡されるのか
現在のWeb開発のほとんどはフレームワークを使って行われています。Rails、Sinatra、Lotusなど、どれを使っていても、Cookieやその他のHTTPヘッダーがnginxやApacheからアプリケーションサーバーを経由してアプリ本体へ届くまでの仕組みについて意識する必要はほとんどありません。自動的に処理されるからです。
しかし、この「ヘッダーの旅」を少し深く掘り下げてみると、そこにはWebの歴史を感じさせる興味深い情報がたくさん詰まっています。
そもそもHTTPヘッダーとは何か?
Webブラウザがリクエストを送信する際には、必ず「HTTPヘッダー」と呼ばれる情報が一緒に送られます。これにはCookie、ユーザーエージェントの情報、キャッシュ関連の情報など、実に多くの有用なデータが含まれています。
実際にどのようなヘッダーが送信されているかは、ブラウザの開発者ツールでリクエストの中身を確認すれば分かります。以下がその例です。ご覧のとおり、ヘッダーには特別な仕掛けは何もありません。単に決められた形式で整形されたテキストにすぎないのです。

ヘッダーは環境変数として直接渡されるわけではない
Rackアプリを書いたことがある方なら、envハッシュを目にしたことがあるでしょう。これはアプリの環境変数を格納したハッシュです。中身を覗いてみると、通常のシステム環境変数に加えて、すべてのリクエストヘッダーも含まれていることに気づくはずです。
# config.ru
run lambda { |env| [200, {"Content-Type" => "text/plain"}, [env.inspect]] }
# 出力例:
# { "HTTP_HOST"=>"localhost:9000", "HTTP_CONNECTION"=>"keep-alive", "HTTP_PRAGMA"=>"no-cache", "HTTP_CACHE_CONTROL"=>"no-cache", "HTTP_ACCEPT"=>"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "HTTP_UPGRADE_INSECURE_REQUESTS"=>"1", "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36", ... }
しかし、これはnginxがヘッダーをアプリへ渡す実際の方法ではありません。:)
アプリケーションサーバーの役割
近年のRuby Webアプリの多くは、Unicornのようなアプリケーションサーバー上で動作しています。アプリサーバーはnginxによって起動されるわけではないため、nginx側からプロセスの環境変数を設定することはできません。
では、ヘッダーはどのようにnginxからUnicornへ伝わるのでしょうか? 答えはシンプルです。nginxがリクエストをアプリサーバーへ転送する際、リクエスト全体――ヘッダーも含めて――をそのまま送り出します。
これを実証するために、nginxから送られてきたすべてのデータをSTDOUTに出力するだけのシンプルなアプリケーションサーバーを作成してみました。
require "socket"
# ソケットを作成し、ファイルシステム上に配置
server = UNIXServer.new('/tmp/socktest.sock')
# 接続(nginxからの)を待ち受ける
socket = server.accept
# ソケットからすべて読み取る
while line = socket.readline
puts line.inspect
end
socket.close
nginxの接続先をUnicornではなくこのサーバーに変更してみると、アプリサーバーに送られている情報が正確に確認できます。それは、ただの普通のHTTPリクエストです。ヘッダー込みで。

シンプルなアップストリーム用アプリサーバーの書き方については、unix socketsに関する記事もあわせてご覧ください。
では、なぜ環境変数なのか?
話は1993年にさかのぼります。当時のNCSAは「Common Gateway Interface」、略してCGIと呼ばれる仕様を公開しました。

これは、ApacheのようなWebサーバーがディスク上の任意のプログラムを実行し、動的なWebページを生成するための仕組みでした。ユーザーがページをリクエストすると、Apacheは文字通り外部プログラムを起動して結果を生成します。Apacheがアプリを直接起動していたため、そのプロセスに対して環境変数を設定することができたのです。
CGI標準では、HTTPヘッダーを環境変数として渡すことが定められています。さらに、既存の環境変数との名前の衝突を避けるため、ヘッダー名の先頭に「HTTP_」を付けることも規定されています。
こうして、次のような環境変数の集合が出来上がりました:
HTTP_ACCEPT="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
HTTP_ACCEPT_CHARSET="ISO-8859-1,utf-8;q=0.7,*;q=0.7"
HTTP_ACCEPT_ENCODING="gzip, deflate"
HTTP_ACCEPT_LANGUAGE="en-us,en;q=0.5"
HTTP_CONNECTION="keep-alive"
HTTP_HOST="example.com"
HTTP_USER_AGENT="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0"
今日、新規開発でCGIを使うことはほとんどありませんが、HTTPヘッダーが環境変数という形式で扱われるスタイルは今でも非常に一般的です。ただし、場合によってはそれが「偽物の」環境変数であることもあります。
アプリサーバーはどうやって「偽装」しているのか
アプリケーションサーバーは、生のHTTPリクエストを解析してヘッダーを取り出します。では、どうやってそれらを環境変数として扱っているのでしょうか? 答えは、アプリサーバー自身がそこへ投入しているからです。
試しにwebrickのソースコードを調べてみたところ、決定的な証拠となるコードを見つけました:
self.each{|key, val|
next if /^content-type$/i =~ key
next if /^content-length$/i =~ key
name = "HTTP_" + key
name.gsub!(/-/o, "_")
name.upcase!
meta[name] = val
}
こうして作られた「偽物の」環境変数は、やがて本物のシステム環境変数とマージされ、Rackアプリへ、そしてRailsへと引き渡されます。Rails側では、それらを再び環境変数ハッシュから取り出して利用するわけです。:)
-
【保存版】macOSからSearchMineを完全に削除する方法|Safari・Chrome・Firefoxの乗っ取りを解消
MacでSearchMineという不審なマルウェアに悩まされていませんか?この記事では、Macからこの厄介なマルウェアを完全に除去し、Safari・Chrome・Firefoxが悪質なSearchmine.netサイトへ勝手にリダイレクトされる問題を解決する方法を詳しく解説します。「無料」という言葉には、つい目を奪われてしまいがちです。特に若い世代はダウンロード時の注意喚起を軽視しがちですが、「タダより高いものはない」という鉄則は忘れてはいけません。そもそも、誰かが時間とコストをかけてウェブサイトを作り、何かを無料で提供する理由は何でしょうか?純粋な善意なのでしょうか?それとも何らかの詐欺行為
-
パソコンからiPhoneへお気に入りの曲を転送する方法
パソコンに保存しているお気に入りの曲をiPhoneに転送したいと思ったことはありませんか?Androidスマートフォンと違い、iPhoneはケーブルで接続するだけですぐに音楽や動画をコピーできるわけではありません。しかし、だからといって同じ曲をもう一度購入する必要はありません。実は、パソコン(Windows・Mac)からiPhoneへ音楽を簡単に転送する方法があるのです。 ここでは、iTunesを使ってパソコンからiPhoneに音楽を転送する手順を詳しく解説します。 iTunesで音楽を転送する手順 iTunesをダウンロードする:まず、Appleの公式サイトから最新版のiTunesをダウン