Hack 98 Directory Aliasing, Indexing, and Autoindexing


A few more Apache configuration hacks involving creating an alias to a file outside the normal Apache document hierarchy and customizing the look-and-feel of directory listings.

When it comes to URLs that end in slashes and resolve to a directory on your web site, Apache can serve data two different ways. The most common is to serve the directory index, a list of filenames that can be used in place of the directory slash. The other possibility is to have Apache generate a bland list of filenames. In this hack, we'll talk about modifying the directory index to match your needs, as well as making that bland autoindex more attractive.

98.1 Aliases

Before we begin indexes, let's talk about aliasing. If you've read [Hack #92], you'll know a ScriptAlias directive is a way to map a URL to a location on our hard drive. You can read more about the other capabilities of Apache's mod_alias at the Apache web site (http://httpd.apache.org/docs/mod/mod_alias.html), but here's a simple example of making /Users/morbus/Pictures/ accessible as

Alias /~morbus/pictures/ "/Users/morbus/Pictures/"

When creating aliases like this, you want to be careful about permissions. Mac users have never had to deal with permissions before, so they can be an interesting thing to muddle through. We won't get into a detailed description here, but in a simplified nutshell:

  • User directories like Pictures, Library, Music, and so forth are not normally viewable by the Apache web server; the permissions are too restrictive.

  • Simply creating an alias probably will not work. Sure, you're telling Apache to serve files from that location, but that directory is still protected from other users (one of them is www, which Apache runs as). Again, the permissions are still too restrictive.

  • In this case, to give Apache permission to access the /Users/morbus/Pictures/ directory, we need to say chmod 755 /Users/morbus/Pictures in our Terminal [Hack #48]. This loosens the permissions and allows Apache to read from, but not write to, files in that directory.

Here's another example of aliasing, only more powerful:

<Directory "/Developer/Documentation/">
  Options FollowSymLinks Indexes

AliasMatch ^/~morbus/docs/(.*) "/Developer/Documentation/"

Here, we're taking every file and directory accessed under /Users/morbus/docs and instead serving them from /Developer/Documentation. Accessing would serve /Developer/Documentation/Carbon/carbon.html; likewise, would return an index of the entire /Developer/Documentation/Carbon/ directory.

98.2 Directory Indexes

Why does Apache sometimes serve a listing of files in a directory, as it did for Carbon/, and other times serve an HTML document, often called index.html? The key is a directive within the Apache configuration file called DirectoryIndex. By default, on OS X it's:

DirectoryIndex index.html

What this means is that if a file called index.html is in a directory, Apache will serve that file instead of autogenerating a file listing. Remove the file, and Apache's back to spitting out what it can find: the contents of the directory itself.

We're not restricted to only one possible directory index. We could use index.html all of the time, index.php some of the time, and perhaps insomnia caused the rather suggestive zzzdex.shtml. Apache can be told to look for all of these, in order of preference:

DirectoryIndex index.html index.php index.cgi zzzdex.shtml

In this case, we're saying "Hey, if someone doesn't request a particular file in a URL, then look for index.html. If it's there, cool, display that. If not, try looking for index.php. If that's not there, try zzzdex.shtml. If that's not there, then yeah, I suppose you can automatically generate an index."

You can add as many entries as you wish to the DirectoryIndex, but you do want to try to keep the most common filename first. If you're serving thousands of pages a second, a properly ordered directory index will save you a tiny bit of time and processing.

98.3 Customizing the Directory Listing

There are times when we do want Apache to autogenerate a listing, and the mod_autoindex (http://httpd.apache.org/docs/mod/mod_autoindex.html) Apache module gives us a lot of power in customizing the autogenerated appearance. For instance, you can control the initial sorting order, the descriptions of the files shown, and even include headers or footers (in HTML with optional server-side includes or plain text).

Take the following example. This will add a descriptive element to all our JPEG images and a different description to all our PHP files. When Apache autogenerates the index, it'll display our blurbage for each matching file:

<Directory "/Users/morbus/Sites/">
  Options Includes Indexes Multiviews
  AllowOverride All
  IndexOptions FancyIndexing 
  AddDescription "This is a short description" *.jpg 
  AddDescription "This is a description of questionable quality." *.php

There's one problem, however, and that's length. With the look-and-feel of Apache's autoindex, the description is either cut off arbitrarily, or else the browser will scroll the data off screen. That's where HeaderName and ReadmeName come in. These directives tell Apache which files to use as the header (controlled by HeaderName) and footer (controlled by ReadmeName) of a directory listing. By default, these files are HEADER.txt (or HEADER.html) and README.txt (or README.html), respectively.

With that in mind, I'll create HEADER.html, like so:

<style type="text/css"><!--
pre { font-size: 14px; font-family: times, serif; }
<h1>Smurferific Directory Listings</h1>

I'll also tweak the configuration a little:

<Directory "/Users/morbus/Sites/">
  Options Includes Indexes Multiviews
  AllowOverride All
  IndexOptions FancyIndexing SuppressHTMLPreamble DescriptionWidth=*
  AddDescription "This is a <u>short</u> description" *.jpg 
  AddDescription "This is a description of questionable quality." *.php

Besides the fact that we've now added our own HTML header that makes the font smaller (via HEADER.html), we've also told Apache not to spit out its normal header code (with SuppressHTMLPreamble). Our descriptions will no longer be truncated, since we've given ourselves unlimited length via DescriptionWidth (they may still scroll off the end of the browser window, though).

You may also notice that we've added an underline to one of our descriptions. Including HTML within the AddDescription comes with no restrictions, but you do want to be careful about truncating. If you're not, the HTML code could be cut in half, distorting the rest of your page (in the previous code, there's nothing to worry about, since we've turned off truncating with DescriptionWidth).

There are many other options available. With a little ingenuity, a user wanting to offer a large collection of downloadable files could have a complete web site in 10 minutes. Think of it ? thousands of MP3s sorted and described, using only two HTML files and some AddDescription lines. Need to add a new song? Just stick it in the directory, add a description, and you're done. No muss, no fuss, and you didn't need any database or programming knowledge.

Of course, you may not like the idea that millions of anonymous Internet users could leech your MP3 collection. With the tips described in [Hack #97], you'll be able to stop the tragedy of the commons and restore a little more order.