.htaccess redirect addin trailing slash - .htaccess

I have been using the following .htaccess for some time now to redirect non-https to https:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
This week however an SEO expert told me this gives 2 redirects for links like this:
www.example.com/test
The first to http s ://www.example.com/test
The second to http s ://www.example.com/test /
Apparantly this is bad for SEO so I have tried adding a / to the last line, this doesn't work for files, e.g.
www.example.com/test.php => https://www.example.com/test.php/
I have done some searching but I can't seem to find a solution for both issues. Can anyone point me in the right direction?

How about adding a check for the directory in the rule (one for directories and one for files):
<IfModule mod_rewrite.c>
RewriteEngine on
# for directories without trailing slashes
RewriteCond %{HTTPS} !=on [NC]
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} [^/]$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}/ [R=301,L]
# for everything else
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
However, there's a good chance this won't work since the redirect from /test to /test/ isn't happening via Rewrite, but via mod_dir's DirectorySlash directive. If you really want to just make this one redirect (I don't think the impact is that serious), then you can turn DirectorySlash off and have that redirect happen via mod_rewrite instead:
DirectorySlash Off
<IfModule mod_rewrite.c>
RewriteEngine on
# for directories without trailing slashes
RewriteCond %{HTTPS} !=on [NC]
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} [^/]$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}/ [R=301,L]
# for everything else
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Add trailing slashes for directories that have them missing
RewriteCond %{HTTPS} on [NC]
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} [^/]$
RewriteRule ^(.*)$ %{REQUEST_URI}/ [R=301,L]
</IfModule>

Related

How do I reduce redirect chain with .htaccess?

I've been having some problem with solving the redirect chain of my website. I wanted my website to ultimately have only one version, which is HTTPS + non-www + trailing slash
When tested, below htaccess gave me 4 response with redirect chain out of 8 total variation tested (https, www/non-www,trailing slash, 2x2x2 = 8 variations).
The http://www. variation gave me a redirect chain with 3 redirects
http://www. --> https://www. --> https://www. + trailing slash ---> https:// + trailing slash
Is there a way that I can make it no redirect chain or at least not more than 2?
Appreciate if someone could help me out! Thanks
# Force trailing slash
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_METHOD} GET
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1/ [L,R=301]
# HTTPS forced by SG-Optimizer
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
</IfModule>
# END HTTPS
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
I use this
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
RewriteCond %{HTTPS_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.mywebsite.com/$1 [L,R=301]
</IfModule>
If I understood you correctly, you want to force HTTPS//non-WWW and remove trailing slashes from files in one redirect. That's a bit demanding and require some sort of GOTO/SKIP logic in the .htaccess file. Try it like this with a fresh browser in incognito mode:
RewriteEngine on
## Check if not a directory and ends in /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
## If not a directory skip next RewriteRule
RewriteRule ^ - [S=2]
## Check if HTTPS and non-WWW
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [OR,NC]
RewriteCond %{https} off
## This RewriteRule skipped if URI was a directory
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
## This RewriteRule used if URI was a directory
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [S=1]
RewriteRule ^(.*)/$ https://example.com/$1 [R=301,L]
PS: I get the idea, but Google's Gary Illyes tweeted in 2016 "30x redirects don't lose PageRank anymore." So, even for SEO this is no longer a burning issue.

Trailing slash not added with .htaccess

I have the following .htaccess setup:
RewriteEngine On
RewriteBase /
DirectoryIndex index.php
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
What I want to achieve:
Redirect from http to https
Redirect from the non-www to www
Add trailing slash
The first two points are ok, the redirects are working as expected, but the third one doesn't.
How can I adapt the existing rules in order to add the trailing slash.
You may use these rules in your .htaccess:
DirectoryIndex index.php
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
RewriteCond %{HTTPS} !on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
# add a trailing slash to non-files
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=301,NE]
Make sure to use a new browser for testing the updated rules.

.htaccess force www and force https for certain path and Concrete5 pretty URLs

edit: This question is now moot as the whole site will be served using HTTPS
My .htaccess is causing a redirect loop.
I need all three sections to work, the purpose of each is in the comment.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Force HTTPS for /book unless dev or already there
RewriteCond %{HTTP_HOST} !^dev\.
RewriteCond %{HTTPS} !^on$
RewriteRule ^book https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Force www prefix unless dev or already there
RewriteCond %{HTTP_HOST} !^dev\.
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ %{REQUEST_PROTOCOL}://www.%{HTTP_HOST}/$1 [L,R=301]
# Concrete5 pretty URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}/index.html !-f
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule . index.php [L]
</IfModule>
I'm having to work on the live server because the certificate is only valid there (with www. required).
I've tried many variations of the above, but am stumped, so am hoping fresh eyes on this will help, many thanks in advance.
Your 2nd rule isn't looking right as REQUEST_PROTOCOL has value of HTTP/1.1.
You can use this code:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Force HTTPS for /book unless dev or already there
RewriteCond %{HTTP_HOST} !^dev\.
RewriteCond %{HTTPS} !^on$
RewriteRule ^book https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
# Force www prefix unless dev or already there
RewriteCond %{HTTPS}s on(s)|
RewriteCond %{HTTP_HOST} !^(?:www|dev)\. [NC]
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [NE,L,R=301]
# Concrete5 pretty URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}/index.html !-f
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule . index.php [L]
</IfModule>

.htaccess & mod_rewrite redirect issues

Alright. I'm having no luck. So I figured I'd see if you all could help make some sense of this issue.
I've inherited a site that previously had a lot of different subdomains, which have now all been written into the .htaccess file to rewrite as subdirectories (i.e., blog.site.com becomes site.com/blog).
To avoid duplicate content issues, I also need to rewrite all site.com URL's as www.site.com. And even though the current rules look good to me, they're apparently not rewriting all the subdirectories of the domain. (I've never been that great with RegEx, so that could be part of the problem.)
Here are the current rules from .htaccess:
#---------------------------------
# Start rewrite engine
#---------------------------------
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
</IfModule>
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=on
RewriteCond %{PATH_INFO} !^$
RewriteCond %{HTTP_HOST} !^localhost$ [NC]
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteCond %{HTTP_HOST} !^blog\..+$ [NC]
RewriteCond %{HTTP_HOST} !^docs\..+$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
#---------------------------------
# Rewrite some of our subdomains
#---------------------------------
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^blog\.site\.com$ [NC]
RewriteRule (.*)$ "http://www.site.com/blog/$1" [R=301,QSA,L]
RewriteCond %{HTTP_HOST} ^docs\.site\.com$ [NC]
RewriteRule (.*)$ http://www.site.com/docs/$1 [R=301,QSA,L]
RewriteCond %{HTTP_HOST} ^wiki\.site\.com$ [NC]
RewriteRule (.*)$ http://www.site.com/wiki/$1 [R=301,L]
</IfModule>
#---------------------------------
# Wordpress specific - do not place anything below this line
#---------------------------------
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
(Obviously, some of them exist to allow for a local dev environment, etc).
Any thoughts on why I'm not seeing site.com/directory rewritten as www.site.com/directory? What am I missing here?

.htaccess - how make rules apply to both specific pages and directories

I got help from this site to get functioning code for .htaccess:
# force https for /login.php and /register.php
RewriteCond %{HTTPS} off
RewriteRule ^(login|register)\.php$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# don't do anything for images/css/js (leave protocol as is)
RewriteRule \.(gif|jpe?g|png|css|js)$ - [NC,L]
# force http for all other URLs
RewriteCond %{HTTPS} on
RewriteCond %{SCRIPT_FILENAME} !(login|register)\.php$
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
But now I realize I also need to add a couple of directories to these rules. How can this be done?
Why doesn't the following work:
# force https
RewriteCond %{HTTPS} off
RewriteCond %{SCRIPT_FILENAME} ^(securimage|ADM)/(.*)$
RewriteCond %{SCRIPT_FILENAME} ^(login|register)\.php$
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# don't do anything for images/css/js (leave protocol as is)
RewriteRule \.(gif|jpe?g|png|css|js)$ - [NC,L]
# force http for all other URLs
RewriteCond %{HTTPS} on
RewriteCond %{SCRIPT_FILENAME} !(securimage|ADM)/(.*)$
RewriteCond %{SCRIPT_FILENAME} !(login|register)\.php$
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
I've tried a few different variances, nothing's working. :(
I solved it by putting separate .htaccess files in the directories I wanted to secure, containing:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

Resources