Nowadays, most CMS, frameworks, and web applications direct all requests to a central point where the controller is located, providing greater flexibility for routing users to the correct destination.
If you decide to implement this system on an Apache server manually, you will need to configure redirects in the .htaccess
file. In this article, I’d like to share a configuration pattern that I consider the best, based on my years of web development experience.
Introduction to mod_rewrite
Detailed documentation on this topic can be found on the official Apache website.
Let’s explore the principles of mod_rewrite
. We can create blocks where we first set conditions using the RewriteCond
command and then add the RewriteRule
instruction, which executes when the conditions are met. There can be multiple such blocks. Conventionally, they look like this:
# First block RewriteCond TestString CondPattern [flags] RewriteCond TestString CondPattern [flags] RewriteRule Pattern Substitution [flags] # Second block RewriteCond TestString CondPattern [flags] RewriteCond TestString CondPattern [flags] RewriteRule Pattern Substitution [flags]
RewriteCond
The RewriteCond
directive is used to define conditions under which a rewrite rule will be applied. Each RewriteCond
is evaluated in order, and the following RewriteRule
will only be executed if all conditions in the current block are met. These conditions can check for various server variables, such as the requested URL, the HTTP host, or environment variables, using specific patterns or regular expressions. This flexibility allows for detailed control over URL routing and redirection logic.
RewriteRule
The RewriteRule
directive defines how the URL should be transformed if the preceding conditions (RewriteCond
) are satisfied. It takes the incoming URL pattern and maps it to a new destination, which could be a different URL or an internal file. These rules are key to routing requests and ensuring that users and search engines are directed to the correct resources.
Flags
Flags in RewriteRule
and RewriteCond
allow you to modify how the rewrite or redirection operates. Common flags include [R=301]
for permanent redirects, [L]
to indicate that this is the last rule to process if matched, and [QSA]
to append query strings to the new URL. Flags enhance the power of rewrite rules, enabling fine-grained control over how URLs are processed and ensuring compatibility with various use cases like SEO, HTTPS enforcement, and user-friendly URLs.
Enable the address rewriting service
First, open the .htaccess
file (or create one) in the root directory of your site or application. To enable the address rewriting service, you need to place the code:
<IfModule mod_rewrite.c> RewriteEngine on # Next code here... </IfModule>
Redirect to HTTPS
Beginning in October 2017, the Google Chrome browser began displaying a “Not Secure” warning on web pages with input fields served over HTTP rather than HTTPS.
While it is unlikely that users will follow an HTTP link – especially since ISPs today generally enable default redirection to HTTPS – it remains a possibility. To prevent this situation, which could deter visitors, we can implement a hard redirect for all requests to HTTPS. To achieve this, simply add the following code:
# Redirects to HTTPS RewriteCond %{HTTPS} off RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301]
Redirect from WWW to non-WWW
The abbreviation WWW stands for World Wide Web. This prefix indicates that the connection to the site will most likely use the HTTP protocol. While ‘www’ was originally an indicator that the site existed on the World Wide Web, today it has become a vestige.
Nevertheless, this prefix can be a problem for a site’s SEO, as all of your addresses can technically be duplicated. If search engine crawlers index your site in two versions, this could be a problem in the future. To avoid this in advance, we can do a redirect from WWW to non-WWW.
# Redirects to non-WWW RewriteCond %{HTTP_HOST} ^www\.(.*)$ RewriteRule .* https://%1%{REQUEST_URI} [R=301,L]
Redirect to index file
After checking the HTTPS and WWW requests we can redirect to our index file.
The code for this redirect will look like this:
# Redirects to index.php RewriteCond %{REQUEST_FILENAME} !-f [OR] RewriteCond %{REQUEST_FILENAME} \.php$ RewriteCond %{REQUEST_URI} !^/rest/(.*)$ RewriteRule ^(.*)$ index.php?path=$1 [QSA,L]
Next, let’s look at all the rows in order:
RewriteCond %{REQUEST_FILENAME} !-f [OR] RewriteCond %{REQUEST_FILENAME} \.php$
This part of the code sets the condition that the current request does not access the file, or is addressed to a file that has the extension .php
. This way we can access all files except PHP (this is necessary for security). You can supplement this condition, but the one given in the example is, in my opinion, universal.
RewriteCond %{REQUEST_URI} !^/rest/(.*)$
This part of the code sets a condition that allows us to bypass redirection when accessing files in a given directory. Usually it is necessary to implement REST API. If you are not implementing the REST API in your application, this line can be removed.
RewriteRule ^(.*)$ index.php?path=$1 [QSA,L]
And we come to the redirect rule, which sends us to the index.php
file. We also set a GET parameter that we can retrieve in our application to pass to the controller, allowing us to build the necessary logic to serve the content.
<?php echo $_GET[ 'path' ];
Final Code
<IfModule mod_rewrite.c> RewriteEngine on # Redirects to HTTPS RewriteCond %{HTTPS} off RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301] # Redirects to non-WWW RewriteCond %{HTTP_HOST} ^www\.(.*)$ RewriteRule .* https://%1%{REQUEST_URI} [R=301,L] # Redirects to index.php RewriteCond %{REQUEST_FILENAME} !-f [OR] RewriteCond %{REQUEST_FILENAME} \.php$ RewriteCond %{REQUEST_URI} !^/rest/(.*)$ RewriteRule ^(.*)$ index.php?path=$1 [QSA,L] </IfModule>