home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Apache The Definitive Guide, 3rd EditionApache: The Definitive GuideSearch this book

Chapter 8. Redirection

Few things are ever in exactly the right place at the right time, and this is as true of most web servers as of anything else. Alias and Redirect allow requests to be shunted about your filesystem or around the Web. Although in a perfect world it should never be necessary to do this, in practice it is often useful to move HTML files around on the server — or even to a different server — without having to change all the links in the HTML document.[31] A more legitimate use — of Alias, at least — is to rationalize directories spread around the system. For example, they may be maintained by different users and may even be held on remotely mounted filesystems. But Alias can make them appear to be grouped in a more logical way.

[31]Too much of this kind of thing can make your site difficult to maintain.

A related directive, ScriptAlias, allows you to run CGI scripts, discussed in Chapter 16. You have a choice: everything that ScriptAlias does, and much more, can be done by the new Rewrite directive (described later in this chapter), but at a cost of some real programming effort. ScriptAlias is relatively simple to use, but it is also a good example of Apache's modularity being a little less modular than we might like. Although ScriptAlias is defined in mod_alias.c in the Apache source code, it needs mod_cgi.c (or any module that does CGI) to function — it does, after all, run CGI scripts. mod_alias.c is compiled into Apache by default.

Some care is necessary in arranging the order of all these directives in the Config file. Generally, the narrower choices should come first, with the "catch-all" versions at the bottom. Be prepared to move them around (restarting Apache each time, of course) until you get the effect you want.

Our base httpd1.conf file on ... /site.alias, to which we will add some directives, contains the following:

User webuser
Group webgroup

NameVirtualHost 192.168.123.2

<VirtualHost www.butterthlies.com>
ServerName www.butterthlies.com
DocumentRoot /usr/www/APACHE3/site.alias/htdocs/customers
ErrorLog /usr/www/APACHE3/site.alias/logs/error_log
TransferLog /usr/www/APACHE3/site.alias/logs/access_log
</VirtualHost>

<VirtualHost sales.butterthlies.com>
DocumentRoot /usr/www/APACHE3/site.alias/htdocs/salesmen
ServerName sales.butterthlies.com
ErrorLog /usr/www/APACHE3/site.alias/logs/error_log
TransferLog /usr/www/APACHE3/site.alias/logs/access_log
</VirtualHost>

Start it with ./go 1. It should work as you would expect, showing you the customers' and salespeople's directories.

8.1. Alias

One of the most useful directives is Alias, which lets you store documents elsewhere. We can demonstrate this simply by creating a new directory, /usr/www/APACHE3/somewhere_else, and putting in it a file lost.txt, which has this message in it:

I am somewhere else

httpd2.conf has an extra line:

...
Alias /somewhere_else /usr/www/APACHE3/somewhere_else
...

Stop Apache and run ./go 2. From the browser, access http://www.butterthlies.com/somewhere_else/. We see the following:

Index of /somewhere_else
. Parent Directory
. lost.txt

If we click on Parent Directory, we arrive at the DocumentRoot for this server, /usr/www/APACHE3/site.alias/htdocs/customers, not, as might be expected, at /usr/www/APACHE3. This is because Parent Directory really means "parent URL," which is http://www.butterthlies.com/ in this case.

What sometimes puzzles people (even those who know about it but have temporarily forgotten) is that if you go to http://www.butterthlies.com/ and there's no ready-made index, you don't see somewhere_else listed.

8.1.1. A Subtle Problem

Note that you do not want to write:

Alias /somewhere_else/ /usr/www/APACHE3/somewhere_else

The trailing / on the alias will prevent things working. To understand this, imagine that you start with a web server that has a subdirectory called fred in its DocumentRoot. That is, there's a directory called /www/docs/fred, and the Config file says:

DocumentRoot /www/docs

The URL http://your.webserver.com/fred fails because there is no file called fred. However, the request is redirected by Apache to http://your.webserver.com/fred/, which is then handled by looking for the directory index of /fred.

So, if you have a web page that says:

<a href="/fred">Take a look at fred</a>

it will work. When you click on "Take a look at fred," you get redirected, and your browser looks for:

 http://your.webserver.com/fred/ 

as its URL, and all is well.

One day, you move fred to /some/where/else. You alter your Config file:

Alias /fred/ /some/where/else

or, equally ill-advisedly:

Alias /fred/ /some/where/else/

You put the trailing / on the aliases because you wanted to refer to a directory. But either will fail. Why?

The URL http://your.webserver.com/fred fails because there is no file /www/docs/fred anymore. In spite of the altered line in the Config file, this is what the URL still maps to, because /fred doesn't match /fred/, and Apache no longer has a reason to redirect.

But using this Alias (without the trailing / on the alias):

Alias /fred /some/where/else

means that http://your.webserver.com/fred maps to /some/where/else instead of /www/docs/fred. It is once more recognized as a directory and is automatically redirected to the right place.

Note that it would be wrong to make Apache detect this and do the redirect, because it is legitimate to actually have both a file called fred in /www/docs and an alias for /fred/ that sends requests for /fred/* elsewhere.

It would also be wrong to make Apache bodge the URL and add a trailing slash when it is clear that a directory is meant rather than a filename. The reason is that if a file in that directory wants to refer visitors to a subdirectory .../fred/bill, the new URL is made up by the browser. It can only do this if it knows that fred is a directory, and the only way it can get to know this is if Apache redirects the request for .../fred to /fred/.

The same effect was produced on our system by leaving the ServerName directive outside the VirtualHost block. This is because, being outside the VirtualHost block, it doesn't apply to the virtual host. So the previously mentioned redirect doesn't work because it uses ServerName in autogenerated redirects. Presumably this would only cause a problem depending on IPs, reverse DNS, and so forth.

ScriptAlias

ScriptAlias url_path directory_or_filename 
Server config, virtual host

ScriptAlias allows scripts to be stored safely out of the way of prying fingers and, moreover, automatically marks the directory where they are stored as containing CGI scripts. For instance, see ...site.cgi/conf/httpd0.conf:

...
ScriptAlias /cgi-bin/ /usr/www/apache3/cgi-bin/
...
ScriptInterpreterSource

ScriptInterpreterSource registry|script
Default: ScriptInterpreterSource script 
directory, .htaccess

Figure

This directive is used to control how Apache 1.3.5 and later finds the interpreter used to run CGI scripts. The default technique is to use the interpreter pointed to by the #! line in the script. Setting the ScriptInterpreterSource registry will cause the Windows registry to be searched using the script file extension (e.g., .pl) as a search key.

Alias

Alias url_path directory_or_filename
Server config, virtual host

Alias is used to map a resource's URL to its physical location in the filesystem, regardless of where it is relative to the document root. For instance, see .../site.alias/conf/httpd.conf:

...
Alias /somewhere_else/ /usr/www/APACHE3/somewhere_else/
...

There is a directory /usr/www/APACHE3/somewhere_else/, which contains a file lost.txt. If we navigate to www.butterthlies.com/somewhere_else, we see:

Index of /somewhere_else
    Parent Directory 
    lost.txt 
UserDir



UserDir directory
Default: UserDir public_html
Server config, virtual host

The basic idea here is that the client is asking for data from a user's home directory. He asks for http://www.butterthlies.com/~peter, which means "Peter's home directory on the computer whose DNS name is www.butterthlies.com." The UserDir directive sets the real directory in a user's home directory to use when a request for a document is received from a user. directory is one of the following:

If neither the enabled nor the disabled keyword appears in the UserDir directive, the argument is treated as a filename pattern and is used to turn the name into a directory specification. A request for http://www.foo.com/~bob/one/two.html will be translated as follows:

UserDir public_html     -> ~bob/public_html/one/two.html
UserDir /usr/web        -> /usr/web/bob/one/two.html
UserDir /home/*/www/APACHE3     -> /home/bob/www/APACHE3/one/two.html

The following directives will send the redirects shown to their right to the client:

UserDir http://www.foo.com/users -> http://www.foo.com/users/bob/one/two.html
UserDir http://www.foo.com/*/usr -> http://www.foo.com/bob/usr/one/two.html
UserDir http://www.foo.com/~*/   -> http://www.foo.com/~bob/one/two.html

Be careful when using this directive; for instance, UserDir ./ would map /~root to /, which is probably undesirable. If you are running Apache 1.3 or above, it is strongly recommended that your configuration include a UserDir disabled root declaration.

Figure

Under Win32, Apache does not understand home directories, so translations that end up in home directories on the righthand side (see the first example) will not work.

Redirect

Redirect [status] url-path url
Server config, virtual host, directory, .htaccess

The Redirect directive maps an old URL into a new one. The new URL is returned to the client, which attempts to fetch the information again from the new address. url-path is a (%-decoded) path; any requests for documents beginning with this path will be returned a redirect error to a new (%-encoded) URL beginning with url.

Example

Redirect /service http://foo2.bar.com/service

If the client requests http://myserver/service/foo.txt, it will be told to access http://foo2.bar.com/service/foo.txt instead.

TIP: Redirect directives take precedence over Alias and ScriptAlias directives, irrespective of their ordering in the configuration file. Also, url-path must be an absolute path, not a relative path, even when used with .htaccess files or inside of <Directory> sections.

If no status argument is given, the redirect will be "temporary" (HTTP status 302). This indicates to the client that the resource has moved temporarily. The status argument can be used to return other HTTP status codes:

permanent
Returns a permanent redirect status (301) indicating that the resource has moved permanently.

temp
Returns a temporary redirect status (302). This is the default.

seeother
Returns a "See Other" status (303) indicating that the resource has been replaced.

gone
Returns a "Gone" status (410) indicating that the resource has been permanently removed. When this status is used, the url argument should be omitted.

Other status codes can be returned by giving the numeric status code as the value of status. If the status is between 300 and 399, the url argument must be present, otherwise it must be omitted. Note that the status must be known to the Apache code (see the function send_error_response in http_protocol.c).

RedirectTemp

RedirectTemp url-path url
Server config, virtual host, directory, .htaccess

This directive makes the client know that the Redirect is only temporary (status 302). This is exactly equivalent to Redirect temp.

RedirectPermanent

RedirectPermanent url-path url
Server config, virtual host, directory, .htaccess

This directive makes the client know that the Redirect is permanent (status 301). This is exactly equivalent to Redirect permanent.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.