[an error occurred while processing this directive] このサイトは Apache URL Rewriting Guide サイトの日本語訳です。
A Users Guide to
URL Rewriting with the
Apache Webserver



Ralf S. Engelschall <rse@apache.org>

T his document は http://www.apache.org/docs/mod/mod_rewrite.html にある Apache Group によるオリジナルの mod_rewrite マニュアルを補足するものです。ウェブマスターが普段、実際に直面している典型的な URL-based の問題を、mod_rewrite でどのように解決するかを記述しています。URL の rewriting ruleset を設定することによってそれぞれの問題を解決する方法を詳述してあります。
Table Of Contents

はじめに
解決策
    URL レイアウト
        Canonical URLs
        Canonical Hostnames
        DocumentRoot の移動
        ディレクトリのスラッシュの解決
        均一な URL 配置をした ウェブ・クラスタ
        異なるウェブサーバへのホーム・ディレクトリの移動
        ホーム・ディレクトリの構築
        ファイルシステムの再構築
        NCSA imagemap を Apache mod_imap で
        複数のディレクトリでファイル検索
        URL 部に基づく環境変数の設定
        Virtual User Host
        他サーバへホーム・ディレクトリをリダイレクト
        他のウェブサーバへ失敗した URL をリダイレクト
        リダイレクト拡張
        アーカイブ・アクセスの多重化
        時間に依存する rewrite
        YYYY から XXXX への移動と、以前との互換性
	コンテンツのハンドリング
        From Old to New (内部的)
        From Old to New (外部的)
        コンテンツに依存するブラウザ
        動的 Mirror
        逆動的 Mirror
        イントラネットから不足データの読み出し
        ロードバランス
        逆プロキシー
        新しい MIME-type、新しいサービス
        静的から動的に
        On-the-fly でコンテンツ再生
        自動更新するドキュメント
        大量の Virtual Host
    アクセス制限
        ロボットを制限
        インライン画像を制限
        Host 拒否
        Proxy 拒否
        特殊な環境変数
        Referer ヘッダを基にした Deflector
    その他
        外部 rewrite エンジン

Introduction to mod_rewrite

Apache の mod_rewrite モジュールは必殺仕事人です。つまり、URL 操作を確実に行う最も粋なモジュールだということです。 あなたが夢にまで見た、URL のあらゆる操作を殆ど全て実行することができます。その代償としてあなたは、その複雑さを許容しなければなりません。 なぜなら mod_rewrite の最大の欠点は、初心者の理解と利用が困難な点にあるからです。 そしてまた Apache に熟練した者でさえ、mod_rewrite の新しい側面に出くわすのです。

すなわち: 初めて mod_rewrite を使ったことにより、あなたは自ら災いを招き、あなたの余生でそれを二度と使わないか、あるいはそれを愛するようになるかは、 そういう訳です。このドキュメントは既に成功した解決例を提示することによって、最初の躓きを避けるために2、3の事象を成功させようとするものです。

Practical Solutions

ここには過去に私自身が考え出した解決策と、他の人々から集めてきた解決策があります。これらの例で、遠慮なく URL rewrite の黒魔術を習得してください。

ATTENTION: あなたのサーバ設定によって、例を多少変更する必要があるかもしれません。例えば、mod_alias と mod_userdir 等を使っているなら [PT] フラッグを追加することです。あるいはサーバ毎のコンテクストの代わりに.htaccessコンテクストに合うようにルールセットを書き換えることです。 使う前にはそれぞれのルールセットが何をするのかを理解するようにしてください。そうすれば問題ありません。



URL Layout



Canonical URLs

Problem Description:

いくつかのウェブサーバにはリソースに対して一つ以上の URL があります。普通、正統な URL(実際に使われて配送されているもの) とショートカット、内部的なもの等です。ユーザが要求した、独立したどの URL でも、canonical な URL だけを最終的に見るようにするべきです。

Problem Solution:

ブラウザの閲覧とそれに続く全てのリクエストのために、訂正する non-canonical の URL に対して外部 HTTP リダイレクトをします。以下にあるルールセットの例では、/~user を canonical な /u/user に置き換えて、/u/user に欠けているスラッシュを修正します。

RewriteRule   ^/~([^/]+)/?(.*)    /u/$1/$2  [R]
RewriteRule   ^/([uge])/([^/]+)$  /$1/$2/   [R]


Canonical Hostnames

Problem Description:

...

Problem Solution:



RewriteCond %{HTTP_HOST}   !^fully.qualified.domain.name
RewriteCond %{HTTP_HOST}   !^$
RewriteCond %{SERVER_PORT} !^80$
RewriteRule ^/(.*)         http://fully.qualified.domain.name:%{SERVER_PORT}/$1 [L,R]
RewriteCond %{HTTP_HOST}   !^fully.qualified.domain.name
RewriteCond %{HTTP_HOST}   !^$
RewriteRule ^/(.*)         http://fully.qualified.domain.name/$1 [L,R]


Moved DocumentRoot

Problem Description:

普通、ウェブサーバの DocumentRoot は、URL の``/''と直接結びついています。しかし、しばしばこのデータは本当は最優先ではなくて、 ことによるとたくさんのデータプールの一つの要素に過ぎません。例えば私達のイントラネット・サイトでは /e/www/ (WWW のためのホームページ), /e/sww/ (イントラネットのためのホームページ) 等です。今、DocumentRoot のデータが /e/www/ にあるので、後に続くリクエストのためにこのデータプールにある全てのインライン・画像とその他のコンテンツを確実にしなければなりません。

Problem Solution:

URL の //e/www/ にリダイレクトするだけです。取るに足らないことのように見えますが、実際 mod_rewrite なら取るに足らないことです。 代表的な古い URL Aliases のメカニズム(mod_alias とその仲間)では prefix の一致が使われます。これだと DocumentRoot が全ての URL にプレフィックスを付けるので、そのようなリダイレクトができません。mod_rewrite にとっては本当に取るに足らないことです:

RewriteEngine on
RewriteRule   ^/$  /e/www/  [R]


Trailing Slash Problem

Problem Description:

ウェブマスターは皆、URL の参照するディレクトリにスラッシュを付けることに関しては詩人です。 もしそれが失われると、サーバはエラーを起こします。/~quux/foo/ ではなく /~quux/foo だと、サーバは foo という名前のファイルを探すからです。そしてこのファイルがファイルではなく、ディレクトリだから文句を言うのです。実際にはほとんどの場合、自力で解決しようとしますが、時々このメカニズムをあなたがエミュレートしてやる必要があります。例えば、CGI スクリプト等に対してたくさんの複雑な URL を rewrite します。

Problem Solution:

このデリケートな問題を解決するには、サーバに自動的にスラッシュを付けてやることです。正確にこれを実行するには、外部リダイレクトを使うと、ブラウザが正しく画像等をリクエストします。内部的な書き換えを行うだけなら、ディレクトリページに対してだけ働くようにします。しかし、画像が相対 URL でこのページに含まれると、うまくいきません。なぜならブラウザはインライン・オブジェクトを要求するからです。例えば、/~quux/foo/index.htmlimage.gif に対するリクエストは、外部リダイレクトがないと /~quux/image.gif になってしまいます!

これを実現するには、こんなトリックを使います:

RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^foo$  foo/  [R]


イカれた甲斐性無しは、ディレクトリの最上層にある .htaccess ファイルで以下のようにします。 しかしこれはいくらかのオーバーヘッドを作ることに気を付けてください。

RewriteEngine  on
RewriteBase    /~quux/
RewriteCond    %{REQUEST_FILENAME}  -d
RewriteRule    ^(.+[^/])$           $1/  [R]


Webcluster through Homogeneous URL Layout

Problem Description:

イントラネット上のウェブ・クラスタで WWW サーバを端から端まで同じ構造でつじつまが合う URL のレイアウトにしたいとします。すなわち、全ての URL(per definition server local and thus server dependent!) が実際に独立したサーバになるということです。私たちがしたいのは、サーバが独立した矛盾しないレイアウトでWWW の名前を設定することです: URL が物理的に正しいターゲットのサーバを含むことはありません。クラスタ自身は物理的なターゲットのホストに自動的に向かいます。

Problem Solution:

まず、ターゲットのサーバの情報は、ユーザ、グループ、実体がどこにあるのかという情報を持っている(配布されている)外部マップからもたらされます。 そのフォームは

user1  server_of_user1
user2  server_of_user2
:      :
それらを map.xxx-to-host というファイルに記述します。二番目に、URL がサーバに対してローカルで正統でないときに、

/u/user/anypath
/g/group/anypath
/e/entity/anypath
から

http://physical-host/u/user/anypath
http://physical-host/g/group/anypath
http://physical-host/e/entity/anypath
へ、全てのサーバがリダイレクトするフォームの URL を教えてやる必要があります。以下のルールセットはマップファイルの助けにより、これを行うことができます(もしユーザがマップにエントリを持っていなければ、使われるデフォルト・サーバは server0 であると仮定します):

RewriteEngine on

RewriteMap      user-to-host   txt:/path/to/map.user-to-host
RewriteMap     group-to-host   txt:/path/to/map.group-to-host
RewriteMap    entity-to-host   txt:/path/to/map.entity-to-host

RewriteRule   ^/u/([^/]+)/?(.*)   http://${user-to-host:$1|server0}/u/$1/$2
RewriteRule   ^/g/([^/]+)/?(.*)  http://${group-to-host:$1|server0}/g/$1/$2
RewriteRule   ^/e/([^/]+)/?(.*) http://${entity-to-host:$1|server0}/e/$1/$2

RewriteRule   ^/([uge])/([^/]+)/?$          /$1/$2/.www/
RewriteRule   ^/([uge])/([^/]+)/([^.]+.+)   /$1/$2/.www/$3


Move Homedirs to Different Webserver

Problem Description:

多くのウェブマスターが以下の状況に対する解決策を求めています: ウェブサーバにある全てのホーム・ディレクトリを他のウェブサーバにリダイレクトしたい場合です。普通、長い間使い古されたものを置き換える新しいウェブサーバを立ち上げるときに、これが必要になります。

Problem Solution:

この解決は mod_rewrite なら些細なことです。古いウェブサーバで、全ての /~user/anypath URL を http://newserver/~user/anypath にリダイレクトするだけです。

RewriteEngine on
RewriteRule   ^/~(.+)  http://newserver/~$1  [R,L]


Structured Homedirs

Problem Description:

数千のユーザがいるいくつかのサイトでは普通、ホームディレクトリ構造のレイアウトを使っています。すなわち、それぞれのホーム・ディレクトリは、例を挙げればユーザ名の最初の文字で始まるサブ・ディレクトリです。/~foo/anypath/home/f/foo/.www/anypath で、/~bar/anypath/home/b/bar/.www/anypath です。

Problem Solution:

私たちは、ニョロ(~)の URL を正確な、上の示したレイアウトのように展開するルールセットを使っています。

RewriteEngine on
RewriteRule   ^/~(([a-z])[a-z0-9]+)(.*)  /home/$2/$1/.www$3


Filesystem Reorganisation

Problem Description:

これは、本当にカタイ例です: ウェブをスムーズに見るために、ディレクトリ毎に RewriteRules を使い、そのデータ構造は決してイジられたりしません。
Background: net.sw は私が 1992 年に集め始めた、フリーの Unix ソフトウェア・パッケージです。 これは趣味でもあり、仕事でもあります。というのは、私は情報科学を勉強する一方、システムとネットワークの管理者としても長年働いてきたからです。 毎週私はある種のソフトウェアを必要としていて、パッケージを貯蔵するディレクトリの階層は深くなっていきました:

drwxrwxr-x   2 netsw  users    512 Aug  3 18:39 Audio/
drwxrwxr-x   2 netsw  users    512 Jul  9 14:37 Benchmark/
drwxrwxr-x  12 netsw  users    512 Jul  9 00:34 Crypto/
drwxrwxr-x   5 netsw  users    512 Jul  9 00:41 Database/
drwxrwxr-x   4 netsw  users    512 Jul 30 19:25 Dicts/
drwxrwxr-x  10 netsw  users    512 Jul  9 01:54 Graphic/
drwxrwxr-x   5 netsw  users    512 Jul  9 01:58 Hackers/
drwxrwxr-x   8 netsw  users    512 Jul  9 03:19 InfoSys/
drwxrwxr-x   3 netsw  users    512 Jul  9 03:21 Math/
drwxrwxr-x   3 netsw  users    512 Jul  9 03:24 Misc/
drwxrwxr-x   9 netsw  users    512 Aug  1 16:33 Network/
drwxrwxr-x   2 netsw  users    512 Jul  9 05:53 Office/
drwxrwxr-x   7 netsw  users    512 Jul  9 09:24 SoftEng/
drwxrwxr-x   7 netsw  users    512 Jul  9 12:17 System/
drwxrwxr-x  12 netsw  users    512 Aug  3 20:15 Typesetting/
drwxrwxr-x  10 netsw  users    512 Jul  9 14:08 X11/
1996 年 7 の月、nice Web interfaceウェブのインターフェース経由でこの 350 MB のアーカイブを公開することにしました(http://net.sw.engelschall.com/net.sw/)。 "Nice"というのは、アーカイブの階層を通じて直接目を通すことができるインターフェースを提供したかったからです。 そして、"nice"というのはこの階層に変更を加えたくないということです - CGI スクリプトを置いたりしないで。 何故かって?それは上の構成は FTP でアクセスできるようにするべきで、そこにウェブや CGI のツールは欲しくないからです。

Problem Solution:

解決方法は二段階です: まず、on-the-fly で全てのディレクトリで全てのページを作る CGI スクリプトのセットです。 以下のように /e/netsw/.www/ にそれを置きます:

-rw-r--r--   1 netsw  users    1318 Aug  1 18:10 .wwwacl
drwxr-xr-x  18 netsw  users     512 Aug  5 15:51 DATA/
-rw-rw-rw-   1 netsw  users  372982 Aug  5 16:35 LOGFILE
-rw-r--r--   1 netsw  users     659 Aug  4 09:27 TODO
-rw-r--r--   1 netsw  users    5697 Aug  1 18:01 netsw-about.html
-rwxr-xr-x   1 netsw  users     579 Aug  2 10:33 netsw-access.pl
-rwxr-xr-x   1 netsw  users    1532 Aug  1 17:35 netsw-changes.cgi
-rwxr-xr-x   1 netsw  users    2866 Aug  5 14:49 netsw-home.cgi
drwxr-xr-x   2 netsw  users     512 Jul  8 23:47 netsw-img/
-rwxr-xr-x   1 netsw  users   24050 Aug  5 15:49 netsw-lsdir.cgi
-rwxr-xr-x   1 netsw  users    1589 Aug  3 18:43 netsw-search.cgi
-rwxr-xr-x   1 netsw  users    1885 Aug  1 17:41 netsw-tree.cgi
-rw-r--r--   1 netsw  users     234 Jul 30 16:35 netsw-unlimit.lst
DATA/ サブディレクトリは上のようなディレクトリ構造を持っています。すなわち、本当の net.sw で、時々 rdist によって自動的にアップデートされます。
二つ目の段階として: これら二つの構造を一つにしてスムーズに URL ツリーを見るには、どのようにリンクをすれば良いのでしょうか? URL に対して 適切な CGI スクリプトが走っている間、ユーザからは DATA/ ディレクトリを隠したいのです。
解決法は: まず、内部パス /e/netsw に対してアナウンスされた URL /net.sw/ を書き換えるために、サーバの Document Root にディレクトリ毎の設定ファイルに以下を記述します:

RewriteRule  ^net.sw$       net.sw/        [R]
RewriteRule  ^net.sw/(.*)$  e/netsw/$1


最初のルールセットは、スラッシュがない時のリクエストのためのものです。二番目のルールセットがブツです。 そして、ディレクトリ毎の設定ファイル /e/netsw/.www/.wwwacl でブチかます設定になっています:

Options       ExecCGI FollowSymLinks Includes MultiViews

RewriteEngine on

RewriteBase   /net.sw/

RewriteRule   ^$                       netsw-home.cgi     [L]
RewriteRule   ^index\.html$            netsw-home.cgi     [L]

RewriteRule   ^.+/(netsw-[^/]+/.+)$    $1                 [L]

RewriteRule   ^netsw-home\.cgi.*       -                  [L]
RewriteRule   ^netsw-changes\.cgi.*    -                  [L]
RewriteRule   ^netsw-search\.cgi.*     -                  [L]
RewriteRule   ^netsw-tree\.cgi$        -                  [L]
RewriteRule   ^netsw-about\.html$      -                  [L]
RewriteRule   ^netsw-img/.*$           -                  [L]

RewriteRule   !^netsw-lsdir\.cgi.*     -                  [C]
RewriteRule   (.*)                     netsw-lsdir.cgi/$1


解釈するためのヒントです:

  1. 四つ目の所で L (last) フラッグと、置き換え領域がない('-')ことに気を付けてください
  2. 最後の部分の最初のルールで ! (not) 記号と、C (chain) フラッグに気を付けてください
  3. 最後のルールで catch-all パターンに気を付けてください


NCSA imagemap to Apache mod_imap

Problem Description:

NCSA ウェブサーバから Apache に乗り換えるときには、スムーズな移行が望まれます。 それで、古い NCSA imagemap プログラムをわざわざ Apache で動かすための情報が必要になります。 問題は /cgi-bin/imagemap/path/to/page.map によって imagemap プログラムを参照するハイパー・リンクがたくさんあることです。 Apache では /path/to/page.map を読むだけです。

Problem Solution:

全てのリクエストに対して on-the-fly でプレフィックスを外すグローバルなルールを使います:

RewriteEngine  on
RewriteRule    ^/cgi-bin/imagemap(.*)  $1  [PT]


Search pages in more than one directory

Problem Description:

時々一つ以上のディレクトリでウェブサーバにページを検索させる必要が生じたとします。そこでは MultiViews やその他の技術では役に立ちません。

Problem Solution:

ディレクトリにあるファイルを検索するルールセットです。

RewriteEngine on

RewriteCond         /your/docroot/dir1/%{REQUEST_FILENAME}  -f
RewriteRule  ^(.+)  /your/docroot/dir1/$1  [L]

RewriteCond         /your/docroot/dir2/%{REQUEST_FILENAME}  -f
RewriteRule  ^(.+)  /your/docroot/dir2/$1  [L]

RewriteRule   ^(.+)  -  [PT]


Set Environment Variables According To URL Parts

Problem Description:

もしかすると、リクエストとそれを encode する URL との間のステータス情報を維持したいことがあるかもしれません。 しかし、この情報をストリッピングするために、全てのページに CGI wrapper を使いたくないとします。

Problem Solution:

ステータス情報をストリッピングして、XSSI か CGI 内部からは後で参照されない環境変数によて、その情報を記憶しておくための rewrite ルールを使います。 この方法で URL /foo/S=java/bar//foo/bar/ に変換されます。そして、STATUS と名付けられた環境変数は値を "java" に設定します。

RewriteEngine on
RewriteRule   ^(.*)/S=([^/]+)/(.*)    $1/$3 [E=STATUS:$2]


Virtual User Hosts

Problem Description:

同じマシンに対する DNS A レコード を使って、このマシンに virtualhosts なしでユーザ名のホームページに対して www.username.host.domain.com を提供したいとします。

Problem Solution:

HTTP/1.0 リクエストに対しては解決法がありませんが、HTTP/1.1 に対するリクエストは Host を含んでいます: HTTP ヘッダは http://www.username.host.com/anypath を内部的に /home/username/anypath に rewrite するルールセットを使います:

RewriteEngine on
RewriteCond   %{HTTP_HOST}                 ^www\.[^.]+\.host\.com$
RewriteRule   ^(.+)                        %{HTTP_HOST}$1          [C]
RewriteRule   ^www\.([^.]+)\.host\.com(.*) /home/$1$2


Redirect Homedirs For Foreigners

Problem Description:

ユーザへのリクエストがローカルドメイン ourdomain.com には留まらない時、ホームディレクトリの URL が他のウェブサーバ www.somewhere.com へリダイレクトするようにします。これは virtual host のコンテンツでしばしば使われます。

Problem Solution:

ただの rewrite 設定です:

RewriteEngine on
RewriteCond   %{REMOTE_HOST}  !^.+\.ourdomain\.com$
RewriteRule   ^(/~.+)         http://www.somewhere.com/$1 [R,L]


Redirect Failing URLs To Other Webserver

Problem Description:

URL の rewrite に関する一般的な FAQ は、ウェブサーバ A でリクエストが失敗した時にウェブサーバ B へどうやったらリダイレクトするのか、というものです。 普通、これは Perl の ErrorDocument CGI-scripts 経由で行われますが、mod_rewrite による解決もできます。 しかし、これは ErrorDocument CGI-script を使うよりもパフォーマンスが低いことに気を付けてください!

Problem Solution:

最初に紹介する解決法はパフォーマンスは良いのですが、柔軟性に欠け、error safe が少ないです:

RewriteEngine on
RewriteCond   /your/docroot/%{REQUEST_FILENAME} !-f
RewriteRule   ^(.+)                             http://webserverB.dom/$1


ここで問題なのは、DocumentRoot 内部にあるページにだけ働きかけることです。 更に条件を追加してやると(例えばホームディレクトリをハンドルするようにする)、より良くなります:

RewriteEngine on
RewriteCond   %{REQUEST_URI} !-U
RewriteRule   ^(.+)          http://webserverB.dom/$1


これは URL のルックアヘッド機能を使っています。これによりあらゆるタイプの URL に働き、確実な方法です。 しかし、ウェブサーバに対するパフォーマンスに影響は大きく、あらゆるリクエストに対して一つ以上の内部リクエストがあります。 ですので、ウェブサーバが強力な CPU で走っているのなら、これを使ってください。 もし遅いマシンなら、最初に記述した方法か ErrorDocument CGI-script が良いでしょう。

Extended Redirection

Problem Description:

私達は、時々リダイレクト URL の制御をする必要があります(キャラクタ・エスケープのしくみに関して)。普通、Apache カーネルの URL エスケープ機能もまた、アンカーをエスケープします。すなわち、URL は "url#anchor" が好ましいのです。mod_rewrite でリダイレクトしているこのディレクトリを使うことはできません。なぜなら Apache の uri_escape() 機能は hash キャラクタをエスケープするからです。そんな URL にどうやってリダイレクトするのでしょう?

Problem Solution:

それ自身がリダイレクトする NPH-CGI スクリプトを使って、修復をしなければなりません。 ここではエスケープが行われないからです(NPH=non-parseable headers)。 まず、以下のようなサーバ毎の設定行による(最後の rewrite ルールの一つでなければなりません)、新しい URL のスキームである xredirect: を紹介します:

RewriteRule ^xredirect:(.+) /path/to/nph-xredirect.cgi/$1 [T=application/x-httpd-cgi,L]


これは、nph-xredirect.cgi プログラムを通じてパイプされた xredirect: で全ての URL にプレフィックスを付けます。 このプログラムはこんな感じです:



$| = 1;
$url = $ENV{'PATH_INFO'};

print "HTTP/1.0 302 Moved Temporarily\n";
print "Server: $ENV{'SERVER_SOFTWARE'}\n";
print "Location: $url\n";
print "Content-type: text/html\n";
print "\n";
print "<html>\n";
print "<head>\n";
print "<title>302 Moved Temporarily (EXTENDED)</title>\n";
print "</head>\n";
print "<body>\n";
print "<h1>Moved Temporarily (EXTENDED)</h1>\n";
print "The document has moved <a href=\"$url\">here</a>.<p>\n";
print "</body>\n";
print "</html>\n";



これは全ての URL スキームにリダイレクトするようにします。すなわち、mod_rewrite で直接受け入れられないものを含みます。 例を挙げれば、news:newsgroup 経由でもリダイレクトするには

RewriteRule ^anyurl  xredirect:news:newsgroup


注: ルールに [R] や [R,L] を置いていないのは、後で xredirect: が上の"pipe through"ルールによって拡張される必要があるからです

Archive Access Multiplexer

Problem Description:

http://www.perl.com/CPAN にある CPAN (Comprehensive Perl Archive Network) を知っていますか? これはCPAN ミラーを運び、リクエストをしているクライアントの場所から近い、世界中にあるいくつかの FTP サーバのうちの一つにリダイレクトします。 実はこれは、FTP アクセスの多重送信サービスと呼ばれています。CGI スクリプトによって CPAN を走らせるように、mod_rewrite ではどんな実装が可能でしょうか?

Problem Solution:

まず、version 3.0.0 からの mod_rewrite は、リダイレクトの "ftp:"スキームを使うことに気を付けます。 次に、ロケーションの近似はクライアントの top-level ドメインを超えた rewritemap によって行われます。 ルールセットのトリッキーな連鎖で、多重化マップの鍵として、この top-level ドメインを使うことができます。

RewriteEngine on
RewriteMap    multiplex                txt:/path/to/map.cxan
RewriteRule   ^/CxAN/(.*)              %{REMOTE_HOST}::$1                 [C]
RewriteRule   ^.+\.([a-zA-Z]+)::(.*)$  %{multiplex:$1|ftp.default.dom}$2  [R,L]


de        ftp://ftp.cxan.de/CxAN/
uk        ftp://ftp.cxan.uk/CxAN/
com       ftp://ftp.cxan.com/CxAN/
 :


Time-Dependend Rewriting

Problem Description:

時間に依存するようなコンテンツのトリックが必要な時に、多くのウェブマスターは CGI スクリプト、例えば、特化したページにリダイレクトするようなものを使っています。mod_rewrite で行うにはどうすれば良いでしょう?

Problem Solution:

rewrite の条件には TIME_xxx と名付けられたたくさんの変数があります。 特別な辞書編集比較パターン <STRING、>STRING、=STRING に関連して、時間依存のリダイレクトをすることができます:

RewriteEngine on
RewriteCond   %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond   %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule   ^foo\.html$             foo.day.html
RewriteRule   ^foo\.html$             foo.night.html


これは 07:00-19:00 の間、URL foo.htmlfoo.day.html のコンテンツにして、それ以外の時間は foo.night.html のコンテンツにします。ホームページに未来があることを・・・

Backward Compatibility for YYYY to XXXX migration

Problem Description:

document.YYYY を document.XXXX に移動した後、例えば、.html のファイル群を .phtml に書き換えた後、URL の以前との互換性を実現するにはどうすればいいでしょう?

Problem Solution:

その基となる名前に名前を rewrite して、新しい拡張子で存在するものをテストします。 もし存在すれば、その名前を取ります。そうでなければオリジナルの状態の URL に rewrite します。

RewriteEngine on
RewriteBase   /~quux/
RewriteRule   ^(.*)\.html$              $1      [C,E=WasHTML:yes]
RewriteCond   %{REQUEST_FILENAME}.phtml -f
RewriteRule   ^(.*)$ $1.phtml                   [S=1]
RewriteCond   %{ENV:WasHTML}            ^yes$
RewriteRule   ^(.*)$ $1.html


Content Handling



From Old to New (intern)

Problem Description:

最近 bar.html というページを foo.html に名前を変えて、以前との互換性のために古い URL を与えたいとします。 古い URL のユーザはページの名前が変えられたことを認識すらしていないとします。

Problem Solution:

以下のようなルールによって、内部的に古い URL を新しいものに rewrite します:

RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^foo\.html$  bar.html


From Old to New (extern)

Problem Description:

再び bar.html ページが foo.html に名前を変更されて、以前との互換性のために古い URL を与えたいとします。 ただしこの時、古い URL のユーザは新しい方のヒントを持っているとします。ブラウザのロケーション・フィールドも変更するはずです。

Problem Solution:

ブラウザとユーザの見る画面の変更をする新しい URL に HTTP をリダイレクトさせます:

RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^foo\.html$  bar.html  [R]


Browser Dependend Content

Problem Description:

少なくとも重要な top-level のページのためには、しばしばブラウザの依存するコンテンツに最適な条件にする必要があります。 最新の Netscape の変数にはフルバージョン、Lynx ブラウザには最小バージョン、その他は平均的な機能のバージョンということです。

Problem Solution:

コンテンツ・ネゴシエーションは使えません。ブラウザがフォームの類を提供していないからです。 代わりに HTTP ヘッダで "User-Agent" を動かさねばなりません。以下のコードは次のことをします: HTTP ヘッダの "User-Agent" は "Mozilla/3" で始まり、foo.html ページは foo.NS.html に書き換えられて rewrite を停止します。 ブラウザはバージョン 1 か 2 の "Lynx" か "Mozilla" で、URL は foo.20.html になります。 全ての他のブラウザは foo.32.html ページを受け取ります。これは以下のルールセットで行われます:

RewriteCond %{HTTP_USER_AGENT}  ^Mozilla/3.*
RewriteRule ^foo\.html$         foo.NS.html          [L]

RewriteCond %{HTTP_USER_AGENT}  ^Lynx/.*         [OR]
RewriteCond %{HTTP_USER_AGENT}  ^Mozilla/[12].*
RewriteRule ^foo\.html$         foo.20.html          [L]

RewriteRule ^foo\.html$         foo.32.html          [L]


Dynamic Mirror

Problem Description:

自分の namespace に持ってきたいようなイカしたページがリモートのホストにあったとします。 FTP サーバなら、ローカルのマシーンにリモートのデータを最新のものにコピーする mirror プログラムを使います。 ウェブサーバなら HTTP 経由で似たようなことをする webcopy というプログラムを使います。しかし、どちらも大きな欠点が一つあります: 時々プログラムを走らせると、ローカルコピーは常に最新のものになります。もし設置しなければならないミラーが静的でなければ、ずっと良くなります。 代わりに、必要がある時に(リモートのホストでデータが更新された時)データを自動的にアップデートする動的なミラーをします。

Problem Solution:

そのためには、リモートのウェブページにマップするか、Proxy Throughput 機能 (flag [P]) を使って namespace をリモートのウェブエリアにします:

RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^hotsheet/(.*)$  http://www.tstimpreso.com/hotsheet/$1  [P]


RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^usa-news\.html$   http://www.quux-corp.com/news/index.html  [P]


Reverse Dynamic Mirror

Problem Description:

...

Problem Solution:



RewriteEngine on
RewriteCond   /mirror/of/remotesite/$1           -U
RewriteRule   ^http://www\.remotesite\.com/(.*)$ /mirror/of/remotesite/$1


Retrieve Missing Data from Intranet

Problem Description:

実際に運用、メインテナンスをしているのは、ファイアウォールによって保護されている(内部の)イントラネット・ウェブサーバ(www2.quux-corp.dom)で、 (外部の)インターネット・ウェブサーバ(www.quux-corp.dom)をバーチャルで走らせるトリックです。種明かしすると、内部から on-the-fly でリクエストされたデータを読み出すのが外部のウェブサーバ、ということになります。

Problem Solution:

まず、まだファイアウォールは内部のウェブサーバを保護していて、外部のウェブサーバだけがそこからデータを読み出すことを許可されています。 パケット・フィルタリングをしているファイアウォールとしては、例えば以下のようなファイアウォールのルールセットです:

ALLOW Host www.quux-corp.dom Port >1024 --> Host www2.quux-corp.dom Port 80
DENY  Host *                 Port *     --> Host www2.quux-corp.dom Port 80


実際のあなたの設定に合わせて編集します。プロキシーのスループット機能を通じて、裏で欠けているデータをリクエストする mod_rewrite ルールを設定することができます:

RewriteRule ^/~([^/]+)/?(.*)          /home/$1/.www/$2
RewriteCond %{REQUEST_FILENAME}       !-f
RewriteCond %{REQUEST_FILENAME}       !-d
RewriteRule ^/home/([^/]+)/.www/?(.*) http://www2.quux-corp.dom/~$1/pub/$2 [P]


Load Balancing

Problem Description:

www.foo.com に対するトラフィックのロードバランスを www[0-5].foo.com (全部で 6) 以上にしたいとします。 どうすれば良いでしょう?

Problem Solution:

これにはたくさんの解決方法があります。最初に、一般的に知られている DNS-based variant、そして mod_rewrite による特別な方法を紹介します:

  1. DNS Round-Robin

    ロードバランスのための最も簡単な方法は、BIND の DNS round-robin 機能を使うことです。 ここでは DNS の A(address) レコードで従来通り www[0-9].foo.com を設定します。例えば

    www0   IN  A       1.2.3.1
    www1   IN  A       1.2.3.2
    www2   IN  A       1.2.3.3
    www3   IN  A       1.2.3.4
    www4   IN  A       1.2.3.5
    www5   IN  A       1.2.3.6


    それに加えて、以下のエントリを追加します:

    www    IN  CNAME   www0.foo.com.
           IN  CNAME   www1.foo.com.
           IN  CNAME   www2.foo.com.
           IN  CNAME   www3.foo.com.
           IN  CNAME   www4.foo.com.
           IN  CNAME   www5.foo.com.
           IN  CNAME   www6.foo.com.


    これは間違っているように見えますが、実際に BIND の機能を果たすもので、この方法で使うことができます。しかし、www.foo.com がリソルバされると、 BIND は www0-www6 を出力します - いつでもわずかに入れ替わってローテーションします。この方法でクライアントは多くのサーバに散らばります。
    しかし、これは完璧なロードバランス機構ではありません。なぜなら、DNS リソルバ情報はネット上の他のネームサーバにキャッシュされていて、クライアントが一度www.foo.com を特定の wwwN.foo.com にリソルバすると、全ての続くリクエストもこの特定の wwwN.foo.com に向かうからです。 しかし、最終的には大丈夫です。リクエストのトータルな合計が本当に多くのウェブサーバに散るからです。

  2. DNS Load-Balancing

    ロードバランスのための洗練された DNS-based の方法は、http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html にあるような lbnamed プログラムを使うことです。DNS に真のロードバランスを与える、Perl 5 で書かれた補助ツールです。

  3. Proxy Throughput Round-Robin

    このやり方では、mod_rewrite とそのプロキシー・スループット機能を使います。まず、www0.foo.com が実際には DNS で単一のエントリ www.foo.com になるようにします。

    www    IN  CNAME   www0.foo.com.


    それから www0.foo.com をプロキシーだけのサーバに変換します。つまり、届く全ての URL が他の 5 つのサーバ(www1-www5)の一つに対する内部プロキシーを通じてプッシュされるように、このマシンを設定します。そのためには、全ての URL に対してロードバランスを取る lb.pl スクリプトと接触するようなルールセットにします。

    RewriteEngine on
    RewriteMap    lb      prg:/path/to/lb.pl
    RewriteRule   ^/(.+)$ ${lb:$1}           [P,L]


    それから lb.pl を書きます:

    $| = 1;
    
    $name   = "www";     # the hostname base
    $first  = 1;         # the first server (not 0 here, because 0 is myself)
    $last   = 5;         # the last server in the round-robin
    $domain = "foo.dom"; # the domainname
    
    $cnt = 0;
    while () {
        $cnt = (($cnt+1) % ($last+1-$first));
        $server = sprintf("%s%d.%s", $name, $cnt+$first, $domain);
        print "http://$server/$_";
    }
    


    最後に: 何故これが役に立つのでしょう?www0.foo.com がオーバーロードになるように見えませんか?答えは yes で、それはオーバーロードになります。 ただし単なるプロキシーのスループットとしてです!全ての SSI、CGI、ePerl等の処理は完全に他のマシンで行われます。ここがミソです。

  4. Hardware/TCP Round-Robin

    ハードウェア的な解決方法もあります。Cisco には TCP/IP レベルでロードバランスを取る LocalDirector という番犬がいます。 実はこれはウェブクラスタの前にたむろする、ある種の迂回レベルのゲートウェイです。もし資金が潤沢で、本当に高いパフォーマンスの解決が 必要なら、これを使ってください。


Reverse Proxy

Problem Description:

...

Problem Solution:



ServerType           standalone
Port                 8000
MinSpareServers      16
StartServers         16
MaxSpareServers      16
MaxClients           16
MaxRequestsPerChild  100

KeepAlive            on
MaxKeepAliveRequests 100
KeepAliveTimeout     15
Timeout              400
IdentityCheck        off
HostnameLookups      off

PidFile              /path/to/apache-rproxy.pid
LockFile             /path/to/apache-rproxy.lock
ErrorLog             /path/to/apache-rproxy.elog
CustomLog            /path/to/apache-rproxy.dlog "%{%v/%T}t %h -> %{SERVER}e URL: %U"

ServerRoot           /tmp
DocumentRoot         /tmp
CacheRoot            /tmp
RewriteLog           /dev/null
TransferLog          /dev/null
TypesConfig          /dev/null
AccessConfig         /dev/null
ResourceConfig       /dev/null


Options -FollowSymLinks -SymLinksIfOwnerMatch
AllowOverwrite None



SetHandler server-status


RewriteEngine        on
RewriteLogLevel      0

RewriteMap     server  rnd:/path/to/apache-rproxy.conf-servers

RewriteRule    ^/apache-rproxy-status.*  -  [L]
RewriteRule    ^(http|ftp)://.*          -  [F]

RewriteRule    ^/(.*\.(cgi|shtml))$  to://${server:dynamic}/$1  [S=1]
RewriteRule    ^/(.*)$               to://${server:static}/$1

RewriteRule    ^to://([^/]+)/(.*)    http://$1/$2   [E=SERVER:$1,P,L]

RewriteRule    .*                    -              [F]

ProxyRequests        on
NoCache              *

ProxyPassReverse  /  http://www1.foo.dom/
ProxyPassReverse  /  http://www2.foo.dom/
ProxyPassReverse  /  http://www3.foo.dom/
ProxyPassReverse  /  http://www4.foo.dom/
ProxyPassReverse  /  http://www5.foo.dom/
ProxyPassReverse  /  http://www6.foo.dom/


static    www1.foo.dom|www2.foo.dom|www3.foo.dom|www4.foo.dom

dynamic   www5.foo.dom|www6.foo.dom


New MIME-type, New Service

Problem Description:

ネット上にはたくさんの粋な CGI プログラムがあります。しかし、その使用法はいつもうんざりするもので、多くのウェブマスターはそれを使っていません。 CGI プログラムが、入力として特別な URL (実際には PATH_INFO と QUERY_STRINGS) を必要としない時に、MIME-type のための Apache Action ハンドラー機能でさえも割り当てるだけです。
まず、ポピュラーな cgiwrap プログラムによって処理される、.scgi (secure な CGI) という拡張子を持つ新しいファイルタイプを設定します。 ここで問題なのは、例えば、ユーザのホーム・ディレクトリ内部にあるファイルが URL /u/user/foo/bar.scgi という均一な URL Layout(上を参照) を使うことです。しかし、cgiwrap/~user/foo/bar.scgi/ という形式での URL を必要とします。以下のルールが問題を解決します:

RewriteRule ^/[uge]/([^/]+)/\.www/(.+)\.scgi(.*) ...
... /internal/cgi/user/cgiwrap/~$1/$2.scgi$3  [NS,T=application/x-http-cgi]


なにか粋なプログラムがいくつかあるとします: wwwlog (URL サブツリーに対する access.log を表示する) と wwwidx (URL サブツリーで Glimpse を走らせる)。作用する領域がわかっているので、これらのプログラムに対して URL 領域を与えなければなりません。しかし、普通これは不快なことです。なぜなら、いつもまだその領域からリクエストされるので、つまり、通常は不快なハイパーリンク

/internal/cgi/user/swwidx?i=/u/user/foo/
経由で /u/user/foo/ 内部から swwidx プログラムを走らせるからです。領域のロケーションハイパーリンク内部の CGI のロケーションの両方をハードコードしなければならないからです。 領域を再構成する時、様々なハイパーリンクを修正するのにたくさんの時間がかかります。

Problem Solution:

ここでの解決方法は、自動的に適切な CGI を実行するようにする特別な、新しい URL フォーマットを与えることです。 以下を設定します:

RewriteRule   ^/([uge])/([^/]+)(/?.*)/\*  /internal/cgi/user/wwwidx?i=/$1/$2$3/
RewriteRule   ^/([uge])/([^/]+)(/?.*):log /internal/cgi/user/wwwlog?f=/$1/$2$3


/u/user/foo/ で検索されるハイパーリンクが読むのは

href="*"
だけです。これは内部的には自動的に

/internal/cgi/user/wwwidx?i=/u/user/foo/
に変換されます。同じやり方で、ハイパーリンク :log が使われるとき、access log CGI プログラムのために実行するようになります。

From Static to Dynamic

Problem Description:

見られないような方法で、静的なページ foo.html を動的な foo.cgi に変換するにはどうしたらいいでしょう。ブラウザ、ユーザからの通知なしで。

Problem Solution:

CGI スクリプトに URL を rewrite して、CGI スクリプトとして本当に走るように正確な MIME-type にします。この方法で内部的な /~quux/foo.html へのリクエストは /~quux/foo.cgi を呼び出すようになります。

RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^foo\.html$  foo.cgi  [T=application/x-httpd-cgi]


On-the-fly Content-Regeneration

Problem Description:

ここでは、本当に難解な機能を実現します: 動的に生じて静的に提供されるページ、つまり、ページは静的なページとして配送されるが(ファイルシステムから読まれて、通過する)、もし見つからなくてもウェブサーバによって動的に生じているということです。 この方法で、人が(あるいはクーロン)静的なコンテンツを外さない限り静的に CGI が生じたページを持つことができます。 それからコンテンツは更新されます。

Problem Solution:

これは以下のルールセットで行われます:

RewriteCond %{REQUEST_FILENAME}   !-s
RewriteCond ^page\.html$          page.cgi   [T=application/x-httpd-cgi,L]


もし page.html がまだ行方不明か、ファイルサイズが null なら、page.html へのリクエストは page.cgi と一致する内部動作になります。page.cgi は、その出力を page.html というファイルに書き込む(加えてその STDOUT に) 普通の CGI スクリプト、というトリックです。 一度走ると、サーバは page.html のデータを送信します。ウェブマスターがコンテンツを更新したければ、単に page.html を削除するだけです(普通はクーロンで実行)。

Document With Autorefresh

Problem Description:

もしウェブブラウザが、編集によって新しいものを書いた時に、いつでもページを自動的に更新すれば、複雑なウェブページを作るのに便利ではないでしょうか? それは不可能でしょうか?

Problem Solution:

いいえ!単に MIME マルチパート機能、ウェブサーバの NPH 機能、そして mod_rewrite の URL 操作能力を組み合わせるだけです。 まず、新しい URL 機能を確立します: 何らかの URL に単に :refresh を追加して、ファイルシステムで更新した時にはいつでも、 最新のものになるようにします。

RewriteRule   ^(/[uge]/[^/]+/?.*):refresh  /internal/cgi/apache/nph-refresh?f=$1


今、以下の URL を参照すると、

/u/foo/bar/page.html:refresh
内部的な URL の実行を引き起こし、

/internal/cgi/apache/nph-refresh?f=/u/foo/bar/page.html
失われる部分は NPH-CGI スクリプトだけです。人はいつも"読み手に実行したものを残せ" ;-) と言うのですが、私はこれもちゃんとやっています。

$| = 1;

@pairs = split(/&/, $ENV{'QUERY_STRING'});
foreach $pair (@pairs) {
    ($name, $value) = split(/=/, $pair);
    $name =~ tr/A-Z/a-z/;
    $name = 'QS_' . $name;
    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
    eval "\$$name = \"$value\"";
}
$QS_s = 1 if ($QS_s eq '');
$QS_n = 3600 if ($QS_n eq '');
if ($QS_f eq '') {
    print "HTTP/1.0 200 OK\n";
    print "Content-type: text/html\n\n";
    print "<b>ERROR</b>: No file given\n";
    exit(0);
}
if (! -f $QS_f) {
    print "HTTP/1.0 200 OK\n";
    print "Content-type: text/html\n\n";
    print "<b>ERROR</b>: File $QS_f not found\n";
    exit(0);
}

sub print_http_headers_multipart_begin {
    print "HTTP/1.0 200 OK\n";
    $bound = "ThisRandomString12345";
    print "Content-type: multipart/x-mixed-replace;boundary=$bound\n";
    &print_http_headers_multipart_next;
}

sub print_http_headers_multipart_next {
    print "\n--$bound\n";
}

sub print_http_headers_multipart_end {
    print "\n--$bound--\n";
}

sub displayhtml {
    local($buffer) = @_;
    $len = length($buffer);
    print "Content-type: text/html\n";
    print "Content-length: $len\n\n";
    print $buffer;
}

sub readfile {
    local($file) = @_;
    local(*FP, $size, $buffer, $bytes);
    ($x, $x, $x, $x, $x, $x, $x, $size) = stat($file);
    $size = sprintf("%d", $size);
    open(FP, "<$file");
    $bytes = sysread(FP, $buffer, $size);
    close(FP);
    return $buffer;
}

$buffer = &readfile($QS_f);
&print_http_headers_multipart_begin;
&displayhtml($buffer);

sub mystat {
    local($file) = $_[0];
    local($time);

    ($x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime) = stat($file);
    return $mtime;
}

$mtimeL = &mystat($QS_f);
$mtime = $mtime;
for ($n = 0; $n < $QS_n; $n++) {
    while (1) {
        $mtime = &mystat($QS_f);
        if ($mtime ne $mtimeL) {
            $mtimeL = $mtime;
            sleep(2);
            $buffer = &readfile($QS_f);
            &print_http_headers_multipart_next;
            &displayhtml($buffer);
            sleep(5);
            $mtimeL = &mystat($QS_f);
            last;
        }
        sleep($QS_s);
    }
}

&print_http_headers_multipart_end;

exit(0);


Mass Virtual Hosting

Problem Description:

Apache の <VirtualHost> 機能は優れモノで、2、3、ダースの virtual host があっても、うまく動きます。 しかし、あなたが ISP で、数百の virtual host をこの機能で提供するのは、あまりいい選択ではありません。

Problem Solution:

この機能を提供するためには、リモートのウェブページをマップするか、Proxy Throughput 機能(flag [P])を使うことによって namespace に完全なリモートのウェブ領域をマップすることです:

www.vhost1.dom:80  /path/to/docroot/vhost1
www.vhost2.dom:80  /path/to/docroot/vhost2
     :
www.vhostN.dom:80  /path/to/docroot/vhostN


    :
UseCanonicalName on

    :
CustomLog  /path/to/access_log  "%{VHOST}e %h %l %u %t \"%r\" %>s %b"
    :

RewriteEngine on

RewriteMap    lowercase    int:tolower
RewriteMap    vhost        txt:/path/to/vhost.map

RewriteCond   %{REQUEST_URL}  !^/commonurl1/.*
RewriteCond   %{REQUEST_URL}  !^/commonurl2/.*
    :
RewriteCond   %{REQUEST_URL}  !^/commonurlN/.*
RewriteCond   %{HTTP_HOST}  !^$
RewriteCond   ${lowercase:%{HTTP_HOST}|NONE}  ^(.+)$
RewriteCond   ${vhost:%1}  ^(/.*)$
RewriteRule   ^/(.*)$   %1/$1  [E=VHOST:${lowercase:%{HTTP_HOST}}]
    : 


Access Restriction



Blocking of Robots

Problem Description:

実に不愉快なロボットが、特定のウェブエリアのページを読み出さないようにするには? "Robot Exclusion Protocol" のエントリを持っている /robots.txt ファイルでは、そのようなロボットから逃れるには不十分です。

Problem Solution:

ウェブエリア /~quux/foo/arc/ (おそらく、ロボットの横断がサーバのロードを大きくする最下層ディレクトリ) の URL を禁じるルールセットを使います 特定のロボットに対してだけアクセスを拒否するようにしなければなりません。言い換えれば、ロボットが走るホストを禁じるのでは不十分だということです。 これは、このロボットからのユーザも拒否します。User-Agent HTTP ヘッダ情報との一致によって、これを実現します。

RewriteCond %{HTTP_USER_AGENT}   ^NameOfBadRobot.*
RewriteCond %{REMOTE_ADDR}       ^123\.45\.67\.[8-9]$
RewriteRule ^/~quux/foo/arc/.+   -   [F]


Blocked Inline-Images

Problem Description:

インラインの GIF 画像が http://www.quux-corp.de/~quux/ のどこかのページにあるとします。 これらの画像がいい感じなので、そのページへのハイパーリンクによって誰かが直接取り込みます。 このやり方は感心しません。サーバに無駄なトラフィックが生じるからです。

Problem Solution:

含まれている画像を 100% 保護はできませんが、少なくともブラウザが HTTP Referer ヘッダを送信している場合を制限します。

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]
RewriteRule .*\.gif$        -                                    [F]


RewriteCond %{HTTP_REFERER}         !^$
RewriteCond %{HTTP_REFERER}         !.*/foo-with-gif\.html$
RewriteRule ^inlined-in-foo\.gif$   -                        [F]


Host Deny

Problem Description:

私達のサーバを使って外部的に設定されたホストのリストを禁じるにはどうすればいいでしょうか?

Problem Solution:

Apache 1.3b6 以降:

RewriteEngine on
RewriteMap    hosts-deny  txt:/path/to/hosts.deny
RewriteCond   ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR]
RewriteCond   ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND
RewriteRule   ^/.*  -  [F]
Apache 1.3b6 以前:

RewriteEngine on
RewriteMap    hosts-deny  txt:/path/to/hosts.deny
RewriteRule   ^/(.*)$ ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}/$1
RewriteRule   !^NOT-FOUND/.* - [F]
RewriteRule   ^NOT-FOUND/(.*)$ ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}/$1
RewriteRule   !^NOT-FOUND/.* - [F]
RewriteRule   ^NOT-FOUND/(.*)$ /$1


193.102.180.41 -
bsdti1.sdm.de  -
192.76.162.40  -


Proxy Deny

Problem Description:

Apache proxy の使用で、特定のホストや特別なホストのユーザを拒否するにはどうすれば良いでしょうか?

Problem Solution:

まず、Apache をコンパイルする時に Configuration ファイルで mod_rewrite が mod_proxy より下(!)になるようにしてください。 この方法は called _before_ mod_proxy と言われています。それから host-dependend deny... に対して以下を設定します。

RewriteCond %{REMOTE_HOST} ^badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.*  - [F]


user@host-dependend deny なら:

RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST}  ^badguy@badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.*  - [F]


Special Authentication Variant

Problem Description:

時々特殊な認証、例えばはっきり設定されたユーザチェックのための認証が必要とされます。 これらは明白な入力(mod_access による Basic Auth を使用した時に生じる)をうながさないでアクセスを受け入れるべきです。

Problem Solution:

友達を除いて、全てを締め出すために rewrite 条件のリストを使います:

RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend1@client1.quux-corp\.com$
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend2@client2.quux-corp\.com$
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend3@client3.quux-corp\.com$
RewriteRule ^/~quux/only-for-friends/      -                                 [F]


Referer-based Deflector

Problem Description:

"Referer" HTTP ヘッダで動く柔軟な URL Deflector をプログラムして、好みのたくさんの参照ページとして設定するにはどうしましょうか?

Problem Solution:

以下のようなトリッキーなルールセットを使います...

RewriteMap  deflector txt:/path/to/deflector.map

RewriteCond %{HTTP_REFERER} !=""
RewriteCond ${deflector:%{HTTP_REFERER}} ^-$
RewriteRule ^.* %{HTTP_REFERER} [R,L]

RewriteCond %{HTTP_REFERER} !=""
RewriteCond ${deflector:%{HTTP_REFERER}|NOT-FOUND} !=NOT-FOUND
RewriteRule ^.* ${deflector:%{HTTP_REFERER}} [R,L]


対応する rewrite マップと一緒に:

http://www.badguys.com/bad/index.html    -
http://www.badguys.com/bad/index2.html   -
http://www.badguys.com/bad/index3.html   http://somewhere.com/


これは自動的に参照ページ(マップで値として"-"が使われた時)か、特定の URL (URL が二番目の引数としてマップで指定された時) に対してリクエストをリダイレクトします。

Other



External Rewriting Engine

Problem Description:

FAQ: FOO/BAR/QUUX/etc. の問題をどうやって解決しますか?mod_rewrite を使って解決方法はないようですが。

Problem Solution:

外部 rewrite マップを使います。つまり rewrite マップのように動くプログラムです。 一度 Apache の起動時に走って、STDIN でリクエストされた URL を受け取り、STDOUT (同じ順番で) の URL (普通は rewrite されて) になります。

RewriteEngine on
RewriteMap    quux-map       prg:/path/to/map.quux.pl
RewriteRule   ^/~quux/(.*)$  /~quux/${quux-map:$1}


$| = 1;

while (<>) {
    s|^foo/|bar/|;
    print $_;
}


これはデモンストレーションのみのサンプルで、単に全ての URL /~quux/foo/.../~quux/bar/... に rewrite します。 実際にはあなたの好きなようにプログラムできます。しかし、そのマップは並みのユーザによっても使われ、システムの管理者はそれを定義するだけです。


このサイトは Apache URL Rewriting Guide サイトの日本語訳です。オリジナルのドキュメントは、これより新しくなっている可能性がありますので
http://www.engelschall.com/pw/apache/rewriteguide/ を見て下さい。 日本語訳に関する責任はインフォサイエンス(株)にあります。日本語訳に関する質問、誤訳の指摘などは japache@infoscience.co.jp まで御連絡ください。

翻訳の原文はここです。


このページの情報に関わる、ご質問、お問い合わせは、
japache@infoscience.co.jpまで。

JAPACHE ホームページ