Modify existing .htaccess so that it ignores subdomains - apache

I have the following .htaccess file in place, and whilst I know it is nowhere near optimal (and probably a bit cringeworthy) - it just works.
# Prevents public viewing of .htaccess file
<Files .htaccess>
order allow,deny
deny from all
</Files>
# Custom 404 page
ErrorDocument 404 https://www.domain.com/404/
# Turn on rewriting and set rewriting base
RewriteEngine On
RewriteBase /
# Force WWW
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} ^([^.]+)\.([a-z]{2,4})$ [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
# Force WWW and HTTPS
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
RewriteCond %{HTTPS} off
RewriteRule ^ https://www.domain.com%{REQUEST_URI} [R=301,L]
# Remove .php extension
RewriteRule ^(properties)/(all|location1|location2|location3)/(all|1|2|3|4|5|6|7|8|9)/(asc|desc) $1.php?location=$2&bedrooms=$3&sort-by=$4
RewriteRule ^(properties)/(all|location1|location2|location3)/(all|1|2|3|4|5|6|7|8|9) $1.php?location=$2&bedrooms=$3
RewriteRule ^(properties)/(all|location1|location2|location3) $1.php?location=$2
RewriteRule ^(view-property)/(.*)/(print-view) $1.php?id=$2&print=true
RewriteRule ^(view-property)/(.*)/ $1.php?id=$2
RewriteRule ^(.*)/$ $1.php
Our new website is now ready to be pushed to our newly created staging environment for testing. In this instance it would be staging.domain.com but we're having problems actually accessing this staging URL.
EDIT - Just to clarify, the problem is that accessing staging.domain.com redirects to https://www.domain.com.
We believe the problem is caused by the rewrite rules we have in place above. I have researched a few possible solutions include adding additional conditions to the existing rewrite rules such as:
RewriteCond %{HTTP_HOST} !^staging\.domain\.com
or adding a new condition/rule such as:
RewriteCond %{HTTP_HOST} ^staging\.domain\.com [NC]
RewriteRule ^(.*) - [L]
but unfortunately none of these have worked. Working with .htaccess files is really not my strong suit, so if anyone could offer any assistance that would be great.
P.S. The new site is powered by Laravel 5.3 so I will be getting rid of the terrible attempt at rewriting rules (those at the bottom) when we go live!

Your top rules must be changed to this to remove hardcoded domain name in target URL:
# Turn on rewriting and set rewriting base
RewriteEngine On
RewriteBase /
# Force WWW and HTTPS
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE]
# Remove .php extension and rest of the rewrite rules

Related

Re-writing url - apache - htaccess

I am migrating an existing website to a Codeigniter one so need a help with re-writing of the urls.
I need to map old URLs with new URLs so that people visiting site from search engine results get redirected to matching new URLs as otherwise they would get page not found errors.
Most of the old urls in this format e.g.
/page.php?id=5 or /page.php?id=180&t=78
/data.php?token=GH45LK
/faqs.php?k=98#section2
Their matching new URLs are
/page/5 or I will be happy with /page?id=5&whatever=xyz too
/data/GH45LK
/faqs/98#section2
This is my current .htaccess of CodeIgniter
# Turning on the rewrite engine is necessary for the following rules and features.
# FollowSymLinks must be enabled for this to work.
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
# If you installed CodeIgniter in a subfolder, you will need to
# change the following line to match the subfolder you need.
# http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritebase
RewriteBase /
# Redirect Trailing Slashes...
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Rewrite "www.example.com -> example.com"
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
# Checks to see if the user is attempting to access a valid file,
# such as an image or css document, if this isn't true it sends the
# request to the front controller, index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
# Ensure Authorization header is passed along
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>
I tried something like this after RewriteBase / line
RewriteRule ^data\.php\?token=(.*)?$ data/=$1 [R=301,L]
but not sure if I got that right as it's not working.
Could you help me getting it right? Thx
RewriteRule does not work that way: it only test the path part of an URL. For all the other parts (domain, query string, ...), you need to use RewriteCond and the corresponding variable (%{QUERY_STRING}, for the query string/here).
RewriteCond %{QUERY_STRING} (?:^|&)id=(\d+)
RewriteRule ^page\.php$ /page/%1 [L,R=permanent]
RewriteCond %{QUERY_STRING} (?:^|&)token=([^&]+)
RewriteRule ^data\.php$ /data/%1? [L,R=permanent]
RewriteCond %{QUERY_STRING} (?:^|&)k=(\d+)
RewriteRule ^faqs\.php$ /faqs/%1? [L,R=permanent]
And I think there is an error with RewriteCond %{HTTPS} !=on as you redirect on http://, not https://, this should result in an infinite loop.
Also note that the anchor (#section2 in your example), is not sent to the server (so it can't be rewritten).

Force HTTPS and WWW in .htaccess

I start reading about a similar topic at this page .htaccess - how to force "www." in a generic way? and the solution was not, well almost what I am looking to do.
The problem : I need the user to be on HTTPS and on WWW to make my application working properly. But if some one click on a html link like:
www.example.com
The user will fall on my website with this :
https://www.www.example.com/
Here is my current .htaccess file.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://www.%{SERVER_NAME}/$1 [R=301,L]
</IfModule>
Is there any way to detect that the user already entered the WWW or is there a best practice to get the result I am looking for?
Thank you.
You are getting this behavior because http -> https rule is adding www\. in target URL without checking if URL is already starting with www.
You should replace both of your rules with this single rule and as a bonus avoid multiple redirects:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE]

generic non-www to www, and non-http to https

I have the following code for my .htaccess file that I've picked up from here and tried adapting it as I understand from .htaccess, yet I can't seem to get it to work (or maybe the browser has cached it but I can't seem to clear it).
Options -Indexes
Options +FollowSymlinks
<IfModule mod_rewrite.c>
########## FORCE SSL ##########
RewriteEngine On
RewriteBase /
# Non-secure requests to www.domain.com should redirect to https://www.domain.com
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^www\.%{HTTP_HOST} [NC]
RewriteRule ^(.*)$ https://www\.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# All secure (HTTPS) traffic should redirect to https://www.domain.com
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} !^www\.%{HTTP_HOST} [NC]
RewriteRule ^(.*)$ https://www\.%{HTTP_HOST}/$1 [L,R=301]
</IfModule>
I want to make it as generic a possible so I can simply copy and paste it to any site I make so no need to edit it each time - I guess I could also do this in PHP but I think it would be good if .htaccess is also there.
Another point is, can .htaccess be read if i were to go to www.domain.com/.htaccess or do I need to cover that in a 'deny all' kind of thing?
The second argument to the RewriteCond must be a regex, so it cannot contain a variable.
Try adding the following to your .htaccess file in place of the rules you had
#capture top level domain (.com or .co.uk)
RewriteCond %{HTTP_HOST} ([-_a-zA-Z0-9]+\.([a-zA-Z]{2,5}|co\.uk))$ [NC]
RewriteCond %{HTTP_HOST} (www\.)?(.+)$ [NC]
RewriteRule ^ - [E=MY_TLD:%2]
# Non-secure requests to www.domain.com should redirect to https://www.domain.com
RewriteCond %{HTTPS} off
RewriteRule ^ https://www\.%{ENV:MY_TLD}%{REQUEST_URI} [L,R=301]
# All secure (HTTPS) traffic should redirect to https://www.domain.com
RewriteCond %{HTTPS} on
#if host does not start with www
RewriteCond %{HTTP_HOST} !^www\.[-_a-zA-Z0-9]+\.([a-zA-Z]{2,5}|co\.uk)$ [NC]
RewriteRule ^ https://www\.%{ENV:MY_TLD}%{REQUEST_URI} [L,R=301]
Shortest version would be:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTP_HOST} (www\.)?(.+)$ [NC]
RewriteRule ^ https://www\.%2%{REQUEST_URI} [L,R=301]
Only (somewhat) downside would be that subdomain.example.com gets redirected to www.subdomain.example.com

Htaccess maintenance mode allow certain directories

So I use the following for to force my site into maintenance mode while updating certain things:
# MAINTENANCE-PAGE REDIRECT
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REMOTE_ADDR} !^23\.1\.12\.167
RewriteCond %{REQUEST_URI} !/maintenance.html$ [NC]
RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif) [NC]
RewriteRule .* /maintenance.html [R=302,L]
</IfModule>
This has worked well, but now I have the situation when in maintenance mode that I wish to exclude certain dir's from being sent to the maintenance.html and rather have them display their normal contents.
So it would be something like:
root/
.htaccess
maintenance.html
index.html
everything.else.html
/do_not_display_me
/display_me_always
Not sure if this is possible from the root level .htaccess or if I'm going to have to get crafty with sub-dir .htaccess files, any help is appreciated.
This should do the job. It tells Apache to not to rewrite those folders (which makes maintenance rules to be omitted as rewrite chain will never reach them).
# activate rewrite engine
RewriteEngine on
# always allow these folders
RewriteCond %{REQUEST_URI} ^/display_me_always [OR]
RewriteCond %{REQUEST_URI} ^/another_folder [OR]
RewriteCond %{REQUEST_URI} ^/even_more_folders
RewriteRule .+ - [L]
# maintenance rules
RewriteCond %{REMOTE_ADDR} !^23\.1\.12\.167
RewriteCond %{REQUEST_URI} !/maintenance.html$ [NC]
RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif) [NC]
RewriteRule .* /maintenance.html [R=302,L]
Letter case matters, so if you need to match mixed case spelling insert NC, into [OR].
You may consider adding slash / at the end of folder names if you have files in root folder with the same names.

How do i force www subdomain on both https and http

For whatever reason I can't seem to get this right, I've looked at many examples on here and apache's website. I'm trying to force www.domain.com instead of domain.com on EITHER http or https but I am not trying to force https over http.
the following code seems to work for all https connections but http will not redirect to www.
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteRule ^ https://www.domain.com%{REQUEST_URI} [R=301]
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteRule ^ http://www.domain.com%{REQUEST_URI} [R=301]
You don't need the second RewriteEngine directive. That may or may not be causing a parse issue making the second set of rules not work. To test whether this is the case, try switching the order of the two blocks you have.
It's good practice to use L to modify requests that are definitely the last. So, change [R=301] to [R=301,L] both times it appears.
Largely as a matter of style, I would consider changing the RewriteRule directives to something like (using http or https as appropriate):
RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,L,QSA]
Your rules seem to be fine. You can combine them as follows:
RewriteCond %{HTTP_HOST} !^www\.example\.com$
RewriteCond %{HTTPS}s on(s)|
RewriteRule ^ http%1://www.example.com%{REQUEST_URI} [L,R=301]
Also note the additional L flag to stop the rewriting process after this rule has been applied.
In case anyone still need an answer to this. Use another .htaccess. Get guide from here, I found it and it looks good: http://www.farinspace.com/codeigniter-htaccess-file/
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
### Canonicalize codeigniter URLs
# If your default controller is something other than
# "welcome" you should probably change this
RewriteRule ^(welcome(/index)?|index(\.php)?)/?$ / [L,R=301]
RewriteRule ^(.*)/index/?$ $1 [L,R=301]
# Removes trailing slashes (prevents SEO duplicate content issues)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ $1 [L,R=301]
# Enforce www
# If you have subdomains, you can add them to
# the list using the "|" (OR) regex operator
RewriteCond %{HTTP_HOST} !^(www|subdomain) [NC]
RewriteRule ^(.*)$ http://www.domain.tld/$1 [L,R=301]
# Enforce NO www
#RewriteCond %{HTTP_HOST} ^www [NC]
#RewriteRule ^(.*)$ http://domain.tld/$1 [L,R=301]
###
# Removes access to the system folder by users.
# Additionally this will allow you to create a System.php controller,
# previously this would not have been possible.
# 'system' can be replaced if you have renamed your system folder.
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php/$1 [L]
# Checks to see if the user is attempting to access a valid file,
# such as an image or css document, if this isn't true it sends the
# request to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
<IfModule !mod_rewrite.c>
# Without mod_rewrite, route 404's to the front controller
ErrorDocument 404 /index.php
</IfModule>
Remember, once you have your CodeIgniter htaccess file setup, you will want to go into your “/system/application/config/config.php”, find the following:
$config['index_page'] = "index.php";
and change it to:
$config['index_page'] = "";