Use FallbackResource for WordPress instead of mod_rewrite
Use FallBackResource as a great alternative to using mod_rewrite to direct Apache to send all requests for non-existing files/directories to a script in WordPress. Htaccess and Server Config enabled.
WordPress Default .htaccess Rewrite Rules
This is the default WordPress .htaccess that says, if request is not already for /index.php
and the requested file is NOT an existing directory or file, than internally rewrite requests to /index.php
which is how WP enables pretty-permalinks and other features such as db-enabled 404 detection.
# BEGIN WordPressRewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] # END WordPress
Use FallBackResource instead
For WordPress, this works faster, especially when placed in server config context and disabling per-directory htaccess configs.
FallbackResource /index.php
Fallback Resource
- Description:
- You want a single resource (say, a certain file, like index.php) to handle all requests that come to a particular directory, except those that should go to an existing resource such as an image, or a css file.
- Solution:
-
As of version 2.2.16, you should use the FallbackResource directive for this:
FallbackResource /index.php
Changes with Apache 2.4.4 - Add support for the value 'disabled' in FallbackResource. [Vincent Deffontaines]
Apache 2.3.3 - 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]
However, in earlier versions of Apache, or if your needs are more complicated than this, you can use a variation of the following rewrite set to accomplish the same thing:
RewriteBase "/" RewriteCond "/home/askapache.com/htdocs/%{REQUEST_FILENAME}" !-f RewriteCond "/home/askapache.com/htdocs/%{REQUEST_FILENAME}" !-d RewriteRule "^" "index.php" [PT]
If, on the other hand, you wish to pass the requested URI as a query string argument to index.php, you can replace that RewriteRule with:
RewriteRule "(.*)" "index.php?$1" [PT,QSA]
FallBackResource in .htaccess
Note that these rulesets can be used in a .htaccess
file, as well as in a <Directory> block.
FallbackResource Directive
Description: | Define a default URL for requests that don't map to a file |
---|---|
Syntax: | FallbackResource disabled | local-url |
Default: | disabled - httpd will return 404 (Not Found) |
Context: | server config, virtual host, directory, .htaccess |
Override: | Indexes |
Status: | Base |
Module: | mod_dir |
Compatibility: | The disabled argument is available in version 2.4.4 and later |
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 /not-404.php
will cause requests for non-existent files to be handled by not-404.php
, while requests for files that exist are unaffected.
It is frequently desirable to have a single file or resource handle all requests to a particular directory, except those requests that correspond to an existing file or script. This is often referred to as a 'front controller.'
In earlier versions of httpd, this effect typically required mod_rewrite, and the use of the -f
and -d
tests for file and directory existence. This now requires only one line of configuration.
FallbackResource /index.php
Existing files, such as images, css files, and so on, will be served normally.
Use the disabled
argument to disable that feature if inheritance from a parent directory is not desired.
In a sub-URI, such as https://www.askapache.com/ this sub-URI has to be supplied as local-url:
FallbackResource /index.php FallbackResource disabled
FallbackResource in mod_dir.c
Like Rich Bowen says, there is a lot of bad info out on the web for Apache, specifically for htaccess. So you need to get in the habit of reading the C source code for any software you care about. Here is the latest mod_dir.c code taken straight from Apache. Obviously much easier to read in vim or SublimeText, emacs, etc., but for the rest of you: ./modules/mappers/mod_dir.c
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"), 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; name_ptr = d->dflt; if ((name_ptr == NULL) || !(strcasecmp(name_ptr,"disabled"))){ return DECLINED; } /* XXX: if FallbackResource points to something that doesn't exist, * this may recurse until it hits the limit for internal redirects * before returning an Internal Server Error. */ /* The logic of this function is basically cloned and simplified * from fixup_dir below. See the comments there. */ 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 dir_fixups(request_rec *r) { if (r->finfo.filetype == APR_DIR) { /* serve up a directory */ return fixup_dir(r); } else if ((r->finfo.filetype == APR_NOFILE) && (r->handler == NULL)) { /* No handler and nothing in the filesystem - use fallback */ return fixup_dflt(r); } return DECLINED; }
Comments