前回はmod_proxy_htmlについて説明しました。今回はmod_proxy_htmlの具体的な設定について載せていきます。
mod_prxoy_htmlはリバースプロキシサーバーに組み込むモジュールのため、前回の説明に使った構成図の環境を作成する流れで説明します。
システム構成
システム構成はmod_proxy_htmlがインストールされたリバースプロキシ、アプリケーション1、アプリケーション2の3つの環境です。
リバースプロキシの環境は CentOS7 を使用します。
アプリケーション1、アプリケーション2は何でも良いのでWebサーバーを動かしておきます。(本記事では割愛します。)
mod_proxy_htmlのインストール
mod_proxy_html を実際に試してみましょう。mod_proxy_html は CentOS7 の標準パッケージに含まれているのでyumコマンドでインストールを行うことができます。
- mod_proxy_htmlインストール
# yum install mod_proxy_html
yum でインストールすると/etc/httpd/conf.modules.d/00-proxyhtml.conf
が配置されますので、Apacheの再起動によってモジュールがロードされる構成となります。
それではhttpd.conf に mod_proxy_html の設定を行います。
httpd.confの設定
リバースプロキシサーバーのhttpd.confに設定を記載します。(本記事ではリバースプロキシに関連した設定のみ扱います。)
URL変換対象のHTMLのタグ
URLの変換を行うHTMLタグの設定です。
ProxyHTMLLinks a href
ProxyHTMLLinks area href
ProxyHTMLLinks link href
ProxyHTMLLinks img src longdesc usemap
ProxyHTMLLinks object classid codebase data usemap
ProxyHTMLLinks q cite
ProxyHTMLLinks blockquote cite
ProxyHTMLLinks ins cite
ProxyHTMLLinks del cite
ProxyHTMLLinks form action
ProxyHTMLLinks input src usemap
ProxyHTMLLinks head profile
ProxyHTMLLinks base href
ProxyHTMLLinks script src for
ProxyHTMLLinks
がURL変換を行うHTMLタグの指定を行うディレクティブです。
第一引数には要素名、第二引数以降には要素に対して適用する属性名を定義します。属性名は複数設定可能です。
上記はサンプルとして設定例を載せていますが、実際の環境ではアプリケーションのURLのリンクとして使用しているHTMLタグに漏れがないか確認して、必要があれば追加します。
共通設定
mod_proxy_htmlを使用するにあたっての共通の設定です。
<Location />
RequestHeader unset Accept-Encoding
<IfModule mod_filter.c>
FilterProvider iconv xml2enc "%{CONTENT_TYPE} =~ m|^text/html|"
FilterProvider proxyhtml proxy-html "%{CONTENT_TYPE} =~ m|^text/html|"
FilterProvider SUBSTITUTE SUBSTITUTE "%{CONTENT_TYPE} =~ m|^text/html|"
FilterProvider SUBSTITUTE SUBSTITUTE "%{CONTENT_TYPE} =~ m|^text/css|"
FilterProvider SUBSTITUTE SUBSTITUTE "%{CONTENT_TYPE} =~ m|^text/javascript|"
FilterProvider SUBSTITUTE SUBSTITUTE "%{CONTENT_TYPE} =~ m|^application/javascript|"
FilterChain SUBSTITUTE iconv proxyhtml
</IfModule>
</Location>
<Location />
で囲んだ中に共通設定を行っています。
RequestHeader unset Accept-Encoding
1はアプリケーションの応答コンテンツで「コンテンツ圧縮」が行われないようにするためにリクエストHTTPヘッダーから削除しています。アプリケーションからの応答コンテンツがコンテンツ圧縮されてしまうとバイナリデータであるためにmod_proxy_htmlやmod_substituteによるURLの変換が行えないためです。
FilterProvider
とFilterChain
で、Apacheのinputフィルタに関する設定を行っています。対象のフィルターはmod_proxy_html
mod_substitute
mod_xml2enc
です。
mod_proxy_html
mod_xml2enc
は、HTMLコンテンツのみに対してURLの変換を行うため、Content-Type が text/html のみ動作する設定を行います。
mod_substitute
はmod_proxy_htmlでURLの変換が行えない場合に補完する役割で使用し、JavaScript や CSS 等のコンテンツに対しても URL の変換を行います。そのため、これらのContent-Type を設定しています。環境によっては他にもxmlファイル等必要な Content-Typeを設定する必要があります。
FilterChain
では、前回の記事で触れたように mod_substitute
mod_xml2enc
mod_proxy_html
の順番でフィルタが動作するようにしています。
Proxy先アプリケーション単位の設定
最後にアプリケーションサーバー単位の設定です。
ProxyPass /ap1/ https://ap1.example.co.jp/
<Location /ap1/>
ProxyPassReverse https://ap1.example.co.jp/
ProxyPassReverseCookiePath / /ap1/
ProxyHTMLCharsetOut *
ProxyHTMLURLMap ^/([^/])|^/$ /ap1/$1 R
Substitute 's|//ap1.example.co.jp/|//rp.example.co.jp/ap1/|n'
</Location>
ProxyPass /ap2/ http://ap2.example.co.jp/
<Location /ap2/>
ProxyPassReverse https://ap2.example.co.jp/
ProxyPassReverseCookiePath / /ap2/
ProxyHTMLCharsetOut *
ProxyHTMLURLMap ^/([^/])|^/$ /ap2/$1 R
Substitute 's|//ap2.example.co.jp/|//rp.example.co.jp/ap2/|n'
</Location>
ProxyPass系 の設定はmod_proxy_htmlの設定ではなく、アプリケーションサーバーへproxyするリバースプロキシとしての設定です。下記3つの設定を行っています。
-
ProxyPass
で接続先のサーバーの設定 -
ProxyPassReverse
では、アプリケーションが応答するLocationヘッダーの書き換え設定 -
ProxyPassReverseCookiePath
では、アプリケーションが発行するSet-CookieヘッダーのPath属性の書き換え設定
ProxyHTMLCharsetOut
は、URLの変換後の文字エンコーディングの指定の設定です。*
と設定することで、mod_proxy_htmlで URL の変換を行った後で元のコンテンツと同じ文字エンコーディングに戻ります。この設定がなければユーザーに返るコンテンツの文字エンコーディングはUTF-8となります。
ProxyHTMLURLMap
で、URLの変換ルールを設定をしています。
//【FQDN】/
のようにスキームが省略されたリンクに対してURLの変換が行われないように正規表現の変換ルールを書いています。
/ /ap1/
と書く記載例が見受けられますが、この設定方法だと //【FQDN】/
のリンクに対しても URL 変換されてしまいます。ただし、正規表現の記述は一見するとわかりづらい設定であり、コンテンツ内に//【FQDN】/
と書くリンクがなければ / /ap1/
と設定しても良いと思います。
Substitute
は、mod_proxy_htmlではなくmod_substituteの設定です。mod_proxy_htmlで変換できない箇所のURLの変換を行うために設定します。
以上で設定が完了しました。Apacheを再起動して設定値を反映させます。
動作確認
アプリケーション1に link.html を配置して、https://rp.example.co.jp/ap1/link.html
へアクセスしてリンクが正しく辿れるか確認してみましょう。 link.html の文字エンコーディングは UTF-8 で作成してください。
<html><head>
<title>AP1リンク</title>
</head><body>
<a href="/top.html">トップへ(/から始まる絶対パス)</a><br>
<a href="./top.html">トップへ(相対パス)</a><br>
<a href="//ap1.example.co.jp/top.html">トップへ(//から始まる絶対パス)</a><br>
<a href="/">/だけのリンク</a><br>
<a href="https://ap1.example.co.jp/top.html">httpから始まる絶対パスのリンク</a>
</body></html>
表示されたlink.htmlのリンクをクリックするとhttps://rp.example.co.jp/ap1/〜
となればmod_proxy_htmlの設定がうまく出来ています。
文字化け?
https://rp.example.co.jp/ap1/link.html
へのアクセスで文字化けした方はいらっしゃいませんか?
もしアプリケーション1のWebサーバー等で Content-Type に 文字エンコーディングがセットされていなければ2文字化けが発生します。
これはmod_xml2encの処理でコンテンツの文字エンコーディングが何か判別できなかったため、デフォルトのISO-8859-1
で文字エンコーディング変換が行われたためです。
if (!HAVE_ENCODING(ctx->xml2enc)) {
cfg = ap_get_module_config(r->per_dir_config, &xml2enc_module);
if (!ctx->encoding) {
ctx->encoding = cfg->default_charset?cfg->default_charset:"ISO-8859-1";
}
文字エンコーディングが何か判別できなった場合のデフォルト値はディレクティブが用意されているため、設定により ISO-8859-1
から変更することが可能です。
文字化けが発生した環境でhttpd.confに以下の設定を追加すると文字化けしなくなります。
xml2EncDefault UTF-8
一般的なWebアプリケーションであれば「文字エンコーディングの指定が無い」なんて事はないと思いますが、このように設定で対処することができます。
もちろん設定を行わずとも、WebサーバーでレスポンスHTTPヘッダーに文字エンコーディングをセットする3、HTMLのMETAタグで文字エンコーディングをセットする4でも文字化けを回避することができます。
ProxyHTMLEnable は使わない
本記事の設定では mod_proxy_htmlを有効にするためのProxyHTMLEnable on
の設定を行っていません。mod_filterによってmod_proxy_htmlを動作させています。これは意図したもので理由は2つあります。
- inputフィルターで動作するフィルタの順番をコントロールしたい
- 不要な Content-Type で mod_xml2enc が動作するのを防ぎたい
「1」についてはすでに説明済みですので「2」の理由を説明します。
ProxyHTMLEnable on
とすると自動的に mod_xml2enc も動作するよう Apache の inputフィルタに登録されます。そしてmod_xml2encのソースコードを見ると、mod_xml2encは Content-Type が text/ で始まるか、xmlという文字列が含まれると動作します。
/* only act if starts-with "text/" or contains "xml" */
if (strncmp(ctype, "text/", 5) && !strstr(ctype, "xml")) {
ap_remove_output_filter(f);
return ap_pass_brigade(f->next, bb) ;
}
URLの変換はHTMLのコンテンツに対してのみ行うため、mod_xml2encが動作するのはtext/htmlだけで問題ありません。しかし、ProxyHTMLEnable on
とすると本来必要の無いコンテンツに対しても文字エンコーディングの変換処理が実行されてしまうためこれを防ぐためにProxyHTMLEnable on
の設定を行わないようにしています。
終わりに
リバースプロキシの環境でmod_proxy_htmlを使用する設定例を説明しました。
もし実際の環境でmod_proxy_htmlを使う場合は、必要なHTMLタグの設定
、mod_substituteの動作対象Content-Type
や置換文字列の設定
など調整が必要です。リバースプロキシとアプリケーションを構築したあとで接続試験を行って URL の変換に漏れがないかの確認を行ってください。構築後に調整が必要となるのでテストの期間を十分に確保するようスケジュールを立てることが望ましいです。
最後にmod_proxy_htmlはどうしても使わなければならない場合のみ使いましょう。この記事を読んでいただければわかりますが、mod_proxy_htmlを使いこなすのは大変です。
もしこれからシステムを設計する状態であるのならば、mod_proxy_htmlを使わない選択肢を取れないか考慮することをオススメします。