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