escape sequences in the path element under consideration are unescaped
before examining it.
-Any path element that begins with a dot is considered invalid and
-results in a 404 response to the client. If the path element names a
-directory in the current directory, the procedure continues in that
-directory. If it 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 names a directory in the current directory, the
+procedure continues in that directory. If it 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
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
-------------
by a *fchild* stanza. This action exists mostly for
convenience.
-If no *match* stanza matches, a 404 response is returned to the
-client.
+404 RESPONSES
+-------------
+
+Any of the following cases will result in a 404 response being sent to
+the client.
+
+ * Failure of the mapping procedure to find a matching physical file.
+ * Presence of a path element during mapping that begins with a dot.
+ * A path element which, after URL unescaping, contains slashes.
+ * The mapping procedure finding a file which is neither a directory
+ nor a regular file.
+ * Presence of a non-final but empty path element during mapping.
+ * A physical file having been found which is not being matched by any
+ *match* stanza.
+
+*dirplex* will send a built-in 404 response by default, but any
+`.htrc` file or global configuration may define a request handler
+named `.notfound` to customize the behavior. Note that, unlike
+successful requests, such a handler will not be passed the
+`X-Ash-File` header.
+
+The built-in `.notfound` handler can also be used in *match* or
+*capture* stanzas.
EXAMPLES
--------
#include <utils.h>
#include <log.h>
#include <cf.h>
+#include <resp.h>
#include "dirplex.h"
struct config **cfs;
struct child *ch;
+ if(cf != NULL)
+ *cf = NULL;
cfs = getconfigs(file);
for(i = 0; cfs[i] != NULL; i++) {
if((ch = getchild(cfs[i], name)) != NULL) {
return(ch);
}
}
+ if(!strcmp(name, ".notfound"))
+ return(notfound);
return(NULL);
}
return(findmatch(file, 1, dir));
return(NULL);
}
+
+static int donotfound(struct child *ch, struct hthead *req, int fd, void (*chinit)(void *), void *idata)
+{
+ simpleerror(fd, 404, "Not Found", "The requested URL has no corresponding resource.");
+ return(0);
+}
+
+static struct chandler i_notfound = {
+ .handle = donotfound,
+};
+
+static struct child s_notfound = {
+ .name = ".notfound",
+ .iface = &i_notfound,
+};
+struct child *notfound = &s_notfound;
simpleerror(fd, 500, "Configuration Error", "The server is erroneously configured. Handler %s was requested, but not declared.", pat->childnm);
return;
}
- twd = NULL;
- if((twd = ccf->path) != NULL) {
+ if((twd = ccf?ccf->path:NULL) != NULL) {
if(!strcmp(twd, ".")) {
twd = NULL;
} else if(strncmp(path, twd, strlen(twd)) || (path[strlen(twd)] != '/')) {
}
}
+static void handle404(struct hthead *req, int fd, char *path)
+{
+ struct child *ch;
+ struct config *ccf;
+ char *tmp;
+
+ tmp = sstrdup(path);
+ ch = findchild(tmp, ".notfound", &ccf);
+ if(childhandle(ch, req, fd, chinit, ccf?ccf->path:NULL))
+ simpleerror(fd, 500, "Server Error", "The request handler crashed.");
+ free(tmp);
+}
+
static void handlefile(struct hthead *req, int fd, char *path)
{
struct pattern *pat;
if((pat = findmatch(path, 0, 0)) == NULL) {
- simpleerror(fd, 404, "Not Found", "The requested URL has no corresponding resource.");
+ handle404(req, fd, path);
return;
}
handle(req, fd, path, pat);
int rv;
if(*el == '.') {
- simpleerror(fd, 404, "Not Found", "The requested URL has no corresponding resource.");
+ handle404(req, fd, sprintf3("%s/", path));
return(1);
}
if(!stat(sprintf3("%s/%s", path, el), &sb)) {
free(newpath);
return(1);
}
- simpleerror(fd, 404, "Not Found", "The requested URL has no corresponding resource.");
+ handle404(req, fd, sprintf3("%s/", path));
return(1);
}
if(!strchr(el, '.') && ((newpath = findfile(path, el, NULL)) != NULL)) {
if(*rest == '/')
rest++;
replrest(req, rest);
- if(childhandle(ch, req, fd, chinit, ccf->path))
+ if(childhandle(ch, req, fd, chinit, ccf?ccf->path:NULL))
simpleerror(fd, 500, "Server Error", "The request handler crashed.");
return(1);
}
goto out;
}
if(strchr(el, '/') || (!*el && *rest)) {
- simpleerror(fd, 404, "Not Found", "The requested URL has no corresponding resource.");
+ handle404(req, fd, sprintf3("%s/", path));
rv = 1;
goto out;
}
{
now = time(NULL);
if(!checkpath(req, fd, ".", req->rest))
- simpleerror(fd, 404, "Not Found", "The requested URL has no corresponding resource.");
+ handle404(req, fd, ".");
}
static void chldhandler(int sig)