静的コンテンツとAPIそれぞれへのHTTPリクエストを Apacheと Javaアプリケーションサーバに振り分ける簡単な設定

Apache HTTP Server

ProxyPassディレクティブで特定のパスを固定的にアプリケーションサーバへ転送するかわりに、静的コンテンツとして処理するかあるいはアプリケーションサーバへリクエストを転送するかの判定を RewriteRuleで動的に行ってみる。

勝手に引用失礼

当社ではまさにその絶対やりたくないそれをしている。少し詳しく言うと、ひと昔前に BlazeDS+Flex (Flashクライアントから、AMFというバイナリフォーマットを用いたHTTP-RPCでサーバ側のJavaメソッドをコールする)なアーキテクチャの業務アプリケーションをいくつか開発したのだが、Flashのオワコン化がそろそろ本格化しており顧客の要望が強くなったため HTML5への置き換えをしているのだ。

Same originポリシーとリバースプロキシ

Flashでもそうだが、原則ブラウザ上で動作するスクリプトは Same originなリソースにしかアクセスできない(※あくまで原則)ため、Flashや HTML/JavaScriptのような静的コンテンツとそこからアクセスされる動的リソース(いわゆるAPI)が同じ Webサーバ(ホストだけでなくポート番号も同じ)の配下にあるように外から見えなければならない。静的コンテンツと APIを別々のサービスで提供しつつ外からは一つに見せるには、リバースプロキシを使う。

表側の Webサーバが裏に居る Javaアプリケーションサーバにリクエストを転送するには、一般的に AJPというバイナリプロトコルを用いる。Apacheには AJPで通信するためのモジュールである mod_proxy_ajpが標準で含まれているが、環境によっては別にインストールする必要があるかもしれない。

リバースプロキシをちょっと柔軟に行う

リクエストに対応する静的コンテンツが存在するかどうかで、そのリクエストを Apacheが処理するかアプリケーションサーバに回すかを動的に決定させると色々なことが楽(先にあまりかっちりパス構造を固めなくていいとか)なのでそうしてみる。

静的コンテンツに対するリクエスト

DocumentRoot以下に当該ファイルが存在するリクエストを受け取った場合、静的コンテンツに対するリクエストとみなし Apacheが処理する。

APIに対するリクエスト

Apacheの管理下に当該ファイルの存在しないリクエストを受け取った場合、動的コンテンツ(API)に対するリクエストとみなしアプリケーションサーバに AJPでリバースプロキシする。

そのための .htaccess

RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) ajp://localhost:8009/$1 [P]

Apacheが .htaccessをいちいち解釈して動作するのでスループット的には不利だが、一秒間に何百ものアクセスがあるようなサービスでなければ問題にならないし、もしそうなったとしてもその時に .htaccessを削除して httpd.confに静的な ProxyPassディレクティブを書けば良いはずだ。またそのような状況では Apacheを Nginxに変えることも選択肢に入るだろう。

DirectoryIndex問題

この方法でリクエストをバックエンドに転送する場合、DirectoryIndexが複数指定されている環境では問題が発生する。例えば DirectoryIndexが index.php index.htmlの順に設定されている時、通常であれば index.phpがあればそれを処理し無ければ index.htmlを探すのだが、先述の Rewrite設定が効いているディレクトリでは index.phpが存在しないと「ファイルが存在しない」という条件を満たしてしまいアプリケーションサーバにリクエストが転送され、結果として index.htmlが存在したとしても無視されてしまう。この問題を回避するには

DirectoryIndex index.html

のようにして DirectoryIndexを一種類に統一しなければならない。どうしても index.phpと index.html(MS-DOS文化を引きずっている場合は index.htmと index.htmlかもしれない)が混在するような環境に対応する必要があるのなら、もう少し複雑な RewriteCondを書く必要があるだろう。

同じカテゴリの記事

mod_extract_forwardedと多段 Proxy 2013年10月15日
DebianのApache2.2で DocumentRootにWebDAVアクセスするための最短手順 2010年8月6日
Sambaのパスワードデータベースを利用してApacheのBASIC認証を行う 2010年6月5日
ApacheとWebDAVとPHP 2010年1月17日

お勧めカテゴリ

英語でアニメ観ようず
なじみ深い日本製アニメの英語版DVDで、字幕と音声から英語を学びましょうという趣旨のシリーズ記事です。
ScalaのようでJavaだけど少しScalaなJSON API
Scalaと Spring Frameworkを使って REST的なJSON APIを実装してみましょう。
ドクジリアン柔術少女 すから☆ぱいそん
代表 嶋田大貴のブログです。写真は神仏に見せ金をはたらく罰当たりの図