📄 rewriteguide.html.en
字号:
character of the username. So, <code>/~foo/anypath</code> is <code>/home/<strong>f</strong>/foo/.www/anypath</code> while <code>/~bar/anypath</code> is <code>/home/<strong>b</strong>/bar/.www/anypath</code>.</p> </dd> <dt>Solution:</dt> <dd> <p>We use the following ruleset to expand the tilde URLs into exactly the above layout.</p><div class="example"><pre>RewriteEngine onRewriteRule ^/~(<strong>([a-z])</strong>[a-z0-9]+)(.*) /home/<strong>$2</strong>/$1/.www$3</pre></div> </dd> </dl> <h3>Filesystem Reorganization</h3> <dl> <dt>Description:</dt> <dd> <p>This really is a hardcore example: a killer application which heavily uses per-directory <code>RewriteRules</code> to get a smooth look and feel on the Web while its data structure is never touched or adjusted. Background: <strong><em>net.sw</em></strong> is my archive of freely available Unix software packages, which I started to collect in 1992. It is both my hobby and job to to this, because while I'm studying computer science I have also worked for many years as a system and network administrator in my spare time. Every week I need some sort of software so I created a deep hierarchy of directories where I stored the packages:</p><div class="example"><pre>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/</pre></div> <p>In July 1996 I decided to make this archive public to the world via a nice Web interface. "Nice" means that I wanted to offer an interface where you can browse directly through the archive hierarchy. And "nice" means that I didn't wanted to change anything inside this hierarchy - not even by putting some CGI scripts at the top of it. Why? Because the above structure should be later accessible via FTP as well, and I didn't want any Web or CGI stuff to be there.</p> </dd> <dt>Solution:</dt> <dd> <p>The solution has two parts: The first is a set of CGI scripts which create all the pages at all directory levels on-the-fly. I put them under <code>/e/netsw/.www/</code> as follows:</p><div class="example"><pre>-rw-r--r-- 1 netsw users 1318 Aug 1 18:10 .wwwacldrwxr-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.cgidrwxr-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</pre></div> <p>The <code>DATA/</code> subdirectory holds the above directory structure, i.e. the real <strong><em>net.sw</em></strong> stuff and gets automatically updated via <code>rdist</code> from time to time. The second part of the problem remains: how to link these two structures together into one smooth-looking URL tree? We want to hide the <code>DATA/</code> directory from the user while running the appropriate CGI scripts for the various URLs. Here is the solution: first I put the following into the per-directory configuration file in the <code class="directive"><a href="../mod/core.html#documentroot">DocumentRoot</a></code> of the server to rewrite the announced URL <code>/net.sw/</code> to the internal path <code>/e/netsw</code>:</p><div class="example"><pre>RewriteRule ^net.sw$ net.sw/ [R]RewriteRule ^net.sw/(.*)$ e/netsw/$1</pre></div> <p>The first rule is for requests which miss the trailing slash! The second rule does the real thing. And then comes the killer configuration which stays in the per-directory config file <code>/e/netsw/.www/.wwwacl</code>:</p><div class="example"><pre>Options ExecCGI FollowSymLinks Includes MultiViewsRewriteEngine on# we are reached via /net.sw/ prefixRewriteBase /net.sw/# first we rewrite the root dir to# the handling cgi scriptRewriteRule ^$ netsw-home.cgi [L]RewriteRule ^index\.html$ netsw-home.cgi [L]# strip out the subdirs when# the browser requests us from perdir pagesRewriteRule ^.+/(netsw-[^/]+/.+)$ $1 [L]# and now break the rewriting for local filesRewriteRule ^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]# anything else is a subdir which gets handled# by another cgi scriptRewriteRule !^netsw-lsdir\.cgi.* - [C]RewriteRule (.*) netsw-lsdir.cgi/$1</pre></div> <p>Some hints for interpretation:</p> <ol> <li>Notice the <code>L</code> (last) flag and no substitution field ('<code>-</code>') in the forth part</li> <li>Notice the <code>!</code> (not) character and the <code>C</code> (chain) flag at the first rule in the last part</li> <li>Notice the catch-all pattern in the last rule</li> </ol> </dd> </dl> <h3>NCSA imagemap to Apache <code>mod_imap</code></h3> <dl> <dt>Description:</dt> <dd> <p>When switching from the NCSA webserver to the more modern Apache webserver a lot of people want a smooth transition. So they want pages which use their old NCSA <code>imagemap</code> program to work under Apache with the modern <code class="module"><a href="../mod/mod_imap.html">mod_imap</a></code>. The problem is that there are a lot of hyperlinks around which reference the <code>imagemap</code> program via <code>/cgi-bin/imagemap/path/to/page.map</code>. Under Apache this has to read just <code>/path/to/page.map</code>.</p> </dd> <dt>Solution:</dt> <dd> <p>We use a global rule to remove the prefix on-the-fly for all requests:</p><div class="example"><pre>RewriteEngine onRewriteRule ^/cgi-bin/imagemap(.*) $1 [PT]</pre></div> </dd> </dl> <h3>Search pages in more than one directory</h3> <dl> <dt>Description:</dt> <dd> <p>Sometimes it is necessary to let the webserver search for pages in more than one directory. Here MultiViews or other techniques cannot help.</p> </dd> <dt>Solution:</dt> <dd> <p>We program a explicit ruleset which searches for the files in the directories.</p><div class="example"><pre>RewriteEngine on# first try to find it in custom/...# ...and if found stop and be happy:RewriteCond /your/docroot/<strong>dir1</strong>/%{REQUEST_FILENAME} -fRewriteRule ^(.+) /your/docroot/<strong>dir1</strong>/$1 [L]# second try to find it in pub/...# ...and if found stop and be happy:RewriteCond /your/docroot/<strong>dir2</strong>/%{REQUEST_FILENAME} -fRewriteRule ^(.+) /your/docroot/<strong>dir2</strong>/$1 [L]# else go on for other Alias or ScriptAlias directives,# etc.RewriteRule ^(.+) - [PT]</pre></div> </dd> </dl> <h3>Set Environment Variables According To URL Parts</h3> <dl> <dt>Description:</dt> <dd> <p>Perhaps you want to keep status information between requests and use the URL to encode it. But you don't want to use a CGI wrapper for all pages just to strip out this information.</p> </dd> <dt>Solution:</dt> <dd> <p>We use a rewrite rule to strip out the status information and remember it via an environment variable which can be later dereferenced from within XSSI or CGI. This way a URL <code>/foo/S=java/bar/</code> gets translated to <code>/foo/bar/</code> and the environment variable named <code>STATUS</code> is set to the value "java".</p><div class="example"><pre>RewriteEngine onRewriteRule ^(.*)/<strong>S=([^/]+)</strong>/(.*) $1/$3 [E=<strong>STATUS:$2</strong>]</pre></div> </dd> </dl> <h3>Virtual User Hosts</h3> <dl> <dt>Description:</dt> <dd> <p>Assume that you want to provide <code>www.<strong>username</strong>.host.domain.com</code> for the homepage of username via just DNS A records to the same machine and without any virtualhosts on this machine.</p> </dd> <dt>Solution:</dt> <dd> <p>For HTTP/1.0 requests there is no solution, but for HTTP/1.1 requests which contain a Host: HTTP header we can use the following ruleset to rewrite <code>http://www.username.host.com/anypath</code> internally to <code>/home/username/anypath</code>:</p><div class="example"><pre>RewriteEngine onRewriteCond %{<strong>HTTP_HOST</strong>} ^www\.<strong>[^.]+</strong>\.host\.com$RewriteRule ^(.+) %{HTTP_HOST}$1 [C]RewriteRule ^www\.<strong>([^.]+)</strong>\.host\.com(.*) /home/<strong>$1</strong>$2</pre></div> </dd> </dl> <h3>Redirect Homedirs For Foreigners</h3> <dl> <dt>Description:</dt> <dd> <p>We want to redirect homedir URLs to another webserver <code>www.somewhere.com</code> when the requesting user does not stay in the local domain <code>ourdomain.com</code>. This is sometimes used in virtual host contexts.</p> </dd> <dt>Solution:</dt> <dd> <p>Just a rewrite condition:</p><div class="example"><pre>RewriteEngine onRewriteCond %{REMOTE_HOST} <strong>!^.+\.ourdomain\.com$</strong>RewriteRule ^(/~.+) http://www.somewhere.com/$1 [R,L]</pre></div> </dd> </dl> <h3>Redirect Failing URLs To Other Webserver</h3> <dl> <dt>Description:</dt> <dd> <p>A typical FAQ about URL rewriting is how to redirect failing requests on webserver A to webserver B. Usually this is done via <code class="directive"><a href="../mod/core.html#errordocument">ErrorDocument</a></code> CGI-scripts in Perl, but there is also a <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> solution. But notice that this performs more poorly than using an <code class="directive"><a href="../mod/core.html#errordocument">ErrorDocument</a></code> CGI-script!</p> </dd> <dt>Solution:</dt> <dd> <p>The first solution has the best performance but less flexibility, and is less error safe:</p><div class="example"><pre>RewriteEngine onRewriteCond /your/docroot/%{REQUEST_FILENAME} <strong>!-f</strong>RewriteRule ^(.+) http://<strong>webserverB</strong>.dom/$1</pre></div> <p>The problem here is that this will only work for pages inside the <code class="directive"><a href="../mod/core.html#documentroot">DocumentRoot</a></code>. While you can add more Conditions (for instance to also handle homedirs, etc.) there is better variant:</p><div class="example"><pre>RewriteEngine onRewriteCond %{REQUEST_URI} <strong>!-U</strong>RewriteRule ^(.+) http://<strong>webserverB</strong>.dom/$1</pre></div>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -