Htaccess maintenance mode allow certain directories - apache

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.

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).

Modify existing .htaccess so that it ignores subdomains

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

htaccess code for maintenance page redirect

I set up a maintenance page that I could enable through an htaccess file. The html file is located in a folder called "maintenance".
The html file has some images in it. However, visitors to the page see no images, even though I added a RewriteCond line to (theoretically) allow them.
If I try to visit the URL of an image file in the browser directly, it redirects to the maintenance.htm page. I do not want image files to be redirected.
Am I missing something?
#RewriteCond %{REMOTE_ADDR} !^127.0.0.1$
#RewriteCond %{REMOTE_ADDR} !^111.111.111.111$
RewriteCond %{REQUEST_URI} !/maintenance/maintenance\.htm$ [NC]
RewriteCond %{REQUEST_URI} !\.(jpg|jpeg|png|gif|css|ico)$ [NC]
RewriteRule ^(.*)$ /maintenance/maintenance.htm [R=302,L]
I think this will work:
<IfModule mod_rewrite.c>
RewriteEngine on
# RewriteCond %{REMOTE_ADDR} !^127.0.0.1$
# RewriteCond %{REMOTE_ADDR} !^111.111.111.111$
RewriteCond %{REQUEST_URI} !/maintenance/maintenance\.htm$
RewriteCond %{REQUEST_URI} !\.(jpg|jpeg|png|gif|css|ico)$
RewriteRule ^(.*)$ /maintenance/maintenance.htm [L]
</IfModule>
I added a condition to confirm the rewrite module is active before procesing the rule. The question rule and conditions are not modified.
This rule was tested here.

Rewrite Rule with dynamic hostname

I'm interesting in rewrite rule to modify some url and paths. Here some Examples.
I have some hostnames which lookups to 1 VirtualHost throught ServerAlias in Apache conf.
example.com
anotherdomain.com
same.org
And a lot of anothers domains. Here, what I want to do:
example.com/uploads/photo.png -> /www/example.com/uploads/example.com/photo.png<br />
anotherdomain.com/uploads/photo.png -> /www/anotherdomain.com/uploads/anotherdomain.com/photo.png<br />
And same thing with another domains. This thing I've made already.
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$
RewriteRule ^uploads/([a-zA-Z0-9-\._]+)$ uploads/%2/$1 [L]
This work perfectly. But, if I try to access uploads/icons/category/image.png
I start to see 500 Internal Apache Error...
I've modify Rule to this:
RewriteCond %{REQUEST_URI} !^/uploads/%{HTTP_HOST}
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$
RewriteRule ^uploads/([a-zA-Z0-9-\._/]+)$ uploads/%2/$1 [L]
And Enable Apache Rewrite log with 9 verbosity.
RewriteCond: input='/uploads/icons/category/image.png' pattern='!^/uploads/%{HTTP_HOST}' => matched
rewrite 'uploads/icons/category/image.png' -> 'uploads/example.com/icons/category/image.png'
RewriteCond: input='/uploads/example.com/icons/category/image.png' pattern='!^/uploads/%{HTTP_HOST}' => matched
rewrite 'uploads/example.com/icons/category/image.png' -> 'uploads/example.com/example.com/icons/category/image.png'
And after that, it's exhausts 10 lookups =(
When I modify to this
RewriteCond %{REQUEST_URI} !^/uploads/example.com
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$
RewriteRule ^uploads/([a-zA-Z0-9-\._/]+)$ uploads/%2/$1 [L]
It's works perfectle for ALL stuff, but only for 1 domain: example.com
I found another solution, but it's not a perfect.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$
RewriteRule ^uploads/([a-zA-Z0-9-\._/]+)$ uploads/%2/$1 [L]
This Rule works only if I have existed dir and file. But, if i try to access:
/uploads/images/not-existed-404.nothing -> It return 500, because this file doesn't exists and rewriting into:
/uploads/example.com/example.com/example.com/example.com.......
P.S. Sorry for my bad English ;)
RewriteCond %{REQUEST_URI} !^/uploads/%{HTTP_HOST}
You CANNOT use variables or back references in pattern -- i.e. %{HTTP_HOST} will not be expanded to example.com, instead it will be treated as normal text.
You can uses these rules (working fine on my PC):
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$
RewriteCond %{DOCUMENT_ROOT}/uploads/%2/$1 -f
RewriteRule ^uploads/(.+)$ uploads/%2/$1 [L]
This rule will check if target file does exist and only then rewrites (order of conditions matter).
Let's assume:
domain name: example.com
website root: /www/example.com/
URL requested: /uploads/img/meow.png
Second condition (RewriteCond %{DOCUMENT_ROOT}/uploads/%2/$1 -f) will check if file /www/example.com/uploads/example.com/img/meow.png exists, and if it does -- then rewrite occurs.
Your .htaccess then may look like this:
RewriteEngine On
RewriteBase /
# do not do anything for already existing files & folders
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .+ - [L]
# rewrite uploads to domain-specific folder
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$
RewriteCond %{DOCUMENT_ROOT}/uploads/%2/$1 -f
RewriteRule ^uploads/(.+)$ uploads/%2/$1 [L]

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'] = "";