force https AND www on all pages except 1 - .htaccess

We have software on our site that enables us to send SMS to our members. The software communicates with a third part api and they communicate delivery reports back to the site. This delivery report specifically needs http://www. The url the send the report to is
http://www.example.com/index.php?option=com_acysms&ctrl=deliveryreport&gateway=telerivet&pass=S6fd65thisisafakepasswordstring
Currently, I have all pages redirecting to https://www using this in .htaccess
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# force https:// for all except some selected URLs
RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} !/index.php?option=com_acysms&ctrl=deliveryreport&gateway=telerivet&pass=S6fd65thisisafakepasswordstring/ [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# force http:// for selected URLs
RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} /index.php?option=com_acysms&ctrl=deliveryreport&gateway=telerivet&pass=S6fd65thisisafakepasswordstring/ [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
As you can see, I am trying to exclude the page in question from the force https://www protocol. It's not working. All my searches deal with either https or www, but not both. Any help here is appreciated.
Cheers!

Ok, I'm not going to address the really bad idea that is sending a password in a query string over an insecure connection. That's something you should take up with the third party running that API.
Now for why your RewriteRules might not be working.
According to the Apache variables documentation, %{THE_REQUEST} covers the full request line, not just the request URI or query string:
THE_REQUEST | The complete request line (e.g., "GET /index.html HTTP/1.1")
You probably want to use %{REQUEST_URI} and %{QUERY_STRING} to capture those reports. So your rules would look something like:
# force https:// for all except some selected URLs
RewriteCond %{HTTPS} off
RewriteCond %{QUERY_STRING} !^option=com_acysms&ctrl=deliveryreport&gateway=telerivet&pass=.+$ [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# force http:// for selected URLs
RewriteCond %{HTTPS} on
RewriteCond %{QUERY_STRING} ^option=com_acysms&ctrl=deliveryreport&gateway=telerivet&pass=.+$ [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Or if you want to use ${THE_REQUEST}, they would look like this:
# force https:// for all except some selected URLs
RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} "^POST /index\.php\?option=com_acysms&ctrl=deliveryreport&gateway=telerivet&pass=.+ HTTP/1\.1$" [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# force http:// for selected URLs
RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} "^POST /index\.php\?option=com_acysms&ctrl=deliveryreport&gateway=telerivet&pass=.+ HTTP/1\.1$" [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
The request is in quotes because of the spaces, but you could just escape them with a \ instead. This also assumes the request is made using HTTP 1.1 and the POST method.

Related

How to force http on specific folder in https site

I have site with https
But I need specific folder should be http.
How can we achieve it ?
e.g.
my site is
https://www.mywebsite.com
I want folder1/subfolder1 should be forced to http://
e.g. http://www.mywebsite.com/folder1/subfolder1
I searched on net...but maximum search show how to force http to https
I tried .htaccess as follows :
try 1.
RewriteRule ^(/folder1/subfolder1)($|/) - [L]
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
try 2.
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} !^/folder1/subfolder1
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
But it didn't work..
You can use these rules in your site root .htaccess:
RewriteEngine On
# force https on everything except /folder1/subfolder1
RewriteCond %{THE_REQUEST} !\s/+folder1/subfolder1[/?\s] [NC]
RewriteCond %{HTTPS} !on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301]
# force http on /folder1/subfolder1
RewriteCond %{THE_REQUEST} \s/+folder1/subfolder1[/?\s] [NC]
RewriteCond %{HTTPS} on
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
Make sure to clear your browser cache or use a new browser for testing.

Disable the start slash being removed in url rewrites

Allright so I have a website where I want traffic to go from
http -> https
non www -> www
So the final url should look like: https://www.x.net
I set up some rewrite rules in my htaccess, which look like the following:
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI}$1 [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}$1
It works fine, everything gets redirected but the only problem is the following type of urls.
x.com/help
What happens is it will redirect to
https://www.x.comhelp
It removes the slash between com and help, I couldn't find an answer on Google so that's why I though, maybe my StackOverflow friend could help me out :)
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI}$1 [R=301,L]
You should not use both the %{REQUEST_URI} server variable and the $1 backreference together. Use one or the other, see below...
You would need to change your directives to the following. This uses a backreference to the RewriteRule pattern which notably excludes the slash, so this must be included in the substitution:
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule (.*) https://www.%{HTTP_HOST}/$1 [R=302,L]
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=302,L]
Alternatively, use the %{REQUEST_URI} server variable instead. (This includes the slash prefix.)
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
Change the 302 (temporary) redirect to a 301 (permanent) redirect when you are sure it's working OK. (301 redirects are cached by the browser, so make sure your caches are cleared before testing.)

Best Practice: 301 Redirect HTTP to HTTPS (Standard Domain)

I have been searching for the perfect 301 redirect. But I am finding so many solutions and do not know what’s best.
Here is what I want to do
http://domain.tld/ → https://domain.tld/
http://www.domain.tld/ → https://domain.tld/
https://www.domain.tld/ → https://domain.tld/
Best practice .htacess?
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
</IfModule>
This is my preferred code. At least unil now.
Alternative ways
I also found a lot of other ways to redirect from HTTP to HTTPS. For example:
1.
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
Missing one step? And no [R=301,L] here?
2.
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Is a different order generally better?
Should I use
RewriteRule ^(.*)$
instead of
RewriteRule (.*)
?
3.
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} example\.com$ [NC]
RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L,NE]
Does using the full domain name have any performance advantages? Do I really need NE? ([R=301,L,NE] vs. [L,R=301])
So, my question to all experts: What's the best (performing) way to redirect both from HTTP to HTTPS and from to HTTPS:// ?
To start with your favorite solution:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
</IfModule>
In the part handling non-https URLs you are redirecting to %{HTTP_HOST}. Then, in case your host name started with "www", a second redirect has to take place to send you from https://www.domain.tld to https://domain.tld which is supposed to be your final destination.
You can shorten this by using
RewriteRule ^(.*)$ https://domain.tld/%{REQUEST_URI} [L,R=301]
directly in the first rule. The second rule would then only apply to clients, who try to access https://www.domain.tld.
Alternative 1. does not work for the same reason (missing the case that HTTP_HOST could be www.domain.tld) and additionally because of the missing [L,R=301]. This is necessary because you do not just rewrite an URL here, like you could do in other types of rewrite rules. You are requesting the client to change the type of it's request - this is why you are sending him a HTTP code of 301.
Concerning the match part of the RewriteRule itself, you should be consistent: if you want to capture parts of the URI you will use a regular expression with parentheses. As you are in fact using it as a whole here it is fine to just use one of the alternatives for "anything", like ^ and use %{REQUEST_URI} later. If you use some capturing (i.e. (some_regex) you should reference it in the target by using $1 (or whatever you are going to reference) here.
In your 3rd alternative, again www + https is missing.
You can check if https is off or if the domain name contains a leading "www" in one rule, however rewrite conditions are implicitly connected with "and".
So it should read:
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^ https://domain.tld%{REQUEST_URI} [R=301,L,NE]
The NE is necessary for passing on things like GET-parameters and the like on to the new URI unchanged, see:
http://httpd.apache.org/docs/2.4/rewrite/flags.html
So, condensing, this becomes;
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L,NE]
Let me know if you see any bugs
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Nothing to change just copy and paste.

www. 301 redirect with parameters

I currently use the following redirect to make the urls look nicer:
RewriteRule profile/(.*) index.php?id=$1
(Result: domain.co.uk/profile/00000001)
From index.php?id=00000001
I would like to 301 redirect urls without www to www. and keep the above profile redirect.
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
However, When this is used the URL comes out like:
http://www.DOMAIN.co.uk/ index.php /00000001 ?id=00000001
I’m assuming this can be done, Does this need to be bespoke for my needs or is there something im missing?
End result would ideally rewrite:
domain.co.uk/profile/00000001
to
www.domain.co.uk/profile/00000001
Keep rules in correct order i.e. keep external redirects before your internal rewrites.
So this should work:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [NE,R=301,L]
# external redirect from actual URL to pretty one
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+index\.php\?id=([^\s&]+) [NC]
RewriteRule ^ %1? [R=301,L]
# internal forward from pretty URL to actual one
RewriteRule ^profile/(.+)$ index.php?id=$1 [L,QSA,NC]

Mod-Rewrite/RewriteRule: Enforce https://www as protocol and domain

I extracted the following code from a question here at stackoverflow (Enforce www and trailing slash with mod_rewrite htaccess on a multi-domain site) and directly from apache.org.
The scenario consists of three requirements:
ensure, that the production domain starts always with www.
don't append www. to beta.domain.tld, dev.domain.tld, mobile.domain.tld
finally ensure, that every url gets rewritten to https.
I came up with the following conditions:
# Enforce www, if no subdomain is given
RewriteCond %{HTTP_HOST} !^(beta|dev|mobile|www)\.
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI}/ [R]
# Enfore SSL for all Domains
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
The mentioned rules works as expected, although one single case doesn't work:
https://domain.tld/ is not correctly redirected to https://www.domain.tld/
Can someone help me with this one?
Try replacing your 2 code with this one:
RewriteCond %{HTTP_HOST} !^(?:beta|dev|mobile|www)\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
RewriteCond %{HTTPS} =off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]

Resources