Exempt several site folders from forced https:// - .htaccess

A year ago I managed to figure out what to add to .htaccess to force https:// on my site. I thought it was working. (Green code)
Last week, however, I noticed that some pages were still coming up as http://
I had someone "fix" it. They added the blue code. And, yes, all pages are now coming up as https://. BUT, the four URLs in the original code that we don't want to be forced to https are now being forced to https://
Is there a simple way to modify the blue code so that the four folders are not forced to https// ??[
I tried moving the four RewriteCond {REQUEST_URI} lines from the green to blue section, but that didn't help.
And, I can safely remove the original code now, right?

RewriteCond rules are processed as a conjunction (a set of and expressions) up to the RewriteRule directive.
The RewriteCond directive defines a rule condition. One or more RewriteCond can precede a RewriteRule directive. The following rule is then only used if both the current state of the URI matches its pattern, and if these conditions are met.
Therefore, they need to be placed before the RewriteRule:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteCond ...
RewriteCond ...
RewriteCond ...
RewriteCond ...
RewriteRule ^(.*)$ https://example.com%{REQUEST_URI} [E=UPGRADE,L,R=301]

Related

redirect a download link from multiple subdomains to another using htaccess

I want to redirect all download links of different subdomains to another main subdomain, for example:
https://sub1.example.com/folder/file.pdf
https://sub2.example.com/folder/file.pdf
these links should be redirected to:
https://mainsub.example.com/folder/file.pdf
the links should stay the same, only the part of the subdomain should be changed.
is there an easy way to do that by writing an htaccess for each subdomain?
thank you.
Something like this should do the trick: the idea is to change the subdomain only and leave the rest of the query intact. You don't need one .htaccess per subdomain - this one can cover all of them.
In this example, a subdomain is required - calling https://example.com/folder/file.pdf will have no effect.
There is also an exception for www.example.com - note the exclamation mark (exclusion)
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} !^www\.example\.com$
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule ^(.*)$ https://mainsub.example.com/$1 [R=301,L]
If you want to restrict the rule to file downloads only, then you can complete the expression but you need to determine the possible patterns for /folder/file.pdf

Dynamic htaccess for www or non-www and http or https

I hope that I'll explain myself in my needs. I'm trying to write a dynamic htaccess but I don't achive to understand the conditions and the rewriting rules.
Here is my thing, I built a small CMS where the user will write their base url like "stackoverflow.com" and he'll choose with some radio input between http or https and also between www or not. Also for SEO porposes, one thing that it's important is to force the slash except in url with extensions.
So, the options for ssl and www are stored in DB, so I wanted to know what do you think, if it's better to write some code like:
if($ssl){
$htaccess.= "RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1/ [R=301]\n";
}else{
$htaccess.= "RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1/ [R=301]\n";
}
As you can see that works if I want to add the www, so I was trying to add more php conditions but i'm sure there must be a way to do it in just a few htacess lines, I already see that we can use conditions like this:
RewriteCond %{HTTP_HOST} ^www.stackoverflow.com$ [NC]
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTPS}:s on:(s)
RewriteRule ^ http%1://www.stackoverflow.com:2368%{REQUEST_URI} [P,QSA,L]
But again all this codes I found have a fixed www or non-www and I don't know if they keep the slash. So, I want to know if I can add more conditions to the code above to have the www as variable to, and to ask if there's some extention to erase the slash. Something like:
RewriteCond %{HTTP_HOST} ^www.stackoverflow.com$ [NC]
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTPS}:s on:(s)
RewriteCond %{HTTP_HOST} !^www. [OR]
RewriteCond %{HTTPS}:s on:(s)
RewriteRule ^ http%1://%2stackoverflow.com%{REQUEST_URI} [P,QSA,L]
I wrote this but I don't know if I can keep the variable (s) with the same name, or if %2 take the value, or if there's a limit of htaccess conditios. Because I was trying to found some htaccess docs for this but I don't get it, and everything I try make show some wrong configuration screen so I hope that you can at least give some advices about how to use this variables or if you think If there's and easy way to do it.
Thanks in advance.

Set up of conditional redirect in htaccess

I've been asked to make an existing web site multi-language.
In preparation for this I have had to move all existing pages from /path/page to /en/path/page
To maintain any existing incoming links I now need to set up an htaccess redirect to send any requests from their original urls to the new /en/path/page urls but I'm having trouble getting this to work.
This is what I currently have;
RewriteCond %{REQUEST_URI} !^/en$
RewriteRule ^(.*)$ /en/$1 [R=301,L]
Which I think is meant to check the requested URI and if it doesn't begin with /en then prepend /en onto the requested URI... but I'm obviously mistaken since it doesn't work.
Any help appreciated. Thank you.
UPDATE.
Since this is an ExpressionEngine site and there is an additional rule to remove the index.php portion of the URL here are both rules
# Rewrite for new language based urls
# This is to try and get all current pages going to /en/(old url) with a 301 redirect
RewriteCond %{REQUEST_URI} !^/en(/.*)?$
RewriteRule ^(.*)$ /en/$1 [R=301,L]
# Removes index.php
RewriteCond $1 !\.(gif|jpe?g|png|ico)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
I have also tried this with the language rewrite after the index.php one. I'm still getting stuck in loops.
What it does is, checking whether the URI is not exactly /en, since the $ indicates the end of the string right after en.
Try this, it checks whether the URI is not exactly /en or /en/ or doesn't start with /en/, and if that's the case it will prepend /en/:
RewriteCond %{REQUEST_URI} !^/en(/.*)?$
RewriteRule ^(.*)$ /en/$1 [R=301,L]
update Considering the other rules you have in your .htaccess file, it is necessary to have the language rule not match again for the following internal redirect to /index.php..., otherwise you'll end up with an endless loop.
There may be better ways to prevent this, however the first thing that comes to my mind would be checking for index.php in the first condition:
RewriteCond %{REQUEST_URI} !^/(index\.php|en)(/.*)?$
So this will cause the rule not to apply after the internal redirect. But be careful, this solves the problem for this specific case only in which the internal redirect goes to index.php!

How to combine RewriteCond in htaccess

I am looking for If, else type of code which can combine my re-write rules based on host/domain name. So if domain name is "domainA" then redirect a to b, c to d and if domain name is "domainB" then redirect x to y and z to p. Basically I don't want to write the Condition again and again as I have done below:
I have written following code for htaccess
RewriteCond %{HTTP_HOST} ^domain\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.domain\.com$
RewriteRule ^home /? [L,R=301]
RewriteCond %{HTTP_HOST} ^domain\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.domain\.com$
RewriteRule ^home-old /? [L,R=301]
In above I am using host because I have multiple domains pointed to same hosting space so htaccess is common between all.
Can I combine the above multiple condition for a domain into one, instead of writing domai name again and again for some set of redirects for specific domain?
Please advise, thanks!
There really is no such if-then-else structure in mod_rewrite. You have to either be clever with your rules (which sometimes makes them unreadable or impossible to amend) or just be explicit about everything.
For your specific example, you can just use regular expressions to combine them:
^domain\.com$ and ^www\.domain\.com$ gets turned into ^(www\.)?domain\.com$
and
^home and ^home-old is just ^home, since the first only matches if the URI starts with home, and home-old does indeed start with home (there is no $ symbol to indicate the end of the string). So you're looking at:
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.com$ [NC]
RewriteRule ^home /? [L,R=301]
If you need to be specific by using the $, you can just change the regex to:
RewriteRule ^home(-old)?$ /? [L,R=301]
EDIT:
If I have some other urls instead of home, and botique, and hairtips then I need to write RewriteCond every time? I guess I have to write that every time just confirming from you
Yes, you have to repeat the condition every time, or, you can make a passthrough at the very beginning of your rules:
RewriteCond %{HTTP_HOST} !^(www\.)?domain\.com$ [NC]
RewriteRule ^ - [L]
This means: anything that's not a request for host: www.domain.com or domain.com, then pass through without rewriting. Then you can just have rules after this because only requests with hosts other than the above will reach those rules.
This is the "clever" bit that I was referring to before. This can make it tricky to change your rules or amend them later because you've set a strict condition at the top.

htaccess and forward one url to another

I have this rewrite code:
RewriteCond %{HTTP_USER_AGENT} ^.*iPhone.*$
RewriteRule ^(.*)$ http://stagingsite.com/site/mobile [R=301]
RewriteRule ^faq/$ /mobile/faq
The first line is working correctly. If the user is on an iphone then redirect to the mobile directory where the index page is displayed.
I also want users visiting:
http://stagingsite.com/site/faq
to get forwarded to http://stagingsite.com/site/mobile/faq if they're on an iphone but the last line of code above doesn't seem to be achieving this.
Any ideas what I have wrong?
RewriteCond directives only get applied to the *immediately following RewriteRule. So you have the condition that checks for iPhone, but that only gets applied to the redirect rule, and not the faq rule. You have to duplicate it:
RewriteCond %{HTTP_USER_AGENT} ^.*iPhone.*$
RewriteRule ^(.*)$ http://stagingsite.com/site/mobile [R=301,L]
RewriteCond %{HTTP_USER_AGENT} ^.*iPhone.*$
RewriteRule ^faq/?$ /site/mobile/faq [L]
You should also include L flags so the 2 rules don't accidentally interfere with each other. And your regex and target needs to be updated to accept an optional trailing slash and the subdirectory.
taking out the slash before mobile as
RewriteRule ^faq/$ mobile/faq
works?

Resources