RewriteCond HTTP_HOST still passes - mod-rewrite

I'm building a preprod environment where the client and developpers will be able to check that everything is working fine for their website they are about to put up but i must disable all HTTPS redirection because at this point it would fall in the PROD site wathever the HOSTNAME is sent in the request.
This is one of the examples i'm using:
RewriteCond %{HTTP_HOST} (www\.)?domain\.com
RewriteCond %{HTTP_HOST} ^s\.domain\.com
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} !^/?basket/$
RewriteCond %{REQUEST_URI} !^/?basket/add/
RewriteCond %{REQUEST_URI} !^/?basket/delete/
RewriteCond %{REQUEST_URI} !^/?basket/modify/
RewriteCond %{REQUEST_URI} !^/?basket//add/
RewriteCond %{REQUEST_URI} !^/?basket//delete/
RewriteCond %{REQUEST_URI} !^/?basket//modify/
RewriteCond %{REQUEST_URI} !^/?basket/info_panier.js
RewriteRule ^/?basket/.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
Problem is, even if i visit:
http://s.domain.com/basket//coordonnees/login/
It still redirects me to the HTTPS version, but i have a rewrite condition on the s.domain.com saying to skip this rule... What am i doing wrong?
CrazyCoder

Never mind i found it two seconds later, but this might help other people:
The condition:
RewriteCond %{HTTP_HOST} (www\.)?domain\.com
Came clashing on the condition:
RewriteCond %{HTTP_HOST} ^s\.domain\.com
Because i didn't put a ! off the start. If i put ! before the (www.)?domain.com it will not match s.domain.com and thus work fine...

Related

How to exclude certain sections of a site from Mod ReWrite Rules

I am moving most pages from a site and I want to redirect all requests to a 404 error page except all/any pages in a certain cname on the site, all/any pages in a certain sub-directory on the site and a certain page in a certain directory on the site.
Here is what I have so far:
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{HTTP_HOST} !^blogs.example.com [NC]
RewriteCond %{REQUEST_URI} !^/private [NC]
RewriteCond %{REQUEST_URI} !^/public/special-form.php [NC]
RewriteCond %{REQUEST_URI} !^/public/special-form_submitted.php [NC]
RewriteCond %{REQUEST_URI} !^/error404.php [NC]
RewriteRule ^(.*) http://example.com/error404.php [R=301,L]
Your issue is mainly the / at the start of your RewriteRule, why?
Because you're using it with an .htaccess so the RewriteRule path starts without the / at the begin.
If it was inside the VirtualHost then that would have worked just fine.
Basically this is what your rule is telling the server to do after our comments conversation and your update:
Options +FollowSymlinks
RewriteEngine On
# if domain is not blogs.example.com
RewriteCond %{HTTP_HOST} !^blogs.example.com [NC]
# and if address does not start with /private
RewriteCond %{REQUEST_URI} !^/private [NC]
# and if the file is not /public/special-form.php
RewriteCond %{REQUEST_URI} !^/public/special-form.php [NC]
# and if the file is not /public/special-form_submitted.php
RewriteCond %{REQUEST_URI} !^/public/special-form_submitted.php [NC]
# and if the file is not /error404.php
RewriteCond %{REQUEST_URI} !^/error404.php [NC]
# then redirect to http://example.com/error404.php
RewriteRule ^ http://example.com/error404.php [R=301,L]
So anything else including images or css or not listed on the conditions would be redirected, in order to avoid that you would have to verify all the needed files within those 2 php pages and white list it, for example with a condition like this:
RewriteCond %{REQUEST_URI} !^/public/[^.]+\.(css|pdf|jpg|doc)$ [NC]
Basically the above means anything within the public folder that ends with .css or .pdf or .doc or .jpg should be displayed.
NOTE: Keep in mind that if your images and documents and whatever else you need to show to your users from those 2 PHP pages are not within the public folder the above will not work, that was merely an example to illustrate an easy way to couple multiple types of files into it.
You could also resume this 2 conditions:
RewriteCond %{REQUEST_URI} !^/public/special-form.php [NC]
RewriteCond %{REQUEST_URI} !^/public/special-form_submitted.php [NC]
as follow:
RewriteCond %{REQUEST_URI} !^/public/(special-form_submitted|special-form)\.php [NC]
You would end with:
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{HTTP_HOST} !^blogs.example.com [NC]
RewriteCond %{REQUEST_URI} !^/private [NC]
RewriteCond %{REQUEST_URI} !^/public/(special-form_submitted|special-form)\.php [NC]
RewriteCond %{REQUEST_URI} !^/public/[^.]+\.(css|pdf|jpg|doc)$ [NC]
RewriteCond %{REQUEST_URI} !^/error404.php [NC]
RewriteRule ^ http://example.com/error404.php [R=301,L]
Just a side information, since you're redirecting anything that does not match the conditions and you're not passing along anything to the redirect, you don't need the (.*), merely using ^ alone will do the job.

Regard a couple of OR-RewriteCond directives if another RewriteCond evals

I have the following configuration,
RewriteCond %{HTTPS} !^on$ [nocase,ornext]
RewriteCond %{HTTP_HOST} !^www\. [nocase,ornext]
RewriteCond %{HTTP_HOST} !\.com$ [nocase]
RewriteRule ^(.*)$ https://www.acme.com/$1 [redirect=301,last]
the purpose is to redirect to a canonical URL if the request is either not HTTPS, nor begins with www. or ends with .com.
For being seamlessly compatible with developer engines, I want to exclude all these directives if %{HTTP_HOST} includes, for example, dev.internal or so. In this case the RewriteRule should be skipped immediately. Since the three ORs are evaluated with the higher precedence than an (implicit) AND, I wonder how and where to place my dev.internal exception...
Thanks for any advice!
//edit: hmm... if OR has the higher precendence, shouldn't
RewriteCond %{HTTP_HOST} !internal\. [nocase]
RewriteCond %{HTTP:X-Forwarded-Proto} !^https$ [nocase,ornext]
RewriteCond %{HTTP_HOST} !^www\. [nocase,ornext]
RewriteCond %{HTTP_HOST} !\.com$ [nocase]
RewriteRule ^(.*)$ https://www.acme.com/$1 [redirect=301,last]
work then?
If my understanding of ornext is correct then yes, your way should work (can someone else confirm it?).
Here's another way, if you don't want to rely on that:
RewriteCond %{HTTP_HOST} internal\. [nocase] # If it's an internal host...
RewriteRule .* - [skip=1] # ... skip the next rule (and leave the URL unchanged)
RewriteCond %{HTTP:X-Forwarded-Proto} !^https$ [nocase,ornext]
RewriteCond %{HTTP_HOST} !^www\. [nocase,ornext]
RewriteCond %{HTTP_HOST} !\.com$ [nocase]
RewriteRule ^(.*)$ https://www.acme.com/$1 [redirect=301,last]

Mod_rewrite to switch HTTP to HTTPS

I am trying to use a Bluehost supplied SSL wildcard certificate to switch one subdomain to HTTPS.
The web root contains many subdomains, and I only want to affect the test. subdomain.
Going into the web root, I've written the following .htaccess file:
RewriteCond %{SERVER_NAME} ^test.mydomain.com
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}$1
Yet hitting http://test.mydomain.com/admin/index.php does not redirect me to https://test.mydomain.com/admin/index.php.
Even cutting out the Condition of SERVER_NAME, it still doesn't work.
Is my rewrite rule bad?
Well, in the first place I was in the wrong .htaccess file. I needed to go to the directory for my subdomain.
Then, simply switching it from HTTP to HTTP apparently causes some kind of redirect to www. behavior.
I had to
A) Preserve the existing rules that were not intended for test.
B) Add the test. rules.
It added up to a lot.
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^test.example.com$
RewriteRule ^index\.php$ - [L]
RewriteCond %{HTTP_HOST} !^test.example.com$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
RewriteCond %{HTTP_HOST} ^test.example.com$
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
RewriteCond %{HTTP_HOST} ^test.example.com$
RewriteCond %{REQUEST_URI} !^/test/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /test%{REQUEST_URI}
RewriteCond %{HTTP_HOST} ^test.example.com$
RewriteRule ^(/)?$ test/admin/index.php [L]

RewriteCond %{REQUEST_URI} not working

I am trying to redirect all requests coming in to the web server as http://portal.company.com/legacy to http://portal.company.com/wps/portal/public/legacy/legacyportlet with the following rule, but it is not working as expected.
RewriteEngine on
RewriteCond %{HTTP_HOST} ^portal\.company\.com$ [NC]
RewriteCond %{REQUEST_URI} ^/legacy$ [NC]
RewriteRule ^(.*)$ /wps/portal/public/legacy/legacyportlet$1 [NC,L,PT]
I have also tried
RewriteCond %{HTTP_HOST} ^portal\.company\.com$ [NC]
RewriteRule ^/legacy /wps/portal/public/legacy/legacyportlet [NC,L,PT]
Any help would be greatly appreciated!
Thanks
It doesn't look like your source or target URLs change in any way, so possibly you're better off using Apache's basic Redirect directive which just redirects one URL to another.
Use this rule:
RewriteCond %{HTTP_HOST} ^portal\.company\.com$ [NC]
RewriteRule ^legacy/?$ /wps/portal/public/legacy/legacyportlet [NC,L]
Remember that in .htaccess RewriteRule doesn't match leading slash of URI.

mod_rewrite with external redirect and internal rewrite

I'm trying to use mod_rewrite to redirect certain pages to use SSL. For that I have:
RewriteCond %{SERVER_PORT} ^443$
RewriteCond %{REQUEST_URI} !^/login(\.php)?$ [NC]
RewriteCond %{REQUEST_URI} !^/contact-us(\.php)?$ [NC]
RewriteCond %{REQUEST_URI} !^/\..*$
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} !^dev\.example\.com$ [NC]
RewriteCond %{SERVER_PORT} ^80$
RewriteCond %{REQUEST_URI} ^/login(\.php)?$ [NC,OR]
RewriteCond %{REQUEST_URI} ^/contact-us(\.php)?$ [NC]
RewriteRule ^(.+)\.php$ https://www.example.com/$1 [R=301,L]
This works fine, and does exactly what I want it to do.
Later in my .htacess I have a:
RewriteRule ^members/(.+)/change-password$ members/.change-password.php?item=$1 [NC,QSA,L]
So if a URL appears as, for example:
http://www.example.com/members/foo-bar/change-password
Internally it would be processed as:
/members/.change-password.php?item=foo-bar
Again, this works fine and is doing what I want it too.
What I now need to do is include this in my original SSL redirect logic to ensure that any change password requests are redirected to the same URL but over https instead. I've tried:
RewriteCond %{SERVER_PORT} ^443$
RewriteCond %{REQUEST_URI} !^/login(\.php)?$ [NC]
RewriteCond %{REQUEST_URI} !^/contact-us(\.php)?$ [NC]
RewriteCond %{REQUEST_URI} !^/\..*$
RewriteCond %{REQUEST_URI} !^/members/.+/change-password [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} !^dev\.example\.com$ [NC]
RewriteCond %{SERVER_PORT} ^80$
RewriteCond %{REQUEST_URI} ^/login(\.php)?$ [NC,OR]
RewriteCond %{REQUEST_URI} ^/contact-us(\.php)?$ [NC,OR]
RewriteCond %{REQUEST_URI} ^/members/.+/change-password [NC]
RewriteRule ^(.+)\.php$ https://www.example.com/$1 [R=301,L]
But this doesn't work - I just get the page delivered over http. Changing the .+ to .* appears to put me into a permanent redirect loop.
I'm guessing this is because of the internal rewrite but no matter what I try I can't seem to resolve it.
Can anyone please advise?
Thanks,
Adam M.
A further review of the mod_rewrite documentation led me to a bit I'd missed specific to its usage in .htaccess files. Basically the [L] flag doesn't actually indicate last as per the norm. Instead you need to use the [END] flag (http://httpd.apache.org/docs/current/rewrite/flags.html#flag_l refers).
Of course that then led me to another issue - my hosting provider doesn't have an up-to-date installation of either Apache or mod_rewrite so the [END] flag triggered the ubiqitous HTTP 500 Internal Server Error.
So what to do? Well I went back to my original ruleset with the knowledge that [L] wasn't doing what I was expecting and spotted the error straight away - the %{REQUEST_URI} value had been updated by the internal rewrite:
RewriteRule ^members/(.+)/change-password$ members/.change-password.php?url-slug=$1 [NC,QSA,L]
Therefore changing my original redirection logic to exclude this resolved my issue:
RewriteCond %{SERVER_PORT} ^443$
RewriteCond %{REQUEST_URI} !^/login(\.php)?$ [NC]
RewriteCond %{REQUEST_URI} !^/contact-us(\.php)?$ [NC]
RewriteCond %{REQUEST_URI} !^/\..*$
RewriteCond %{REQUEST_URI} !^/members/.+/change-password$ [NC]
RewriteCond %{REQUEST_URI} !^/members/\.change-password(\.php)? [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} !^dev\.example\.com$ [NC]
RewriteCond %{SERVER_PORT} ^80$
RewriteCond %{REQUEST_URI} ^/login(\.php)?$ [NC,OR]
RewriteCond %{REQUEST_URI} ^/contact-us(\.php)?$ [NC,OR]
RewriteCond %{REQUEST_URI} ^/members/.+/change-password$ [NC]
RewriteRule ^(.+)(\.php)?$ https://www.example.com/$1 [R=301,L]

Resources