WordPress メディアのURLを mod_ext_filter で一括変換

クラウド
クラウド
スポンサーリンク

WEBサイトへCDNを導入する時に一番大変なのは、画像やCSS、JavaScriptなどの、URLの書き換え作業ではないでしょうか? 特にWordPressで構築したWEBサイトでは、投稿記事以外のURLを書き換えるには、PHPをいじる必要もあるのでなかなか大変です。そこで今回は、Apache HTTPサーバ の mod_ext_filter を使って、画像やCSSなどのURLを一括で書き換える方法と注意点をまとめてみました。

mod_ext_filter を使ったURLなどコンテンツ内容の書き換えには、色々と注意することがあります。本番サーバに設定する前に、一度テストしておくことをオススメします。

mod_ext_filter で URL を書き換える

mod_ext_filter は、レスポンス(HTMLや画像ファイルなどのコンテンツ)をクライアントに送る前に、外部プログラムで処理するための Apacheモジュールです。仕組みはとてもシンプルで、クライアントへのレスポンスを、外部プログラムに標準入力で渡して、外部プログラムの標準出力をクライアントへのレスポンスとして返します。

設定の前に、mod_ext_filte が有効になっているかを確認しましょう。Apache httpd をパッケージからインストールしていれば有効になっていると思います。

$ sudo httpd -M | grep ext_filter_module
 
ext_filter_module (shared) ←この表示があればOK

外部フィルタの定義

処理するためのプログラムを ExtFilterDefineディレクティブ で外部フィルタとして定義します。このディレクティブは httpd.conf などのサーバ設定ファイルにのみ書くことができます。.htaccess ファイルには書くことができません。

$ sudo vi /etc/httpd/conf/httpd.conf

ExtFilterDefine fixtext mode=output intype=text/html cmd="/usr/local/bin/fixtext.sh"

 
fixtex
 定義するフィルタの名前です。この後 SetOutputFilterディレクティブ でこのフィルタ名を指定します。フィルタの名前は任意でつけることができます。

mode=output
 レスポンスを外部フィルタで処理します。Apache 2.1 以降であれば mode=input とすればリクエストを外部フィルタで処理することもできます。

intype=text/html
 外部フィルタで処理をする対象のMIMEタイプを指定します。今回は、画像やCSSなどの「URL」を書き換えるので、text/html のみ処理の対象にします。

cmd="/usr/local/bin/fixtext.sh"
 処理するためのプログラムを指定します。今回はシェルスクリプトを指定していますが、「cmd="/bin/sed -e s/AAA/BBB/g"」のように直接コマンドを書くこともできます。
 

URL書き換えスクリプトの作成

ExtFilterDefineディレクティブで指定した、処理するためのプログラム「cmd="/usr/local/bin/fixtext.sh"」を作成します。今回はWordPressのメディアURLを、CDNのURLに書き換えてみたいと思います。

$ sudo vi /usr/local/bin/fixtext.sh

#!/bin/sh
PATH="/sbin:/bin:/usr/sbin:/usr/bin"

URL="https://blog.apar.jp"
CDN="//cdn.apar.jp"

sed -e "s|${URL}/wp-content/|${CDN}/wp-content/|g" \
    -e "s|${URL}/wp-includes/|${CDN}/wp-includes/|g"

exit 0

スクリプトのオーナーをWEBサーバの実行ユーザ apache に変更し、スクリプトに実行権限をつけます。

$ sudo chown apache /usr/local/bin/fixtext.sh
$ sudo chmod 700 /usr/local/bin/fixtext.sh

外部フィルタの実行設定

最後に SetOutputFilter ディレクティブ で定義したフィルタ「fixtex」を指定します。今回は Location の中に書いていますが、Directory の中に書いてもOKです。

$ sudo vi /etc/httpd/conf/httpd.conf

<Location />
    SetOutputFilter fixtext
</Location>

後は Apache の設定を読み込めば、スクリプトの処理に従ってURLが書き換わります。

$ sudo systemctl reload httpd

注意1:データ圧縮(DEFLATE)を使ってる場合

他の設定箇所で SetOutputFilter に DEFLATE を指定している場合は、書き換えが行われなかったり、DEFLATEのデータ圧縮がされないことがあります。

その場合は、他の設定箇所の SetOutputFilter を削除し、以下のように指定することで、書き換え処理の後にDEFLATEでデータ圧縮がされるようになります。

<Location />
    SetOutputFilter fixtext;DEFLATE
    SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
</Location>

注意2:静的HTMLファイルのキャッシュ対応

WordPressを使っている場合は、基本的にはHTMLの内容はクライアントのブラウザキャッシュを使わないようになっているので問題はないのですが、静的HTMLファイルなど、ブラウザキャッシュが使われる場合は、書き換えたレスポンスをクライアントが受け取ってくれません。

その場合、HTMLの内容はブラウザキャッシュを使わないように設定する必要があります。下は設定例です。FilesMatch の条件は環境に合わせて指定してください。

<FilesMatch "\.(html|htm)$|^$">
    FileEtag None
    RequestHeader unset If-Modified-Since
</FilesMatch>

ラウザキャッシュの動作について「HTTPヘッダチューニング Etag・Last-Modified | キャッシュ屋 blog」の記事を参考にさせていただきました。とても分かりやすい記事です。

注意3:管理画面で URLを書き換えしてはいけない

WordPress など CMS を使っている場合、記事を編集する時にオリジナルのURLまで書き換えてしまいますので、管理画面ではURLを書き換えしないようにしておきましょう。

<Directory "/var/sites/blog/public/wp-admin">
    SetOutputFilter None
</Directory>

おわりに

色々注意点はありますが、WEBサーバ側でコンテンツの内容を書き換えられるのはとても便利ですね。場合によっては、WEBアプリケーションを変更するときの工数を大幅に減らせそうです。

コメント

タイトルとURLをコピーしました