mod_rewrite troubles
I'm trying to rewrite requests for files that exist, regardless of their extension, in a public directory to that directory, and everything else to a controller. If the user goes to http://example.com/images/foo.gif, and it exists, the image should be served from %{DOCUMENT_ROOT}/public/images/foo.gif. If they go to http://example.com/foo/bar, and it doesn't exist then the request should be routed through开发者_如何学C index.php. What I have so far is two blocks that work separately, but not together. When both are put in .htaccess, whichever one is first in .htaccess works perfectly, and the one on the bottom is completely ignored (it gives a 404 page when I try to test it). Can someone please explain to me what I'm doing wrong?
RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI} -f
RewriteRule ^.*$ - [L]
RewriteRule ^.*$ index.php [L]
RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI} !-f
RewriteRule ^.*$ - [L]
RewriteRule ^(.*)$ %{DOCUMENT_ROOT}/public/$1 [L]
It looks like there's a few things wrong.
It looks like your RewriteCond's are backwards. If %{DOCUMENT_ROOT}/public/%{REQUEST_URI}
doesn't exist (!-f) then you want to rewrite to index.php, but if it does exist (-f) then rewrite to /public/$1. The second thing is the RewriteRule ^.*$ - [L]
is actually preventing the actual rule from being applied because it ends with [L] and that stops the rewriting in the current iteration.
Even if you remove the ^.*$ - [L]
rewrites and flip the -f
and !-f
, you run into a problem with the 2nd iteration of rewrites:
RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI} !-f
RewriteRule ^.*$ index.php [L]
RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI} -f
RewriteRule ^(.*)$ %{DOCUMENT_ROOT}/public/$1 [L]
This is what happens when you try to access http://example.com/foo/bar :
- %{DOCUMENT_ROOT}/public//foo/bar doesn't exist, !-f condition met
- foo/bar is rewritten to index.php, with [L], end rewrite
- The request is INTERNALLY redirected to index.php
- With a new URI (index.php) all rules are re-applied
- %{DOCUMENT_ROOT}/public/index.php exists, !-f condition failed
- %{DOCUMENT_ROOT}/public/index.php exists, -f condition met
- index.php gets rewritten to %{DOCUMENT_ROOT}/public/index.php
- INTERNAL redirect, and all rules are reapplied to new URI (/public/index.php)
- %{DOCUMENT_ROOT}/public//public/index.php doesn't exist, !-f condition met
- public/index.php is rewritten to index.php
- go back to 3. internal loop
Something similar happens when you try to access http://example.com/images/foo.gif , essentially, you need to get the other rule to stop rewriting the 2nd time around. So you need to add a 2nd set of conditions:
RewriteCond %{REQUEST_URI} !^/public/
RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI} !-f
RewriteRule ^.*$ index.php [L]
RewriteCond %{REQUEST_URI} !/index.php
RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI} -f
RewriteRule ^(.*)$ %{DOCUMENT_ROOT}/public/$1 [L]
精彩评论