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.
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.
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.
Script |
Script method cgi-script Server config, virtual host, directory Script is only available in Apache 1.1 and later; arbitrary method use is only available with 1.3.10 and later.
This directive adds an action, which will activate cgi-script when a file is requested using the method of method. It sends the URL and file path of the requested document using the standard CGI PATH_INFO and PATH_TRANSLATED environment variables. This is useful if you want to compress on the fly, for example, or implement PUT.
Prior to Apache 1.3.10, method can only be one of GET, POST, PUT, or DELETE. As of 1.3.10, any arbitrary method name may be used. Method names are case sensitive, so Script PUT and Script put have two entirely different effects. (The uses of the HTTP methods are described in greater detail in Chapter 13.)
Note that the Script command defines default actions only. If a CGI script is called, or some other resource that is capable of handling the requested method internally, it will do so. Also note that Script with a method of GET will only be called if there are query arguments present (e.g., foo.html?hi). Otherwise, the request will proceed normally.
# For <ISINDEX>-style searching Script GET /cgi-bin/search # A CGI PUT handler Script PUT /~bob/put.cgi
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/ ...
ScriptAliasMatch |
ScriptAliasMatch regex directory_or_filename Server config, virtual host
The supplied regular expression is matched against the URL; if it matches, the server will substitute any parenthesized matches into the given string and use them as a filename. For example, to activate the standard /cgi-bin, one might use:
ScriptAliasMatch ^/cgi-bin/(.*) /usr/local/apache/cgi-bin/$1
.* is a regular expression like those in Perl that match any character (.) any number of times (*). Here, this will be the name of the file we want to execute. Putting it in parentheses (.*) stores the characters in the variable $1, which is then invoked:
/usr/local/apache/cgi-bin/$1.
You can start the matching further along. If all your script filenames start with the letters "BT," you could write:
ScriptAliasMatch ^/cgi-bin/BT(.*) /usr/local/apache/cgi-bin/BT$1
If the visitor got here by following a link on the web page:
...<a href="/cgi-bin/BTmyscript/customer56/ice_cream">...
ScriptAliasMatch will run BTmyscript. If it accesses the environment variable PATH_INFO (described in Chapter 14), it will find /customer56/ice_cream.
You can have as many of these useful directives as you like in your Config file to cover different situations. For more information on regular expressions, see Mastering Regular Expressions by Jeffrey Friedl (O'Reilly, 2002) or Programming Perl by Larry Wall, Jon Orwant, and Tom Christiansen (O'Reilly, 2001).
ScriptInterpreterSource |
ScriptInterpreterSource registry|script Default: ScriptInterpreterSource script directory, .htaccess
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
AliasMatch |
AliasMatch regex directory_or_filename Server config, virtual host
Again, like ScriptAliasMatch, this directive takes a regular expression as the first argument. Otherwise, it is the same as Alias.
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:
The name of a directory or a pattern such as those shown in the examples that follow.
The keyword disabled. This turns off all username-to-directory translations except those explicitly named with the enabled keyword.
The keyword disabled followed by a space-delimited list of usernames. Usernames that appear in such a list will never have directory translation performed, even if they appear in an enabled clause.
The keyword enabled followed by a space-delimited list of usernames. These usernames will have directory translation performed even if a global disable is in effect, but not if they also appear in a disabled clause.
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.
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.
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:
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).
RedirectMatch |
RedirectMatch regex url Server config, virtual host, directory, .htaccess
Again, RedirectMatch works like Redirect, except that it takes a regular expression (discussed earlier under ScriptAliasMatch) as its first argument.
In the Butterthlies business, sad to relate, the salespeople have been abusing their powers and perquisites, and it has been decided to teach them a lesson by hiding their beloved secrets file and sending them to the ordinary customers' site when they try to access it. How humiliating! Easily done, though.
The Config file is httpd3.conf :
...
<VirtualHost sales.butterthlies.com>
ServerAdmin [email protected]
Redirect /secrets http://www.butterthlies.com
DocumentRoot /usr/www/APACHE3/site.alias/htdocs/salesmen
...
The exact placing of the Redirect doesn't matter, as long as it is somewhere in the <VirtualHost> section. If you now access http://sales.butterthlies.com/secrets, you are shunted straight to the customers' index at http://www.butterthlies.com /.
It is somewhat puzzling that if the Redirect line fails to work because you have misspelled the URL, there may be nothing in the error_log because the browser is vainly trying to find it out on the Web.
An important difference between Alias and Redirect is that the browser becomes aware of the new location in a Redirect, but not in an Alias, and this new location will be used as the basis for relative hot links found in the retrieved HTML.
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.
Copyright © 2003 O'Reilly & Associates. All rights reserved.