RewriteCond RewriteRule based on non-matching IP only before date - mod-rewrite

I am currently forwarding from RCUW.org (new upcoming website) to RiverCitiesUnitedWay.org (old website) for any visitors not matching internal staff - using the following:
RewriteCond %{REMOTE_HOST} !^(104.166.7.62|47.216.48.142|99.203.75.184|50.38.152.51)
RewriteRule ^(.*)$ http://www.rivercitiesunitedway.org/$1 [R=301,L]
However, I want to make it so that after the new year, the website goes live to the public (everyone). Basically so that it disregards the above IP address requirements after that date.

I believe I found the fix.
RewriteCond %{REMOTE_HOST} !^(104.166.7.62|47.216.48.142|99.203.75.184|50.38.152.51) [OR]
RewriteCond %{TIME} >=20191231235959
RewriteRule ^(.*)$ http://www.rivercitiesunitedway.org/$1 [R=301,L]

so that it disregards the above IP address requirements after that date
Presumably, you just don't want the redirect to the old website to occur at all? In which case, you can simply add an additional condition that references the TIME_YEAR server variable.
For example:
RewriteCond %{TIME_YEAR} =2019
RewriteCond %{REMOTE_ADDR} !^(104\.166\.7\.62|47\.216\.48\.142|99\.203\.75\.184|50\.38\.152\.51)
RewriteRule (.*) http://www.old-website.org/$1 [R=301,L]
Note that, strictly speaking, you should be referencing the REMOTE_ADDR server variable, not the REMOTE_HOST server variable. REMOTE_HOST may work OK on your system because your server is probably not configured to resolve remote IP addresses - this is not always the case.
Also, don't forget to escape the literal dots in the IP addresses. Otherwise the dot matches any character so could potentially match more users than anticipated.

Related

How to make complex conditions in mod_rewrite?

I need to deny access to the whole site for everyone except some IPs.
Also, I need to permit access to one folder of site for everyone:
Options +FollowSymLinks
Options +Indexes
RewriteEngine on
# Allow access only for devs
RewriteCond %{REMOTE_ADDR} !10.10.10.10 [NC] # First dev id
RewriteCond %{REMOTE_ADDR} !11.11.11.11 [NC] # Second dev id
# Allow direct access to files
RewriteCond %{REQUEST_FILENAME} !-f
# Redirecting guests
RewriteRule (.*) /coming/soon/index.html [R=307]
# But where to place this condition?
RewriteRule ^/?preview/?$ /preview/index.html [NC]
# Other rules for main site structure
# ...
So, I need the whole site loading only for devs. Other users (guests) will see the /coming/soon/ page
And also guests are allowed to see /preview/ page of the site.
How to do this?
If your /preview/ rewrite is suitable for all users and does not depend on subsequent rewrite rules, the simplest way is to put this RewriteRule first with the [L] flag, so that subsequent rewrites will not be applied.
Otherwise, exceptions for RewriteRule may be specified as RewriteCond matching with %{REQUEST_URI}:
RewriteCond %{REQUEST_URI} !^/?preview/?$ [NC]
Also note that your suggested rule would rewrite both /preview and /preview/ into /preview/index.html, and the first of these rewrites may break relative links unless a redirect is performed.

mod_rewrite secure redirect

Struggling with mod_rewrite trying to redirect a non-secure page to a secure one. This works:
RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} (help/returns)
RewriteRule .? https://mysite.localhost/%1/ [R=301,L]
But this doesn't:
RewriteCond %{SERVER_PORT} 80
RewriteCond %{HTTP:Host} (mysite.localhost|mylivesite.com)
RewriteCond %{REQUEST_URI} (help/returns)
RewriteRule .? https://%1/%2/ [R=301,L]
The URL it tries to give me is https://help/returns//
I can't seem to get the HTTP:host into the final RewriteRule line.
I need the host in there so I can use the same file for local dev and live deployment.
Most grateful for any input.
You can use this rule:
RewriteCond %{HTTPS} =off
RewriteRule ^help/returns https://%{HTTP_HOST}%{REQUEST_URI} [QSA,R=301,L]
This rule will redirect all requests to http://example.com/help/returns to a secure (HTTPS) location: https://example.com/help/returns -- it will preserve full URL path + query string. You have too many conditions, rule becomes complex which is not a good thing when your server is REALLY busy (regular expressions are expensive).
I have replaced %{SERVER_PORT} 80 by more proper %{HTTPS} =off (this especially useful if your site is run on non-default port, which is 80).
I have also removed HTTP_HOST matching part -- you don't really need it unless you have more than one domain name/subdomain bound to the same site. In case if you need this condition just add this line after 1st line: RewriteCond %{HTTP_HOST} ^(mysite.localhost|mylivesite.com)

How to replace 'dash' with 'underscore' in an IIRF rule?

I have a web app which serves images based on the subdomain.
We wanted to provide our users with a url like this:
http://{username}.domain.com/images/myimage.jpg
Instead of what we used to have:
http://www.reallylongdomainname.com/users/{username}/images/myimage.jpg
This makes the url shorter and less 'snoopable'.
So I set up an IIRF .ini file to do some url rewriting and it works great except for the fact that some of our users folders have an underscore. And from what I've read, underscore is not a valid character in a domain name (even though IIS supports it).
I want to know how I could do a find and replace in the $1 back reference so that a url like this:
http://some-user.domain.com/...
Could be rewritten to this:
/users/some_user/..
Here's my IIRF rule.
RewriteCond %{HTTP_HOST} ^(?!www)([^\.]+)\.domain\.com
RewriteRule ^/(.*)$ /users/*1/$1 [L,I]
Thanks for any help.
If you know there is no more than x dashes in the username:
# no dash
RewriteCond %{HTTP_HOST} ^(?!www)([^\.\-]+)\.domain\.com
RewriteRule ^/(.*)$ /users/*1/$1 [L,I]
# one dash
RewriteCond %{HTTP_HOST} ^(?!www)([^\.\-]+)-([^\.\-]+)\.domain\.com
RewriteRule ^/(.*)$ /users/*1_*2/$1 [L,I]
# two dashes
RewriteCond %{HTTP_HOST} ^(?!www)([^\.\-]+)-([^\.\-]+)-([^\.\-]+)\.domain\.com
RewriteRule ^/(.*)$ /users/*1_*2_*3/$1 [L,I]
It's not beautiful, but it works.

Rewriting CNAME subdomain

I have a sub domain that I want to redirect to a different location using mod_rewrite. For example:
subdomain.example.com -> www.example.com/subdomain
I don't want to send a redirect to the browser though (so it doesn't know the page is different).
BTW subdomain.example.com has a CNAME record pointing to example.com.
Edit
Another example, just to clarify. It is very simple: If http://x.abc.com is entered in to the browser, Apache returns the contents of http://www.abc.com/x.
If both domains share the same directory, you could do this to rewrite the requests internal:
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$
RewriteRule !^subdomain/ subdomain%{REQUEST_URI}
After the question has been clarified: This one works for me:
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$
RewriteCond %1.%{THE_REQUEST} ^([^.]+)\.[A-Z]+\ (/[^\ ]*)
RewriteCond %{DOCUMENT_ROOT}$1 !-d
RewriteRule ^([^/]+)? %1%2
But you better go with what Brandon said.
In addition to what Gumbo stated above, you can use Apache's VirtualDocumentRoot statement to dynamically map URL to a dynamic location on disk. It allows you to use parts of the URL to build a path on disk. Check out this link for more information:
http://httpd.apache.org/docs/2.2/mod/mod_vhost_alias.html
Example:
URL = http://sub.example.com/dir/page.html
Server Path = /var/www/site.com/htdocs/sub/dir/page.html
VirtualDocumentRoot = /var/www/%-2.0.%-1.0/htdocs/%-3/
RewriteCond %{HTTP_HOST} ^([^.]+)\.abc\.com$
RewriteRule ^(.*)$ http://www.abc.com/%1$1 [R=301]

Stop Mod_Rewrite execution on matching RewriteCond

I am running the free version of Helicon ISAPI Rewrite on IIS and have several sites running through the same set of rewrite rules. Up 'til now this has been fine as all the rules have applied to all the sites. I have recently added a new site which I don't want to run through all the rules. Is there any way to make requests to this site break out of the rule set after it's executed its own rules.
I've tried the following with no luck; all requests to mysite.com result in a 404. I guess what I'm looking for is a rule that does nothing and is marked as the last rule to execute [L].
## New site rule for mysite.com only
RewriteCond Host: (?:www\.)?mysite\.com
RewriteRule /content([\w/]*) /content.aspx?page=$1 [L]
## Break out of processing for all other requests to mysite.com
RewriteCond Host: (?:www\.)?mysite\.com
RewriteRule (.*) - [L]
## Rules for all other sites
RewriteRule ^/([^\.\?]+)/?(\?.*)?$ /$1.aspx$2 [L]
...
I've done something similar, to stop mod_rewrite on a WebDAV folder:
# stop processing if we're in the webdav folder
RewriteCond %{REQUEST_URI} ^/webdav [NC]
RewriteRule .* - [L]
That should work for your purposes too. If not or if you are interested in additional references, see this previous question: How do I ignore a directory in mod_rewrite?
RewriteRule ^ - [END]
. would be incorrect, since it requires at least 1 char
.* could be less efficient IMHO
L is worse than END, as it allows for additional rounds, also on internal redirects. Only END truly stops. → Details
Rewrite it to itself?
RewriteCond Host: (?:www\.)?mysite\.com
RewriteRule ^(.*)$ $1 [QSA,L]
I don't know ISAPI Rewrite syntax, but on IIRF, the "break out" rule is like this:
## Break out of processing for all other requests to mysite.com
RewriteCond %{SERVER_NAME} ^(?:www\.)?mysite\.com$
RewriteRule (.*) - [L]
or
## Break out of processing for all other requests to mysite.com
RewriteCond %{HTTP_HOST} ^(?:www\.)?mysite\.com$
RewriteRule (.*) - [L]
In each case the rule says "don't rewrite (and don't process any more rules)" and it applies when the hostname used is mysite.com or www.mysite.com. The [L] flag is the part that says "don't process any more rules" and the - replacement is the part that says "don't rewrite".

Resources