From 7381e792a8c0de6b745e9da6b3bdb2c31551c1e7 Mon Sep 17 00:00:00 2001 From: nycki Date: Thu, 30 Oct 2025 13:05:12 -0700 Subject: [PATCH] blog 27: removing slashes and stuff in apache2 --- content/blog/27-apache-slashy.md | 81 ++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 content/blog/27-apache-slashy.md diff --git a/content/blog/27-apache-slashy.md b/content/blog/27-apache-slashy.md new file mode 100644 index 0000000..de61e8e --- /dev/null +++ b/content/blog/27-apache-slashy.md @@ -0,0 +1,81 @@ +--- +date: 2025-10-30 +title: Apache Slash-y +description: remove trailing /index.php from URIs with apache web server. +preview_image: +tags: programming +draft: true +permalink: /blog/27/ +--- + +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 `page2` is a directory then serve from `page2/index.php` +- if `page2.php` exists then serve from `page2.php` +- if none of those things exist then fall back on static file hosting. like, `page2.html` might exist, you can serve that, sure, why not. +- oh you wanted to remove the html extension too? okay do all that again bozo. + +```sh +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](https://httpd.apache.org/docs/current/mod/mod_rewrite.html). + +if there's an easy way to do all this then please please tell me, I miss try_files so much, holy cow. \ No newline at end of file