ウェブサイトに対するクローラーからのアクセスとユーザーからのアクセスを、.htaccess を用いて振り分ける対応をしたので、その際のメモを残しておきます。
厳密には.htaccess ファイル内にてRewrite Rules を記述して実現します。
Apache のmod_rewrite プラグインはチューリング完全なため、かなりプログラマブルに文字列の操作を行うことが可能です。
目次
やりたいこと
- SPA(Single Page Application)で作成したウェブアプリの特定ディレクトリにクローラーがアクセスしてきた際は、予めレンダリングしておいた静的HTLMを返却する。
- ユーザーがアクセスしてきた際は、どのディレクトリであれ通常通りindex.html を返却する。
.htaccess の作成
<IfModule mod_rewrite.c>
RewriteEngine On
# 振り分け用の変数を初期化
RewriteRule .* - [E=X_IS_RENDERED_CONTENT:0]
RewriteRule .* - [E=X_IS_CRAWLER_ACCESS:0]
# /detail/以下へのアクセスの場合、X_IS_RENDERED_CONTENTに1をセット、X_RENDERED_FILE_NAMEに(.*)でキャプチャしたURIを保存
RewriteCond %{REQUEST_URI} ^/detail/(.*)$
RewriteRule .* - [E=X_IS_RENDERED_CONTENT:1,E=X_RENDERED_FILE_NAME:%1]
# 主要クローラーからのアクセスの場合、X_IS_CRAWLER_ACCESSに1をセット
RewriteCond %{HTTP_USER_AGENT} (Googlebot|Mediapartners-Google|Twitterbot|facebookexternalhit|bingbot|Baiduspider)
RewriteRule .* - [E=X_IS_CRAWLER_ACCESS:1]
# X_IS_RENDERED_CONTENT、X_IS_CRAWLER_ACCESSの値が共に1の場合リバースプロキシとして動作、静的HTMLを返却
RewriteCond %{ENV:X_IS_RENDERED_CONTENT} ^1$
RewriteCond %{ENV:X_IS_CRAWLER_ACCESS} ^1$
RewriteRule .* https://static.example.com/rendered/%{ENV:X_RENDERED_FILE_NAME}.html [P,L]
# 上記ルールに該当せず、ファイル、ディレクトリが存在しなければ通常通りindex.html を返却する
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ dist/index.html [L]
</IfModule>
ポイント
[E=VAR_NAME:VALUE]
の記法を用いることで、環境変数をセット出来ます。- RewriteRule の
.*
は全てにマッチするので、すなわち必ず実行される事になります。 -
は文字列の置換を行わないという意味で、フラグの操作だけを実行したい場合に使います。- RewriteCond にてキャプチャした文字列はRewriteRule 内のフラグ操作時に
%1
で参照出来ます。 - セットした環境変数は後のRewriteCond、RewriteRule で
%{ENV:VAR_NAME}
で参照出来ます。 [P]
フラグはプロキシで、別オリジンからデータを取得して返却するリバースプロキシとして動作させることが出来ます。[P]
フラグでリクエスト先にhttps
を指定する場合、SSLProxyEngine On
を指定する必要がありますが、この設定は.htaccess
では設定できないためhttpd.conf
等で指定します。