Stop Mod_Rewrite execution on matching RewriteCond - mod-rewrite

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

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)

mod rewrite and static pages

is possible to exclude a url being parsed by mod rewrite?
my .htaccess has rewrite rules like
RewriteRule ^contact contact_us.php
and a couple more static pages.
currently my site don't have troubles cause uses http://domain.com/user.php?user=username
but now i need rewrite to:
http://domain.com/username
I've tried with:
RewriteRule ^(.*)$ user.php?user=$1 [L]
but all my site stops working...
is possible to avoid parse my static pages like contact/feed/etc being treated like usernames?
edit to match david req:
this is my actual .htaccess file:
RewriteEngine On
Options +Followsymlinks
RewriteRule ^contact contact_us.php [L]
RewriteRule ^terms terms_of_use.php [L]
RewriteRule ^register register.php [L]
RewriteRule ^login login.php [L]
RewriteRule ^logout logout.php [L]
RewriteRule ^posts/(.*)/(.*) viewupdates.php?username=$1&page=$2
RewriteRule ^post(.*)/([0-9]*)$ viewupdate.php?title=$1&id=$2
RewriteRule ^(.*)$ profile.php?username=$1 [L]
also i've enabled modrewrite log my first file:http://pastie.org/1044881
Put the rewrite rules for the static pages first, and add the [L] flag to them:
RewriteRule ^contact contact_us.php [L]
...
then after those, use your rewrite rule for the username:
RewriteRule ^(.*)$ user.php?user=$1 [L]
(hopefully nobody has a username of contact).
EDIT: Based on the log output you posted (which I'm assuming corresponds to an unsuccessful attempt to access the contact page... right?), try changing the contact rewrite rule to either
RewriteRule ^contact$ contact_us.php [L]
or
RewriteRule ^contact contact_us.php [L,NS]
That is, either add $ to make the pattern match only the literal URL contact, or add the NS flag to keep it from applying to subrequests. According to the log output, what seems to have happened is that Apache rewrites contact to contact_us.php and then does an internal subrequest for that new URL. So far so good. The weird thing is that the ^contact pattern again matches contact_us.php, "transforming" it to contact_us.php, i.e. the same thing, which Apache interprets as a signal that it should ignore the rule entirely. Now, I would think Apache would have the sense to ignore the rule only on the subrequest, but I'm not sure if it's ignoring the entire rewriting process and leaving the original URL, /contact, as is. If that's the case, making one of the changes I suggested should fix it.
EDIT 2: your rewrite log excerpt reminded me of something: I'd suggest making the rewrite rule
RewriteRule ^([^/]+)$ user.php?user=$1 [L]
since slashes shouldn't be occurring in any usernames. (Right?) Or you could do
RewriteRule ^(\w+)$ user.php?user=$1 [L]
if usernames can only include word characters (letters, numbers, and underscore). Basically, make a regular expression that matches only any sequence of characters that could be a valid username, but doesn't match URLs of images or CSS/JS files.
The -f and -d options to RewriteCond check if the current match is a file or directory on disk.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ....

mod_rewrite - redirect from one domain to another and preserve trailing values in url

I think this is a pretty straight forward question in mod_rewrite:
I got one domain, which needs to redirect to another, but keep any value after last slash (/) in the first URL, over to the second.
domain.com/4433 should transfer to domain.com/folder/?p=4333
Listed for clarity:
From: domain.com/4433
To: domain.com/folder/?p=4333
Any ideas?
Edit:
Did some testing, we found the following solution:
RewriteCond %{HTTP_HOST} ^domain.com$
RewriteRule ^([0-9a-z]*)$ /folder/?p=$1 [NC]
sincerely,
- bakkelun
In case you don't really want to redirect but to have pretty URLs, you can use
RewriteEngine On
RewriteRule ^/(.+)$ /folder?p=$1 [L]
This takes everything after the first slash and inserts it at the $1 - but only if there's something after the slash. It doesn't issue a redirect so the users won't notice.
Without any further information, try this:
RewriteEngine on
RewriteRule ^/([^/]+)$ /folder/?p=$1
If you want to use the rule in a .htaccess file, remove the leading slashes.
RewriteEngine On
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^(.*)$ domain.com/folder?p=$1 [R=301,L]
Just in case: domain.com = domain1.com and domain2.com? domain1.com should be redirected to domain2.com? Both run on the same server (optional)?
[EDIT:]
If you really only want to do the thing as stated in the comment, then do the following:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domain1.com$
RewriteRule ^4433$ http://domain2.com/folder/?p=4433 [R=301,L]
Else, as Benedikt Eger said, or with R=301 if you want real redirection.
Or, if you want it to redirect only on numbers, then do the following:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domain1.com$
RewriteRule ^([0-9])+$ http://domain2.com/folder/?p=$1 [R=301,L]
RewriteCond checks, if defined vhost is domain1.com, but not domain2.com, then the rewrite rule is applied, and redirects via HTTP status 301 [R=301] only number strings (0-9)+ consisting of at least one number to the specified URL. [L] makes this the last rule applied.

mod_rewrite "too many redirects" problem

Trying,
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]
RewriteCond %{HTTP_HOST} ^(.*)dev\.example\.edu$ [NC]
RewriteRule ^/test(.*)$ http://dev.example.edu/test/index.php/test$1 [NC]
</IfModule>
on an apache 2.2 server, to get this rewrite working to hide the "index.php/test" part of the path.
everything i've tried either loops the url part (index.php/test) within the address bar or gives a "too many redirects" error.
i suspect that the "test" part of the equation being on both sides is throwing it off but am not sure how to get it to work.
i just want:
dev.example.edu/test/index.php/test*
to rewrite to:
dev.example.edu/test/*
thanks
You need to exclude the destination path to avoid an infinite recursion:
RewriteCond %{HTTP_HOST} ^(.*)dev\.example\.com$ [NC]
RewriteCond $1 !^/index\.php/test/
RewriteRule ^/test/(.*)$ http://dev.example.com/test/index.php/test/$1 [NC]
Here the match of the first grouping ($1) is checked not to match ^/index\.php/test/.
But if you want to rewrite /test/index.php/test/… to /test/…, you will rather need this rule:
RewriteCond %{HTTP_HOST} ^(.*)dev\.example\.com$ [NC]
RewriteRule ^/index\.php/test/(.*)$ http://dev.example.com/test/$1 [NC]
Per Jim at webmasterworld (thanks!)
"The [P] flag invokes a reverse-proxy request to the server at the designated URL; That is, it opens a new out-going HTTP connection and sends a request to that server. So at the very least, your configuration is twice as slow as it should be, just using the original working rule, because your server is sending itself a new request via HTTP instead of just serving the content from a non-default-mapped filepath.
It seems to me that all that's needed is an internal rewrite, so that requests for the resource at URL
http://dev.example.edu/distribution/ are served with the content generated by the script at the server filepath /distribution/index.php/distribution/"
RewriteEngine on
#
# Return 403-Forbidden response to TRACE requests
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]
#
# Internally rewrite requests for URL-path /recreation/<anything>
# to filepath /eel/index.php/recreation/<anything>
RewriteCond %{HTTP_HOST} ^dev\.example\.edu [NC]
RewriteRule ^/recreation/(.*)$ /ee1/index.php/recreation/$1 [L]
#
# Internally rewrite requests for URL-path /distribution/<anything>
# to filepath /distribution/index.php/distribution/<anything>
RewriteCond %{HTTP_HOST} ^dev\.example\.edu [NC]
RewriteRule ^/distribution/(.*)$ /distribution/index.php/distribution/$1 [L]
So I think I was just making it more complicated than it had to be. I've removed the P flag and removed the full server address from the rewriterule.

Resources