gahhhhhh this was driving me crazy, putting it here so i don't lose it
basically this solves the problem where you have pages like
http://example.com/page2/index.php?query=true
and you want it to display in the browser as the much nicer
http://example.com/page2?query=true
and you can't use nginx try_files because you promised yourself you were gonna make this work in apache "for old times' sake"
basically: this takes a surprisingly large number of rewrite rules. in order:
- remove trailing slashes,
page2/->page2 - remove file extensions,
page2.php->page2 - remove index filenames,
page2/index.php->page2 - oh yeah for EACH of those last three things, I hope you remembered to preserve the query string, so
page2/?query=true->page2?query=true - okay now you have a nice short URL in the browser. now just undo all that logic to get the actual php file to run on the server.
- if
page2is a directory then serve frompage2/index.php - if
page2.phpexists then serve frompage2.php - if none of those things exist then fall back on static file hosting. like,
page2.htmlmight exist, you can serve that, sure, why not. - oh you wanted to remove the html extension too? okay do all that again bozo.
RewriteEngine On
#LogLevel alert rewrite:trace6
# remove trailing slash
RewriteRule (\/.*)\/+(\?.*)?$ $1$2 [R]
# remove file extensions
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f
RewriteRule (.*)\.(php|html)(\?.*)?$ $1$3 [NC,R]
# remove index.php index.html etc
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteRule (.*)\/index(\?.*)?$ $1$2 [NC,R]
# serve php file
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
RewriteRule (\?.*)?$ fcgi://php:9000/usr/local/apache2/htdocs/%{REQUEST_URI}.php$1 [P,L]
# serve php file with index
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}/ -d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}/index.php -f
RewriteRule (\?.*)?$ fcgi://php:9000/usr/local/apache2/htdocs/%{REQUEST_URI}/index.php$1 [P,L]
# serve html file
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.html -f
RewriteRule ([^?]*)(\?.*)?$ $1.html$2 [L]
# serve html file with index
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}/ -d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}/index.html -f
RewriteRule ([^?]*)(\?.*)?$ $1/index.html$2 [L]
some useful tricks:
- [NC] can be added after any regex rule to make it Non-Case sensitive.
- [R] means "in-browser redirect" and is used when you want to fix a URI on the user's side. if you don't do this then it only affects where the server pulls data from.
- [P] means "proxy" and it allows you to have the server pull data from another machine or from a program running on a local port.
- [L] means "last one" and it skips all remaining rewrite rules, in case you were worried about matching too many of them.
all this and more can be found at the apache2 docs.
if there's an easy way to do all this then please please tell me, I miss try_files so much, holy cow.