How does one use mod_rewrite to "move" the appearance of a site directory to the root without actually moving the files? Spot the error in my code!
So, I have at site where I want pages such as;
www.example.com/shop/index.php
(or any other page under /shop/ for that matter.) to now appear as
www.example.com/index.php
but without actually moving the files, which are still located under /shop/ but are now accessed via urls at /
Seems simple enough, and I can do that on its 开发者_如何学Goown using a RewriteRule, pretty standard. The second requirement is to keep the links to the old content working, so I want a similar thing but in the other direction, but using a 301 external redirect (not rewrite), i.e.
www.example.com/shop/index.php
should 301 redirect to;
www.example.com/index.php
Again, simple enough on its own. But put the two together and you it gives you a lovely "This web page has a redirect loop" error when accessing a page. However, I don't understand why because one rule is a rewrite and one is a 301 redirect and they both have the L flag so I thought no more rules were processed. So, I am at the limit of my understanding of this mod_rewrite stuff.
To test, and avoid mucking up my site for people visiting, I am using the directories /blob/ and /b/ with /b/ being the new directory. The code I currently have that gives the redirect loop is;
RewriteRule ^blob/(.*)$ "http\:\/\/www\.example.com\/b\/$1" [R=301,NC,L]
RewriteRule ^b/(.*)$ /blob/$1 [NC,L]
I guess its because the first rule is being executed again once the second has, why is this if the 'L' flag is used? And what condition should I check or change to make so that the redirect rule only gets activated if the original request is for /blob/ not the rewritten URI.
Without any need of an extra query parameter you can use following rules in your .htaccess file:
Options +FollowSymlinks -MultiViews
RewriteEngine on
RewriteCond %{THE_REQUEST} ^GET\s/shop/ [NC]
RewriteRule ^shop/(.*)$ /$1 [R=301,NC,L]
RewriteCond %{REQUEST_URI} !^/shop/ [NC]
RewriteRule ^(.*)$ /shop/$1 [L]
- First rule will send
301
to any request from/shop/foo
to/foo
in the browser, which is an external redirect - Second rule will internally redirect any
/foo
to/shop/goo
without changing URL in the browser thus making sure your actual files are served from$DOCUMENT_ROOT/shop/
directory.
Try the following (I used your actual url examples):
RewriteEngine On
RewriteCond %{QUERY_STRING} !rewrite
RewriteRule ^shop/(.*)$ http://localhost/$1 [R=301,NC,L]
RewriteCond %{REQUEST_URI} !^\/shop\/
RewriteRule ^(.*)$ /shop/$1?rewrite [NC,L,QSA]
The issue you are running into is that when mod_rewrite
does the rewrite
it is actually performing an Internal Redirect
, which causes the rules to applied again. So, this means you have to protect against that, in this case, I've added a parameter rewrite
to the URL that the redirect checks for.
Hope that helps.
精彩评论