160

I have 8 lines of rewrite rules in my .htaccess file. I need to exclude two physical directories on my server from these rules, so they can become accessible. For now all requests are sent to index.php file.

Directories to exclude: "admin" and "user".

So http requests: http://www.domain.com/admin/ should not be passed to index.php file.

ErrorDocument 404 /index.php?mod=error404

Options  FollowSymLinks
RewriteEngine On
RewriteBase /

RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]

RewriteRule ^([^/] )/([^/] )\.html$ index.php?lang=$1&mod=$2 [L]
RewriteRule ^([^/] )/$ index.php?lang=$1&mod=home [L]
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Kelvin
  • 8,813
  • 11
  • 38
  • 36

6 Answers6

317

Try this rule before your other rules:

RewriteRule ^(admin|user)($|/) - [L]

This will end the rewriting process.

Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • Hello Gumbo, your code worked if user type domain.com/admin/ (with ending slash) but not without it. Do you what can be changed for both cases to work? Thanks – Kelvin Dec 04 '09 at 20:52
  • @Kelvin: The alternation `($|/)` should handle both cases. – Gumbo Dec 04 '09 at 21:56
  • Isn't it better to use RewriteCond here instead of RewriteRule? – rineez Aug 14 '12 at 03:04
  • 8
    @rineez `RewriteCond` does always require a `RewriteRule` that it is attached to. And adding this condition as a negated `RewriteCond` to every `RewriteRule` can be quite bulky, a single `RewriteRule` as an exit above those that should be ignored in such a case is more elegant. – Gumbo Aug 14 '12 at 05:23
  • why that `-` has to be there right before `[L]`, what is it's purpose? – Ergec Jul 14 '13 at 07:34
  • 3
    @Ergec It means “don’t change anything”. – Gumbo Jul 14 '13 at 08:58
  • @Gumbo can your rule also be enhanced, disabling access only if not from a given IP. I want to allow only my local LAN to access an admin interface and want to restrict access for everyone else. – lony Nov 30 '15 at 10:31
  • @lony The remote address is in `%{REMORE_ADDR}` and can be checked with the `RewriteCond` directive, like `RewriteCond %{REMOTE_ADDR} !^192\.168\..*$`. – Gumbo Nov 30 '15 at 18:29
  • If you want to be sure to stop the rewriting engine, add the "END" flag at the end of the line : RewriteRule ..... [L,END] – Antares Oct 16 '17 at 22:30
  • @Antares END is ok but consider it's not available in Apache 2.2 – DrLightman Dec 13 '17 at 11:59
124

What you could also do is put a .htaccess file containing

RewriteEngine Off

In the folders you want to exclude from being rewritten (by the rules in a .htaccess file that's higher up in the tree). Simple but effective.

  • 23
    +1 ~ .htaccess operates hierarchically, so local folders override their parents, just like a normal cascade in CSS or MVC. – Atari Oct 30 '13 at 18:12
  • 7
    there is only one thing you should have in mind: activating .htaccess files (setting `AllowOverride` to anything else than `None` in apache config) forces apache to search for .htaccess on every request. so if you have a high frequented website/webserver that filesystem/harddisk access could have an imense performance impact... – bohrsty Aug 25 '16 at 10:42
  • Perfect advice for validating renewal of SSL certificates via the file method. No need to modify anything outside the temporary directories, or in the vhost file. Once the validation is done, you can just delete the whole folder and you're done. Just great. – Countzero May 26 '20 at 08:13
29

add a condition to check for the admin directory, something like:

RewriteCond %{REQUEST_URI} !^/?(admin|user)/
RewriteRule ^([^/] )/([^/] )\.html$ index.php?lang=$1&mod=$2 [L]

RewriteCond %{REQUEST_URI} !^/?(admin|user)/
RewriteRule ^([^/] )/$ index.php?lang=$1&mod=home [L]
Rob
  • 8,042
  • 3
  • 35
  • 37
  • Hello Rob, I put this line right after "RewriteBase /", and now I am getting "500 Error - Internal Server Error" – Kelvin Dec 04 '09 at 17:42
  • @Kelvin I edited my answer, add the condition before each rule you want it to apply to. – Rob Dec 04 '09 at 17:48
  • This one was the only one that actually helped me. The [accepted answer](https://stackoverflow.com/a/1848579/107625) did _not_ help me. – Uwe Keim Mar 10 '19 at 12:25
  • The question mark is in `!^/?(admin|user)/` not necessary if you know for sure the folders are in root, is it? – Ben Jul 15 '21 at 09:30
6

We used the following mod_rewrite rule:

RewriteEngine on
RewriteCond %{REQUEST_URI} !^/test/
RewriteCond %{REQUEST_URI} !^/my-folder/
RewriteRule (.*) http://www.newdomain.com/$1 [R=301,L]

This redirects (permanently with a 301 redirect) all traffic to the site to http://www.newdomain.com, except requests to resources in the /test and /my-folder directories. We transfer the user to the exact resource they requested by using the (.*) capture group and then including $1 in the new URL. Mind the spaces.

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
6

If you want to remove a particular directory from the rule (meaning, you want to remove the directory foo) ,you can use :

RewriteEngine on

RewriteCond %{REQUEST_URI} !^/foo/$
RewriteRule !index\.php$ /index.php [L]

The rewriteRule above will rewrite all requestes to /index.php excluding requests for /foo/ .

To exclude all existent directories, you will need to use the following condition above your rule:

RewriteCond %{REQUEST_FILENAME} !-d

the following rule

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !index\.php$ /index.php [L]

rewrites everything (except directories) to /index.php .

cafce25
  • 15,907
  • 4
  • 25
  • 31
Amit Verma
  • 40,709
  • 21
  • 93
  • 115
5
RewriteEngine On

RewriteRule ^(wordpress)($|/) - [L]
user3578691
  • 51
  • 1
  • 2