Mod rewrite - rewrite everything but - apache

I have this line of code:
RewriteRule ^(.*)/$ allcities.php?state=$1 [QSA,L]
Howver how can I change it so it doesn't rewrite a new directory I have created, such as "admin". As currently that is being rewritten as well.

You can use RewriteCond for that:
RewriteCond %{REQUEST_URI} !^/admin
RewriteRule ^(.*)/$ allcities.php?state=$1 [QSA,L]
Note the exclamation mark before the regex on the RewriteCond. It makes the regex revert its meaning. So in this case, the condition is true, if the request URI does not start with /admin.
Please see the mod_rewrite documentation for more information.

Rewrite rules are processed in the order that they are received. You will need to have a handler that will route to the existing directory before that rule is processed. For example:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ allcities.php?state=$1 [QSA,L]

Related

Multiple RewriteRule to one RewriteCond

On the side I have about 400,000 subdomains. in view of the above, some calls also operate subdomain level, e.g..
subdomain1.example.com/some_action/
Such actions that should be performed only from the domain have 27.
Htaccess file I created a rule:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www.)?example.com
RewriteRule ^some_action1/?$ index.php?some_action1 [L]
If i add this line
RewriteRule ^some_action2/?$ index.php?some_action2 [L]
not work in the same way as for some_action3, etc.
I have added for each action separately
RewriteCond %{HTTP_HOST} ^(www.)?example.com
Can you somehow skip to harmonize?
Each RewriteCond condition only applies to the immediately following RewriteRule. That means if you have a bunch of rules, you have to duplicate the conditions. If you really don't want to do that for some reason, you could use a negate at the very beginning of all your rules. This may or may not be a good solution since it could affect how you make future changes to the rules:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^(www.)?example.com
RewriteRule ^ - [L]
RewriteRule ^some_action1/?$ index.php?some_action1 [L]
RewriteRule ^some_action2/?$ index.php?some_action2 [L]
RewriteRule ^some_action3/?$ index.php?some_action3 [L]
etc...
So the first rule checks for the negative of the host being example.com, and skips everything. Then you can add all your rules without having to worry about that condition.
However, if your "some_action" is always going to be part of the GET parameters, you can maybe just use a single rule:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www.)?example.com
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/?$ index.php?$1 [L]

flexibility in .htaccess for mod_rewrite rules

i would like to redirect my old php files to new seo friendly ones:
user.php?user=$var1&task=$var2 -> url/$var1/$var2
There are 2 problems. $var2 is not set every time, so i do not know how to deal that and the querystring is always added at the end.
I use the following redirect rule for testing (without $var2)
RewriteCond %{THE_REQUEST} ^(.+)user\.php(.+)$
RewriteCond %{QUERY_STRING} user=([^/]+)$
RewriteRule ^(.+)\.php$ %1 [R]
I get this:
url/$var1/?user=$var1
Second problem is the rewrite rule so that url/$var1 -> user.php?user=$var1
Without it i get a server error.
In the moment i tried this static one for testing, but this is not the only rule so that the Condition is wrong here
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/?$ user.php?user=$1 [L]
How i get the correct results and more flexibility with the variables?
mod_rewrite is not my world in the moment, so i hope you can bring light in the dark.
Thx ruven
1) The way to prevent the query string at the end there is to add a ? at the end of the URL you rewrite to.
RewriteCond %{THE_REQUEST} ^GET\ /user\.php
RewriteCond %{QUERY_STRING} user=([^&=]+)$
RewriteRule ^user\.php %1? [R]
And in case both var1 and var2 are set it would be
RewriteCond %{THE_REQUEST} ^GET\ /user\.php
RewriteCond %{QUERY_STRING} user=([^&=]+)$
RewriteCond %{QUERY_STRING} task=([^&=]+)$
RewriteRule ^user\.php %1/%2? [R]
Combine these (the second one first) and it should redirect as needed
2) Since this is a kind of 'catch all' URL you should put this as the last option in your .htaccess and redirect everything that is not a file or a directory to user.php and then let user.php figure out if the user exists, and if not respond with HTTP 404.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ user.php?user=$1 [L]
(I've removed the / at the end as it's not a good idea to have two URLs for the exact same content).

why does a matched rewriterule not work?

I have the following .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^a/(.*)$ api.php?params=$1 [L,QSA]
RewriteRule ^$ app/webroot/ [L]
RewriteRule (.*) app/webroot/$1 [L]
</IfModule>
I expect that when I go to /a/test that the server returns /api.php?params=test
Instead, the third rule is matched.
If I comment out the third rule, then the first rule works.
Why is that?
Eventhough you have the L flag, which stops rewriting for the current rewriting iteration, the result (the rewritten URI) will be put back into the rewrite engine, and will continue to do so, until the URI going into the rewrite engine comes out unchanged. So what's happening is the first rule gets applied, then api.php?params=test is put back into the rewrite engine, where the 3rd rule gets applied.
You can either turn off all looping, by passing through the URI if an internal redirect was made, by adding this right underneath RewriteEngine On:
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
Or add a condition to the 3rd rule so that it ignores requests to existing resources:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) app/webroot/$1 [L]
Or add an explicit condition to ignore api.php:
RewriteCond %{REQUEST_URI} !^/api\.php
RewriteRule (.*) app/webroot/$1 [L]

Check URL and stop processing using htaccess

I want to check URL using htaccess. Developer might want run special file - specialfile.php. I use htaccess:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /specialfile\.php$
RewriteRule .* [L] #don't change adress
RewriteRule ^$ public/index.html [NC,L]
RewriteRule (.*) public/$1 [NC,L]
My idea was: if rewriteCond %{REQUEST_URI} !/specialfile.php$ true than htaccess should use RewriteRule .* [L] - that should mean that specialfile.php will be run and this all. But it doesn't work because it runs next rule: RewriteRule (.*) public/$1 [NC,L].
I think you are using the RewriteCond not correctly. The conditions only affect the next RewriteRule that follows.
Check out the example on the Apache Homepage. Since your 2nd RewriteRule is evalutated, I think your conditions are not correct. To get a litte bit more information about the rewriting, you should increase the log level. This is also documented here.
Your 2nd rule ^$ matches only an empty request btw. That's why it probably does not work as you expect it to.

RewriteRule not working fine

I wrote the following rule in .htaccess
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^(.*)/$ profile.php?business=$1
When i enter the URL like
http://www.abc.com/mujeeb/
page is correctly transfered to profiles page and page looks fine.
But i enter this in URL
http://www.abc.com/mujeeb
page doesn't show.
Can you please tell why? Or write the rule for this? i tried many times but not sucessful.
Mujeeb.
page doesn't show. because you specified that you RewriteRule is applied to the URL's ending with / at the end. Rewrite it as
RewriteRule ^(.*)/?$ profile.php?business=$1 [L]
And I hope that you have additional RewriteCond statements in order to prevent the infinite loop with redirects.
ps: basically you can prevent loop in two way
1) checks that requested url does not correspond to the existing file or directory. it is, probably, the best way to do (read comments to the second method)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/?$ profile.php?business=$1 [L]
2) checks that you are requesting not the file from RewriteRule. This method is not good, because for each request, even for existing files and directories, it calls profile.php script
RewriteCond %{REQUEST_URI} !profile\.php$
RewriteRule ^(.*)/?$ profile.php?business=$1 [L]
It is because you check for the trailing slash with ^(.*)/$. If you add a question mark, the trailing slash will be optional.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)/?$ profile.php?business=$1
The RewriteCond is neccessary to make sure the Rule will only be applied once. Otherwise Apache will be caught in an infinite loop.
Try this:
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^(.*)[/]?$ profile.php?business=$1
That makes the last slash optional.
Well you rule is checking for a trailing slash in URI and that's the reason /mujeeb/ works but /mujeeb does not. Change your code to:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
# If the request is not for a valid file
#RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid directory
#RewriteCond %{REQUEST_FILENAME} !-f
# your rule without trailing slash
RewriteRule ^(.*)$ profile.php?business=$1 [L,QSA]
Plenty of good answers already. My answer is a bit different.
This is what I usually do. If the requested URL doesn't end with a /, I make the browser redirect to a URL with the trailing /. This is consistent with the default behaviour of Apache (due to mod_dir). So, this is how I solve this problem.
RewriteEngine On
# Canonicalize http://example.com/mujeeb to http://example.com/mujeeb/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)([^/])$ /$1$2/ [R=307,L]
# Let profile.php process http://example.com/mujeeb/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ profile.php?business=$1