When working with Apache 2.2, there are several scenarios where you might want to route all incoming requests to a single entry point (typically index.html). This is particularly common in:
- Single Page Applications (SPAs)
- Maintenance mode setups
- Legacy system migrations
The original approach using Redirect 302
has limitations because:
# This won't work as expected:
Redirect 302 !^/index.html http://www.example.com/index.html
The Redirect
directive doesn't handle complex pattern matching well. What you actually need is mod_rewrite
functionality.
Here's the correct implementation for your .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/index\.html$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /index.html [L]
This solution works because:
RewriteCond %{REQUEST_URI} !^/index\.html$
ensures we don't create infinite loops- The
!-f
and!-d
conditions prevent rewriting real files/directories - The
[L]
flag makes this the last rule to process
For server config files (more efficient than .htaccess):
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html
RewriteEngine On
RewriteRule ^/(?!index\.html$).* /index.html [PT]
</VirtualHost>
For SPAs that need the original path available to JavaScript:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/index\.html$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /index.html [L,QSA]
The QSA
flag keeps query strings intact.
Remember that rewrite rules execute for every request. For high-traffic sites:
- Place rules in main config rather than .htaccess
- Minimize the number of conditions
- Consider using fallback resources in newer Apache versions
If rewrites aren't working:
- Verify
mod_rewrite
is enabled (a2enmod rewrite
) - Check Apache error logs
- Ensure
AllowOverride All
is set for .htaccess files - Test with
RewriteLog
directives for debugging
For Apache 2.4+, consider:
FallbackResource /index.html
This single directive handles all missing file cases more efficiently.
Many developers mistakenly use Redirect when they actually need RewriteRule in Apache. The key differences:
- Redirect: Sends HTTP 302/301 response to client, changing URL in browser address bar
- RewriteRule: Internally maps requests without changing visible URL
For modern SPAs that handle routing client-side, use this in your .htaccess:
RewriteEngine On
RewriteBase /
# Skip actual files and directories
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite everything else to index.html
RewriteRule ^(.*)$ index.html [L]
For API requests or static files that should bypass the rewrite:
RewriteCond %{REQUEST_URI} !^/api/
RewriteCond %{REQUEST_URI} !\.(css|js|png|jpg)$
RewriteRule ^(.*)$ index.html [L]
If you're stuck on Apache 2.2, ensure these modules are loaded:
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule alias_module modules/mod_alias.so
Add this to your vhost config to debug rewrite issues:
LogLevel alert rewrite:trace6
RewriteLog "/var/log/apache2/rewrite.log"
RewriteLogLevel 3
For high-traffic sites, cache the rewritten routes:
<IfModule mod_cache.c>
CacheEnable disk /
CacheHeader on
</IfModule>