Htaccess Redirects - Combine many rules in one single redirect - apache

I am trying to combine more rules in a single redirect, right now I have many rules and many redirects, like in the picture attached, but for SEO purpose this is not a good behavior.
The story is this: I have an old url, which doesn't exist anymore and a new one, where I want to be redirected. If the requested url doesn't have www. and https then I want to add them.Also if the url has an slash at the end, I want to remove it.
All is working right now, but in many steps.
This is what I have in my .htaccess file:
301 redirect from old url to the new one with www.
RewriteRule ^source1/source2$ https://www.domain.com/destination1/destination2 [L,R=301]
Remove the slash from the end of URL
RewriteCond %{REQUEST_URI} !^/system [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)/$ /$1 [R=301,L,QSA]
Redirect to https
#-----------------redirect to https-----------------
RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} !^www.domain.com(.*)$ [NC]
RewriteRule (.*) https://www.domain.com%{REQUEST_URI} [L,R=301]
I use all of these rules inside this directive:
<IfModule mod_rewrite.c>

Have it like this to avoid multiple 301 for SEO purpose:
# specific redirects
RewriteRule ^source1/source2/?$ https://www.domain.com/destination1/destination2 [L,R=301,NC]
# Remove the slash from the end of URL
RewriteCond %{REQUEST_URI} !^/system [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ https://www.domain.com/$1 [R=301,L,NE]
#-----------------redirect to https-----------------
RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.domain.com%{REQUEST_URI} [L,R=301,NE]
Make sure to clear your browser cache completely before testing this change.

Related

Too many redirects with mod_rewrite (at most one redirect?)

I want there to be at most one redirect using my htaccess file. Is that possible?
my htaccess file:
RewriteEngine On
#remove index/index.html
RewriteRule index\.html|index https://example.com/ [R=301,L]
#redirect to non-wwww and https site
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
RewriteCond %{THE_REQUEST} ^GET\ /(.+)\.html [NC]
RewriteRule ^ /%1? [R=301,L]
#remove .html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\.]+)$ $1.html [NC,L]
If I enter for example http://example.com/foo.html or http://example.com/index then I have two redirects.
If I enter for example http://example.com/ or https://example.com/foo.html then I have only one redirect.
What I want:
I want at most one redirect (see last two examples).
If I navigate to the home page, then I always want the index/index.html to be removed
All http calls should be redirected to https calls
All URL which are called with www, should be called without www
If I navigate to the subpage (https://example.com/foo.html), then only the html should be removed respectively the user can call the page without .html (https://example.com/foo).
Is this possible? Currently sometimes two redirections happen.
Could you please try following, based on your shown samples. Please make sure you clear your browser cache before testing URLs.
RewriteEngine ON
##Apply https and remove www together for all requests here.
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.*)$ [NC]
RewriteRule ^(.*)$ https://%1%{REQUEST_URI} [NE,L]
##Server files with backend .html files.
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)$ $1.html [L]
##Deal with home page .html stuff here.
RewriteCond %{REQUEST_URI} ^/?$
RewriteRule ^(.*)$ index/index.html [L]

.htaccess redirect to https and www. if enabled

I want to configure my .htaccess file in a manner where it will do these two things:
ALWAYS make sure www. is appended (even for subdomains like so: www.sub.example.com).
OPTIONALLY add https:// if it is enabled.
I preferably (if possible) want to do this in one rewrite rule, currently I have this:
RewriteEngine On
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [L,NE,R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
So how do I make the s of https:// optional in the same rewrite?
You can use the following Rule to redirect https , non-https and non-www requests to www with a single redirect.
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTPS}s on(s)|offs()
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [NE,L,R]
This is doing a 302 Temporary redirect. If you want a 301 permanent redirect, change the R flag to R=301 .

How can I direct all pages except one to HTTPS in an htaccess?

Currently I am redirecting all pages to https using the following htaccess directive:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
But I have one page, http://foo.bar/baz which needs to be accessed http-only. Using an htaccess directive, how can I redirect to https on all pages except this one, where users are forced to http?
Edit: I should have mentioned that this is a Laravel 4 application, and I currently also have the following rules to handle the front-controller
# Redirect Trailing Slashes...
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
You can use a negative regex pattern in RewriteRule:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} !/baz[/?\s] [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,NE,L]
RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} /baz[/?\s] [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,NE,L]
RewriteRule ^index\.php - [L,NC]
# Redirect Trailing Slashes...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301,NE]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
A negative lookahead works especifically for these cases when you want one or more exceptions:
RewriteRule ^(?!baz)(.*) https://%{HTTP_HOST}/$1 [R,L]
This basically says, redirect everything except baz.
SideNote: Remember ".htaccess" is not some sort of rewrites depot for Apache, if you have access to the config in the virtualhost, make sure to add these rewrites in there. htaccess adds overhead and complexity.

RewriteRule ssl conf combining various

I need to Rewrite every Dir to https, www and trailing slash and for SEO i need every redirect with only one 301.
The first twoo are solved, but the third doesn't work if de URW comes with www (it returns a 302 if a URL exist, and then write de trailing slash), but i've a rule to handle that case, can you see something wrong?
ssl.conf:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{REQUEST_URI} !^/(.*)\.(.*)
RewriteCond %{REQUEST_URI} !^(.*)/$
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI}/ [L,R=301]
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{REQUEST_URI} ^/(.*)\.(.*)
RewriteCond %{REQUEST_URI} ^(.*)/$
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} ^www\.
RewriteCond %{REQUEST_URI} !^/(.*)\.(.*)
RewriteCond %{REQUEST_URI} !^(.*)/$
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI}/ [L,R=301]
It was my fault, the rules above works fine, the problem was with my hosts file that hadn't the www entry to test.
I leave the Rule for help anyone if needed.

Redirect Loop When Enabling SSL on Matching URI Slug

I'm trying to accomplish 2 tasks with mod_rewrite:
If the URL, regardless of protocol, does not have the "www" subdomain, then add "www" to the URL.
If the URI begins with /secure.php AND the protocol is NOT https, then switch the protocol to https.
So I tried:
# Redirect to www subdomain
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
# Force SSL for secure.php URIs
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/secure.php
RewriteRule ^(.*)$ https://www.mysite.com%{REQUEST_URI} [R=301,L]
But I get a redirect loop when accessing /secure.php URIs. I can't figure out what the problem is, this is how I see the sequence of events:
http://mysite.com/secure.php is requested
The host name does not contain "www", so it passes the first condition
The URL is updated to http://www.mysite.com/secure.php, and the process loops back to the top.
The host name does contain "www", so it fails the first condition and skips the rewrite.
HTTPS is off, so it matches the next condition, AND
The URI begins with "/secure.php", so it matches both required conditions
The URL is updated to https://www.mysite.com/secure.php, and the process loops back to the top.
The host name does contain "www", so it fails the first condition, and skips the rewrite.
HTTPS is not off, so it fails the next condition and skips the rewrite.
Have I got that right? What am I doing wrong here?
I also have one other rule in .htaccess for removing index.php from ExpressionEngine URLs:
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
So here's the entire .htaccess file:
RewriteEngine On
RewriteBase /
# Remove index.php from ExpressionEngine URIs
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
# Redirect to www subdomain
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
# Force SSL for /secure.php URIs
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/secure.php
RewriteRule ^(.*)$ https://www.mysite.com%{REQUEST_URI} [R=301,L]
The server variables like HTTP_HOST or REQUEST_URI are available in a RewriteCond, but not in a RewriteRule. If you need these variables you must capture them in a RewriteCond
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTP_HOST} (.+)
RewriteRule .* http://www.%1/$0 [R,L]
You don't need to check for secure.php in a RewriteCond, you can just specify it in the RewriteRule
RewriteCond %{HTTPS} off
RewriteRule ^/?(secure.php.*) https://www.mysite.com/$1 [R,L]
OT: Never test with 301 enabled, see this answer Tips for debugging .htaccess rewrite rules for details.