Reputation: 764
I'll preface this with the fact that htaccess and mod_rewrite aren't my best areas. I've written a php MVC framework for personal use, and in the document root I have a folder called "public" for css, js, images, etc. Every HTTP request is checked against the files in "public" and if it exists, it sends that file; otherwise it redirects to index.php for the framework.
The rules work, but if a match is made in "public," it still routes to index.php. If I comment out the last line which redirects to index.php, the css and js load properly. I can't get it to stop processing after the "public" match is made.
Thanks in advance
Options +FollowSymLinks
RewriteEngine On
#If file exists as public resource
RewriteCond %{DOCUMENT_ROOT}/public/$1 -f
RewriteRule ^(.*) %{DOCUMENT_ROOT}/public/$1 [NC,L]
#Redirect everything else to index.php
RewriteRule ^(.*) index.php [NC,L]
Upvotes: 1
Views: 1589
Reputation: 787
It looks as if you're doing some unnecessary checking, and also getting hit with the fact that you will trigger a new pass through the rules each time you perform a rewrite.
Maybe try something like this?
RewriteEngine On
# pass through anything in the domain.com/public directory
RewriteRule ^/public/(.*)$ - [NC,L]
# route everything else to index
RewriteRule ^(.*)$ index.php [NC,L]
That should pass through anything in the public directory on the first pass, everything else will take 2 passes to settle on the second rule, AFAIK. I think the main trick is to provide a route that doesn't trigger a rewrite, so you don't trigger a second pass.
Bear in mind too that the parenthesis aren't really necessary unless you intend to use their contents for rewriting as $1,$2,...
Upvotes: 1
Reputation: 13169
You need to add a test to see whether the request has already been pointed to the public directory, and only trigger the RewriteRule if not:
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^.*$ index.php
Note that the [L]
("last") flag is often misunderstood. It stops the request being further tested and modified in the current pass, but it cannot stop Apache running the newly modified request through the entire ruleset from the start (which will happen because the .htaccess rules are applied, from the top, to every new or modified request). So you need to add the RewriteCond directive to check that you're not dealing with a request which was pointed to the public folder in the previous pass of the ruleset.
See the Apache 2.4 documentation for the "last" flag for more details. [Note that Apache 2.4 offers the [END]
flag which will stop requests being subjected to another pass of rewrite processing, but this new flag is not available in Apache 2.2 and earlier.]
Upvotes: 2