Pre-requisite
Your apache server must have AllowOverride
set to True
for the folder you will put your .htaccess
. Usually, this is set on the default configuration of apache, or sometimes by specific VirtualHost
.
TL;DR
Here is the code for the lazy guys, copying this is quite ok but make sure you understand it before deploying to production!
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
How to configure the URL rewriting?
Enabling mod_rewrite
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.+)$ index.php
</IfModule>
Now, you've enabled the rewriting for every URL!
But, if you tried this only, you will discover that you can't access your images/css/js files… Quite annoying for serving web pages.
Let's see how to specify to not redirect when the files are available.
Restrict the rewriting only for non-existing files and directory
The URL rewriting module provides the RewriteCond
instruction to specify conditions on the next RewriteRule
.
Here, we want to disable the rewriting for the folders -d
and the files -f
that exists in our directory.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
Now, that's cool! We get our content and we can see our web pages with style and images.
Unfortunatly, you will realise that the visitors can see the content of the subfolders you have. It's a problem if you have content you don't want to make available for everyone.
Let's see how to disable the default listing of folders.
Disabling the listing of your folders
This time, we are going to use another apache module mod_negotiation
(see Content negotiation) to set the options on our folder view.
The Options
allow us to set the way we want our folders to be listed. In our case we want to disable the MultiViews
and the Indexes
.
According to the apache documentation for MultiViews
:
About the Indexes option:
In order to disable theses options (or make sure they are disabled), we have to specify them in the Options
directive prefixed by the -
. On the contrary, if we wanted to add theses options we will put a +
.
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
Troubleshooting
My index consider my route /api different from /api/
In order to solve this problem, we will redirect all the route with a trailing slash if they are not a folder. In our case, /api/
will be redirected to /api
.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
NOTE: This should be done before the rewriting on the index!
My Authorization header is not passed to my script
If you're using the Authorization
header, you may notice that this one is not passed to your PHP script.
Usually, this is due to some apache module that strip this header, for example the basic_auth
module.
In order to solve this issue, we are going to copy our Authorization
header to the environment variable (E=
) HTTP_AUTHORIZATION
.
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
That's it!