2009/9/15 Rich Bowen <[email protected]>:
> FallbackHandler and FrontController both make a lot of sense to me.
> FrontController seems like it might be more "correct", in terms of accepted
> usage in the larger world out there, but either one makes me happy.

Looks like a name was found (or not).  :-)

Besides the name I'd like to propose two features to that directive

- the possibility to override a previous setting back to default (e.g.
for subdirectories, Fallback disabled). I don't know if this is useful
but it was implemented into DirectoryIndex as well

- the possibility to disable the setting for subrequest lookups to
address RĂ¼diger's comment
http://www.mail-archive.com/[email protected]/msg44257.html
(Fallback fooressource nosub)

(- some debug logging+docs)

Bob
Index: modules/mappers/mod_dir.c
===================================================================
--- modules/mappers/mod_dir.c	(revision 815380)
+++ modules/mappers/mod_dir.c	(working copy)
@@ -41,6 +41,7 @@
     apr_array_header_t *index_names;
     slash_cfg do_slash;
     const char *dflt;
+    const char *nosub;
 } dir_config_rec;
 
 #define DIR_CMD_PERMS OR_INDEXES
@@ -73,6 +74,28 @@
     return NULL;
 }
 
+static const char *config_fallback(cmd_parms *cmd, void *dummy, const char *uri,
+                                    char *nosub)
+{
+    dir_config_rec *d = dummy;
+    const char *t, *w;
+
+    t = uri;
+    if (!strcasecmp(t, "disabled")) {
+        d->dflt = "\0";
+    }
+    else {
+        d->dflt = t;
+    }
+
+    w = nosub;
+    if (w != NULL) {
+        d->nosub = "true";
+    }
+
+    return NULL;
+}
+
 static const char *configure_slash(cmd_parms *cmd, void *d_, int arg)
 {
     dir_config_rec *d = d_;
@@ -83,9 +106,8 @@
 
 static const command_rec dir_cmds[] =
 {
-    AP_INIT_TAKE1("Fallback", ap_set_string_slot,
-                  (void*)APR_OFFSETOF(dir_config_rec, dflt),
-                  DIR_CMD_PERMS, "Set a default handler"),
+    AP_INIT_TAKE12("Fallback", config_fallback, NULL, DIR_CMD_PERMS,
+                 "Set a fallback ressource"),
     AP_INIT_RAW_ARGS("DirectoryIndex", add_index, NULL, DIR_CMD_PERMS,
                     "a list of file names"),
     AP_INIT_FLAG("DirectorySlash", configure_slash, NULL, DIR_CMD_PERMS,
@@ -99,6 +121,8 @@
 
     new->index_names = NULL;
     new->do_slash = SLASH_UNSET;
+    new->dflt = NULL;
+    new->nosub = NULL;
     return (void *) new;
 }
 
@@ -112,6 +136,8 @@
     new->do_slash =
         (add->do_slash == SLASH_UNSET) ? base->do_slash : add->do_slash;
     new->dflt = add->dflt ? add->dflt : base->dflt;
+    /* override nosub if Fallback was present */
+    new->nosub = add->dflt ? add->nosub : base->nosub;
     return new;
 }
 
@@ -125,12 +151,13 @@
         return DECLINED;
     }
     name_ptr = d->dflt;
-    if (name_ptr == NULL) {
+    if (name_ptr == NULL || name_ptr[0] == '\0'
+        || (r->main != NULL && d->nosub != NULL)) {
         return DECLINED;
     }
     /* XXX: if Fallback points to something that doesn't exist,
      * this may recurse until it hits the limit for internal redirects
-     * before returning an Internal Server Error.
+     * before returning an Internal Server Error if nosub was not set.
      */
 
     /* The logic of this function is basically cloned and simplified
@@ -143,6 +170,9 @@
     if (rr->status == HTTP_OK
         && (   (rr->handler && !strcmp(rr->handler, "proxy-server"))
             || rr->finfo.filetype == APR_REG)) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                      "Fallback: Fallback to filename %s (%s) for %s",
+                      rr->filename, rr->uri, r->filename);
         ap_internal_fast_redirect(rr, r);
         return OK;
     }
@@ -154,11 +184,17 @@
                                            rr->headers_out);
         r->err_headers_out = apr_table_overlay(r->pool, r->err_headers_out,
                                                rr->err_headers_out);
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                      "Fallback: Fallback of URI-path %s resolved to "
+                      "an external redirect to URI %s.", r->uri, rr->filename);
         error_notfound = rr->status;
     }
     else if (rr->status && rr->status != HTTP_NOT_FOUND
              && rr->status != HTTP_OK) {
         error_notfound = rr->status;
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                      "Fallback: Ressource %s returned %s for "
+                      "fallback of URI-path %s.", rr->filename, rr->status, r->uri);
     }
 
     ap_destroy_sub_req(rr);

Index: docs/manual/mod/mod_dir.xml
===================================================================
--- docs/manual/mod/mod_dir.xml	(revision 815380)
+++ docs/manual/mod/mod_dir.xml	(working copy)
@@ -166,8 +166,8 @@
 <directivesynopsis>
 <name>Fallback</name>
 <description>Define a default URL for requests that don't map to a file</description>
-<syntax>Fallback <var>local-url</var></syntax>
-<default>None - httpd will return 404 (Not Found)</default>
+<syntax>Fallback <var>local-url [nosub]</var></syntax>
+<default>disabled - httpd will return 404 (Not Found)</default>
 <contextlist><context>server config</context><context>virtual host</context>
 
 <context>directory</context><context>.htaccess</context></contextlist>
@@ -175,13 +175,40 @@
 <usage>
     <p>Use this to set a handler for any URL that doesn't map to anything
     in your filesystem, and would otherwise return HTTP 404 (Not Found).
+
+    The <var>local-url</var> can be either a filename which will be treated relative
+    to the directory of the current request or an <var>URL-path</var>.
     For example</p>
     <example>
         <code>Fallback not-404.php</code>
     </example>
     <p>will cause requests for non-existent files to be handled by
-    <code>not-404.php</code>, while requests for files that exist
-    are unaffected.</p>
+    <code>not-404.php</code>, while requests for files that exist or resources
+    with other handlers assigned are unaffected. If the directive was inserted
+    under <code>/var/www</code> and the request resolved to
+    <code>/var/www/foo/nonexistent</code> while the folder <code>foo</code>
+    exists, httpd will try to fall back to <code>/foo/not-404.php</code>.
+    In order to avoid such a relative fall back, an <var>URL-path</var> can be used:</p>
+    <example>
+        <code>Fallback /not-404.php</code>
+    </example>
+    <p>will cause requests for non-existent files to be handled by
+    <code>/not-404.php</code>, regardless of the current directory of the request.</p>
+
+   <p>A previous setting can be disabled by associating the value <var>disabled</var>:</p>
+    <example>
+        <code>Fallback disabled</code>
+    </example>
+   <p>This will override a previously given local-url and httpd will return to
+   its default 404 error handling.</p>
+
+   <p>To avoid interaction with subrequests (e.g. lookups for index files defined by
+   <directive>DirectoryIndex</directive> or includes by <module>mod_include</module>)
+   an optional argument <var>nosub</var> can be used to disable the fall back
+   for subrequests:</p>
+    <example>
+        <code>Fallback /not-404.php nosub</code>
+    </example>
 
 </usage>
 </directivesynopsis>

Reply via email to