Table of Contents



dirplex - Physical directory handler for ashd(7)


dirplex [-hN] [-c CONFIG] DIR


The dirplex handler maps URLs into physical files or directories, and, having found a matching file or directory, it performs various kinds of pattern-matching against its physical name to determine what handler to call in order to serve the request. The mapping procedure and pattern matching are described below.

Having found a handler to serve a file or directory with, dirplex adds the X-Ash-File header to the request with a path to the physical file, before passing the request on to the handler.

dirplex is a persistent handler, as defined in ashd(7).


Print a brief help message to standard output and exit.
Do not read the global configuration file dirplex.rc.
Read an extra configuration file. If CONFIG contains any slashes, it is opened by that exact name. Otherwise, it is searched for in the same way as the global configuration file (see CONFIGURATION below).


Mapping URLs into physical files is an iterative procedure, each step looking in one single physical directory, starting with DIR. For each step, a path element is stripped off the beginning of the rest string and examined, the path element being either the leading part of the rest string up until (but not including) the first slash, or the entire rest string if it contains no slashes. If the rest string is empty, the directory being examined is considered the result of the mapping. Otherwise, any escape sequences in the path element under consideration are unescaped before examining it.

If the path element names a directory in the current directory, the procedure continues in that directory, unless there is nothing left of the rest string, in which case dirplex responds with a HTTP 301 redirect to the same URL, but ending with a slash. Otherwise, the remaining rest string begins with a slash, which is stripped off before continuing. If the path element names a file, that file is considered the result of the mapping (even if the rest string has not been exhausted yet).

If the path element does not name anything in the directory under consideration, but contains no dots, then the directory is searched for a file whose name before the first dot matches the path element. If there is such a file, it is considered the result of the mapping.

If the result of the mapping procedure is a directory, it is checked for the presence of a file named by the index-file configuration directive (see CONFIGURATION below). If there is such a file, it is considered the final result instead of the directory itself. If the index file name contains no dots and there is no exact match, then, again, the directory is searched for a file whose name before the first dot matches the index file name.

See also 404 RESPONSES below.


Configuration in dirplex comes from several sources. When dirplex starts, unless the -N option is given, it tries to find a global configuration file named dirplex.rc. It looks in $HOME/.ashd/etc, and then in all directories named by the PATH environment variable, appended with ../etc/ashd. For example, then, if PATH is /usr/local/bin:/bin:/usr/bin, the directories $HOME/.ashd/etc, /usr/local/etc/ashd, /etc/ashd and /usr/etc/ashd are searched for dirplex.rc, in that order. Only the first file found is used, should there exist several.

If the -c option is given to dirplex, it too specifies a configuration file to load. If the name given contains any slashes, it is opened by that exact name. Otherwise, it is searched for in the same manner as the global configuration file.

In addition, all directories traversed by dirplex when mapping a URL into a physical file may contain a file called .htrc, which may specify extra configuration options for all files in and beneath that directory.

.htrc files are checked periodically and reread if changed. The global configuration file and any file named by the -c option, however, are never reexamined.

When using the configuration files for deciding what to do with a found file, they are examined in order of their "distance" from that file. .htrc files found in the directory or directories containing the file are considered "closest" to the file under consideration, followed by any configuration file named by the -c option, followed by the global configuration file.

Each configuration file is a sequence of configuration stanzas, each stanza being an unindented starting line, followed by zero or more indented follow-up lines adding options to the stanza. The starting line of a stanza is referred to as a "configuration directive" below. Each line is a sequence of whitespace-separated words. A word may contain whitespace if such whitespace is escaped, either by enclosing the word in double quotes, or by escaping individual whitespace characters with a preceding backslash. Backslash quoting may also be used to treat double quotes or another backslash literally as part of the word. Empty lines are ignored, and lines whose first character after leading whitespace is a hash character (#) are treated as comments and ignored.

The following configuration directives are recognized:

include [FILENAME…]
Read the named files and act as if their contents stood in place of the include stanza. A FILENAME may be a glob pattern, in which case all matching files are used, sorted by their filenames. If a FILENAME is a relative path, it is treated relative to the directory containing the file from which the include stanza was read, even if the inclusion has been nested. Inclusions may be nested to any level.
index-file [FILENAME…]
The given FILENAMEs are used for finding index files (see URL-TO-FILE MAPPING above). Specifying index-file overrides entirely any previous specification in a more distant configuration file, rather than adding to it. Zero FILENAMEs may be given to turn off index file searching completely. The index-file directive accepts no follow-up lines.
dot-allow [PATTERN…]
As described under 404 RESPONSES, a path element beginning with a dot character is normally rejected by default, but the dot-allow directive allows certain dot-files or -directories to be selectively allowed. Each PATTERN is an ordinary glob pattern, the matching of which allows access to a given path element. When checking for access to dot-files or -directories, only the dot-allow directive "closest" to the file under consideration is used. It should be noted that the default configuration file for dirplex contains a dot-allow directive for the .well-known directory.
child NAME
Declares a named, persistent request handler (see ashd(7) for a more detailed description of persistent handlers). It must contain exactly one follow-up line, exec PROGRAM [ARGS…], specifying the program to execute and the arguments to pass it. If given in a .htrc file, the program will be started in the same directory as the .htrc file itself. The child stanza itself serves as the identity of the forked process — only one child process will be forked per stanza, and if that child process exits, it will be restarted the next time the stanza would be used. If a .htrc file containing child stanzas is reloaded, any currently running children are reused for child stanzas in the new file with matching names (even if the exec line has changed).
fchild NAME
Declares a named, transient request handler (see ashd(7) for a more detailed description of transient handlers). It must contain exactly one follow-up line, exec PROGRAM [ARGS…], specifying the program to execute and the arguments to pass it. In addition to the specified arguments, the HTTP method, raw URL and the rest string will be appended as described in ashd(7). If given in a .htrc file, the program will be started in the same directory as the .htrc file itself.
match [TYPE]
Specifies a filename pattern-matching rule. The pattern-matching procedure and the follow-up lines accepted by this stanza are described below, under MATCHING.
Only meaningful in .htrc files. If a capture directive is specified, then the URL-to-file mapping procedure as described above is aborted as soon as the directory containing the .htrc file is encountered. The request is passed, with any remaining rest string, to the specified HANDLER, which must be a named request handler specified either in the same .htrc file or elsewhere. The capture directive accepts no follow-up lines. Note that the X-Ash-File header is not added to requests passed via capture directives. Normally, capture directives will be ignored if they appear in the root directory that dirplex serves, but not if FLAGS contain the character D.


When a file or directory has been found by the mapping procedure (see URL-TO-FILE MAPPING above), the name of the physical file is examined to determine a request handler to pass the request to. Note that only the physical file name is ever considered; any logical request parameters such as the request URL or the rest string are entirely ignored.

To match a file, any match stanzas specified by any .htrc file or in the global configuration files are searched in order of their "distance" (see CONFIGURATION above) from the actual file. Which match stanzas are considered depends on the type of the file being matched: if an ordinary file is being matched, only match stanzas without any TYPE parameter are considered, while if it is a directory, only those with the TYPE parameter specified as directory are considered. TYPE can also take the value notfound, described below under 404 RESPONSES.

A match stanza must contain at least one follow-up line specifying match rules. All rules must match for the stanza as a whole to match. The following rules are recognized:

filename PATTERN
Matches if the name of the file under consideration matches any of the PATTERNs. A PATTERN is an ordinary glob pattern, such as *.php. See fnmatch(3) for more information.
pathname PATTERN
Matches if the entire path of the file under consideration matches any of the PATTERNs. A PATTERN is an ordinary glob pattern, except that slashes are not matched by wildcards. See fnmatch(3) for more information. If a pathname rule is specified in a .htrc file, the path will be examined as relative to the directory containing the .htrc file, rather than to the root directory being served.
Matches if and only if no match stanza without a default rule matches (in any configuration file).
Valid only in .htrc files, local matches if and only if the file under consideration resides in the same directory as the containing .htrc file.

In addition to the rules, a match stanza must contain exactly one follow-up line specifying the action to take if it matches. The following actions are recognized:

handler HANDLER
HANDLER must be a named handler (see CONFIGURATION above). The named handler is searched for not only in the same configuration file as the match stanza, but in all configuration files that are valid for the file under consideration, in order of distance. As such, a more deeply nested .htrc file may override the specified handler without having to specify any new match stanzas.
Run a transient handler for this file, as if it were specified by a fchild stanza. This action exists mostly for convenience.

A match stanza may also contain any number of the following, optional directives:

If the match stanza is selected as the match for a file, the named HTTP HEADER in the request is set to VALUE before passing the request on to the specified handler.
xset does exactly the same thing as set, except that HEADER is automatically prepended with the X-Ash- prefix. The intention is only to make configuration files look nicer in this very common case.


A HTTP 404 response is sent to the client if

  • The mapping procedure fails to find a matching physical file;
  • A path element is encountered during mapping which, after URL unescaping, either begins with a dot or contains slashes;
  • The mapping procedure finds a file which is neither a directory nor a regular file (nor a symbolic link to any of the same);
  • An empty, non-final path element is encountered during mapping; or
  • The mapping procedure results in a file which is not matched by any match stanza.

By default, dirplex will send a built-in 404 response, but there are two ways to customize the response:

First, match stanzas with the type notfound will be matched against any request that would result in a 404 error. The filename for such matching is that of the last succesfully found component, which may be a directory, for example in case a name component could not be found in the real filesystem; or a file, for example in case a file was found, but not matched by any match stanzas.

Otherwise, any request that would result in a 404 response but is matched by no notfound stanza is instead passed to a default handler named .notfound, which is handled internally in dirplex by default, but may be overridden just as any other handler may be in a .htrc file or by global configuration. Note, however, that any request not matched by a notfound stanza will not have the X-Ash-File header added to it.

The built-in .notfound handler can also be used in match or capture stanzas (for example, to restrict access to certain files or directories).


The sendfile(1) program can be used to serve HTML files as follows.

fchild send
  exec sendfile

  filename *.html *.htm
  xset content-type text/html
  handler send

Assuming the PHP CGI interpreter is installed on the system, PHP scripts can be used with the following configuration, using the callcgi(1) program.

# To use plain CGI, which uses more resources per handled request,
# but less static resources:
fchild php
  exec callcgi -p php-cgi

# To use FastCGI, which keeps PHP running at all times, but uses less
# resources per handled request:
child php
  exec callfcgi multifscgi 5 php-cgi

  filename *.php
  handler php

If there is a directory without an index file, a file listing can be automatically generated by the htls(1) program as follows.

match directory
  fork htls

The following configuration can be placed in a .htrc file in order to dedicate the directory containing that file to some external SCGI script engine. Note that callscgi, and therefore the script engine itself, is started in the same directory, so that arbitrary code modules or data files can be put directly in that directory and be easily found.

child foo
  exec callscgi scgi-wsgi -p . foo

capture foo


Fredrik Tolf <fredrik@dolda2000.com>