From: Nick Kew Date: Sun, 11 Jul 2010 05:58:13 +0000 (+0000) Subject: Backport FallbackResource directive. X-Git-Tag: 2.2.16~39 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c7fadc6a8b7bbef82f51e6be307ce0325184602d;p=thirdparty%2Fapache%2Fhttpd.git Backport FallbackResource directive. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@962989 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index bcccbd2d5b5..d1a2055e508 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,11 @@ Changes with Apache 2.2.16 *) apxs: Fix -A and -a options to ignore whitespace in httpd.conf [Philip M. Gollucci] + *) mod_dir: add FallbackResource directive, to enable admin to specify + an action to happen when a URL maps to no file, without resorting + to ErrorDocument or mod_rewrite. PR 47184 [Nick Kew] + + Changes with Apache 2.2.15 *) SECURITY: CVE-2009-3555 (cve.mitre.org) diff --git a/STATUS b/STATUS index 2cd3afeb6ae..b85c0b08cfd 100644 --- a/STATUS +++ b/STATUS @@ -122,16 +122,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK: option in the docs page, like e.g. we did for SSLInsecureRenegotiation. wrowe asks; you mean tag? Yes, of course. - * mod_dir: add FallbackResource directive - PR 47184 - Trunk patch: http://svn.apache.org/viewvc?view=rev&revision=785425 - http://svn.apache.org/viewvc?view=rev&revision=795450 - 2.2.x patch: http://people.apache.org/~niq/patches/47184.patch - (identical but for offsets, but patch failed on trunk version) - plus docs patch from r795450 - +1: niq, pgollucci - +1: rbowen - After much debate on IRC, we've agreed on FallbackResource as being the right name for this. - *) core authnz: improve misleading error message. PR 38322. Trunk: N/A 2.2.x: https://issues.apache.org/bugzilla/attachment.cgi?id=25698 diff --git a/docs/manual/mod/mod_dir.xml b/docs/manual/mod/mod_dir.xml index 07d61642d70..7e2152342a3 100644 --- a/docs/manual/mod/mod_dir.xml +++ b/docs/manual/mod/mod_dir.xml @@ -150,5 +150,25 @@ a directory + +FallbackResource +Define a default URL for requests that don't map to a file +FallbackResource local-url +None - httpd will return 404 (Not Found) +server configvirtual host +directory.htaccess +Indexes + +

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). + For example

+ + FallbackResource default.php + +

will cause requests for non-existent files to be handled by + default.php, while requests for files that exist + are unaffected.

+
+
diff --git a/modules/mappers/mod_dir.c b/modules/mappers/mod_dir.c index 9eb10ab6615..59ae536c97e 100644 --- a/modules/mappers/mod_dir.c +++ b/modules/mappers/mod_dir.c @@ -40,6 +40,7 @@ typedef enum { typedef struct dir_config_struct { apr_array_header_t *index_names; slash_cfg do_slash; + const char *dflt; } dir_config_rec; #define DIR_CMD_PERMS OR_INDEXES @@ -65,6 +66,9 @@ static const char *configure_slash(cmd_parms *cmd, void *d_, int arg) static const command_rec dir_cmds[] = { + AP_INIT_TAKE1("FallbackResource", ap_set_string_slot, + (void*)APR_OFFSETOF(dir_config_rec, dflt), + DIR_CMD_PERMS, "Set a default handler"), AP_INIT_ITERATE("DirectoryIndex", add_index, NULL, DIR_CMD_PERMS, "a list of file names"), AP_INIT_FLAG("DirectorySlash", configure_slash, NULL, DIR_CMD_PERMS, @@ -90,9 +94,53 @@ static void *merge_dir_configs(apr_pool_t *p, void *basev, void *addv) new->index_names = add->index_names ? add->index_names : base->index_names; new->do_slash = (add->do_slash == SLASH_UNSET) ? base->do_slash : add->do_slash; + new->dflt = add->dflt ? add->dflt : base->dflt; return new; } +static int fixup_dflt(request_rec *r) +{ + dir_config_rec *d = ap_get_module_config(r->per_dir_config, &dir_module); + const char *name_ptr; + request_rec *rr; + int error_notfound = 0; + if ((r->finfo.filetype != APR_NOFILE) || (r->handler != NULL)) { + return DECLINED; + } + name_ptr = d->dflt; + if (r->args != NULL) { + name_ptr = apr_pstrcat(r->pool, name_ptr, "?", r->args, NULL); + } + rr = ap_sub_req_lookup_uri(name_ptr, r, r->output_filters); + if (rr->status == HTTP_OK + && ( (rr->handler && !strcmp(rr->handler, "proxy-server")) + || rr->finfo.filetype == APR_REG)) { + ap_internal_fast_redirect(rr, r); + return OK; + } + else if (ap_is_HTTP_REDIRECT(rr->status)) { + + apr_pool_join(r->pool, rr->pool); + r->notes = apr_table_overlay(r->pool, r->notes, rr->notes); + r->headers_out = apr_table_overlay(r->pool, r->headers_out, + rr->headers_out); + r->err_headers_out = apr_table_overlay(r->pool, r->err_headers_out, + rr->err_headers_out); + error_notfound = rr->status; + } + else if (rr->status && rr->status != HTTP_NOT_FOUND + && rr->status != HTTP_OK) { + error_notfound = rr->status; + } + + ap_destroy_sub_req(rr); + if (error_notfound) { + return error_notfound; + } + + /* nothing for us to do, pass on through */ + return DECLINED; +} static int fixup_dir(request_rec *r) { dir_config_rec *d; @@ -243,6 +291,7 @@ static int fixup_dir(request_rec *r) static void register_hooks(apr_pool_t *p) { ap_hook_fixups(fixup_dir,NULL,NULL,APR_HOOK_LAST); + ap_hook_fixups(fixup_dflt,NULL,NULL,APR_HOOK_LAST); } module AP_MODULE_DECLARE_DATA dir_module = {