My Stack:
- LAMP
- Apache/2.4.41
Background Information:
I recently launched a new website for a client. During the re-design process we decided to:
- Switch to sitewide HTTPS
- Remove the .php extension from the URLs
- Switch to a CMS
Example of OLD URL:
http://www.example.com/courses/acme-course.php
Example of NEW URL:
https://www.example.com/courses/acme-course
My Issue:
An unnecessary additional 301 Redirect is occurring when a user navigates to one of the OLD URLs.
I do not understand why the additional 301 redirect is being created and not sending the user directly to the correct destination URL using a single 301 redirect.
Interesting Observation:
The unnecessary additional 301 Redirect does not occur when I use the OLD URL with HTTPS instead of HTTP.
Example:
https://www.example.com/courses/acme-course.php _
Using the above URL will correctly do a single 301 Redirect to the correct destination URL of: https://www.example.com/courses/acme-course
Here's an Example of a 301 Redirect Chain:
Original Request URL:
http://www.example.com/courses/acme-course.php
1ST 301 Redirect (Unnecessary):
FROM:
http://www.example.com/courses/acme-course.php
TO:
https://www.example.com/index.php?url=courses/acme-course.php
2ND 301 Redirect (Correct Final Destination URL):
FROM:
https://www.example.com/index.php?url=courses/acme-course.php
TO:
https://www.example.com/courses/acme-course
My .htaccess code:
# (1) General Settings <IfModule mod_rewrite.c> Options +FollowSymLinks RewriteEngine On </IfModule> # (2) Force WWW <IfModule mod_rewrite.c> RewriteCond %{HTTPS} !=off RewriteCond %{HTTP_HOST} !^www\. [NC] RewriteCond %{SERVER_ADDR} !=127.0.0.1 RewriteCond %{SERVER_ADDR} !=::1 RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] </IfModule> # (3) Force HTTPS <IfModule mod_rewrite.c> RewriteCond %{HTTPS} !=on RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L] </IfModule> # (4) URL Routing for CMS <IfModule mod_rewrite.c> RewriteCond %{HTTPS} =on RewriteRule ^ - [env=proto:https] RewriteCond %{HTTPS} !=on RewriteRule ^ - [env=proto:http] ## Check if file/directory exists RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d ## Route all other URLs to index.php/URL RewriteRule ^(.*)$ index.php?url=$1 [PT,L,QSA] </IfModule>