views:

1127

answers:

7

In an application that heavily relies on .htaccess RewriteRules for its PrettyURLs (CakePHP in my case), how do I correctly set up directives to exclude certain directories from this rewriting? I.e.:

/appRoot/.htaccess
app/
static/

By default every request to /appRoot/* is being rewritten to be picked up by app/webroot/index.php, where it's being analysed and corresponding controller actions are being invoked. This is done by these directives in .htaccess:

RewriteBase /appRoot

RewriteRule ^$ app/webroot/ [L]
RewriteRule (.*) app/webroot/$1 [L]

I now want to exclude a few directories like static/ from this rewriting. I tried with this before the Cake RewriteRules:

RewriteCond $1 ^(static|otherDir).*$ [NC]
RewriteRule (.*) - [L]

It works in so far that requests are no longer rewritten, but now all requests are being skipped, even legitimate Cake requests which should not match ^(static|otherDir).*$.

I tried several variations of these rules but can't get it to work the way I want.

A: 

Remove the [L] from the previous rules:

RewriteBase /appRoot

RewriteRule ^$ app/webroot/    
RewriteRule (.*) app/webroot/$1

[L] means "Stop the rewriting process here and don't apply any more rewriting rules."

GateKiller
A: 

No, the order right now is:

RewriteCond $1 ^(static|otherDir).*$ [NC]
RewriteRule (.*) - [L]

RewriteRule ^$ app/webroot/     [L]
RewriteRule (.*) app/webroot/$1 [L]

And I do want to stop rewriting if my "(.*) -" rule applies, otherwise everything will be redirected regardless.

deceze
A: 

Could you not apply the condition to the following rules, but with negation, as in (with some variation thereof, I'm not too good at remembering .htaccess rules, so the flags might be wrong):

RewriteCond $1 !^(static|otherDir).*$ [NC]
RewriteRule ^$ app/webroot/ [L]

RewriteCond $1 !^(static|otherDir).*$ [NC]
RewriteRule ^$ app/webroot/$1 [L]
Mike Tomasello
A: 

@Mike

I tried that as well, but apparently wildcards don't work too well with negation. (?)

RewriteCond $1 !^(static|otherDir).*$ [NC]
RewriteRule (.*) app/webroot/$1 [L]

This redirects nothing into app/webroot.

deceze
+3  A: 

For everybody trying to debug .htaccess directives, you might want to try this:

RewriteCond    %{REQUEST_FILENAME} (.*)
RewriteRule    ^(.*)$ htaccess.php?ruleMatch=$1&condMatch=%1 [L]

This redirects every request to be processed by htaccess.php, attaching the patterns matched by RewriteRule and RewriteCond as GET parameters. In the php file you can simply echo these parameters and the environment variables (REDIRECT_QUERY_STRING for example) to get some inside into what is actually being matched by your rules.

<h1>Matched by .* ($_GET):</h1>
<pre><?php print_r($_GET); ?></pre>
<h1>$_SERVER:</h1>
<pre><?php print_r($_SERVER); ?></pre>

(substitute by programming language of choice)

Still trying to figure this problem out...

deceze
A: 

Continuing to talk to myself...

Apparently the RewriteRules are working okay, the problem is that the requests are not processed by

/appRoot/app/webroot/index.php

but by

/appRoot/index.php

which is not a Cake file but one of the old 'static' files I want to keep accessible.

I guess I'll continue tweaking the rules or try moving this file into the Cake app.

deceze
+3  A: 

And the correct answer iiiiis...

RewriteRule   ^(a|bunch|of|old|directories).* - [NC,L]

# all other requests will be forwarded to Cake
RewriteRule   ^$   app/webroot/   [L]
RewriteRule   (.*) app/webroot/$1 [L]

I still don't get why the index.php file in the root directory was called initially even with these directives in place. It is now located in

/appRoot/app/views/pages/home.ctp

and handled through Cake as well. With this in place now, I suppose this would have worked as well (slightly altered version of Mike's suggestion, untested):

RewriteCond $1      !^(a|bunch|of|old|directories).*$ [NC]
RewriteRule ^(.*)$  app/webroot/$1 [L]

Thanks for playing everybody. ;)

deceze