taketiyo.log

Web Engineering 🛠 & Body Building 💪

【Apache】プログラマブルにRewrite Rulesを記述する【.htaccess】

Programming

  / /

ウェブサイトに対するクローラーからのアクセスとユーザーからのアクセスを、.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等で指定します。

 

参考

http://httpd.apache.org/docs/current/mod/mod_rewrite.html