: Conflicting mod_rewrite rules The Background I run a university club website which has multiple domains, let's say meow.co.uk, foo.uni.ac.uk/bar/meow/ as two relevant cases. (When I upload files
The Background
I run a university club website which has multiple domains, let's say meow.co.uk, foo.uni.ac.uk/bar/meow/ as two relevant cases. (When I upload files using an FTP client, it's the latter that I navigate to.) With my htaccess file, I'm trying to:
Redirect from all other domains to meow.co.uk, the preferred domain, e.g. foo.uni.ac.uk/bar/meow/page.html --> meow.co.uk/page.html
Remove a trailing slash from files that aren't directories, otherwise the user will get an internal server error, e.g. meow.co.uk/page/ --> meow.co.uk/page
Clean the URLs:
Display the contents of the html file if the .html extension is left out, e.g. navigating to meow.co.uk/page shows the same page as navigating to meow.co.uk/page.html
Remove the .html extension from the address bar, e.g. meow.co.uk/page.html --> meow.co.uk/page
The .htaccess
ErrorDocument 404 /errors/404.html
#redirect from the other domains to meow.co.uk
RewriteCond %{HTTP_HOST} !^(www.)?meow.co.uk$ [NC]
RewriteRule ^(.*)$ meow.co.uk/ [R=302]
#remove trailing slash if not a directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ / [R=302]
#meow .co.uk/page will display the contents of meow.co.uk/page.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+)$ .html [L,QSA]
#302 from meow.co.uk/page.html to meow.co.uk/page
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9} /.*.html HTTP/
RewriteRule ^(.*).html$ / [R=302,L]
What works
foo.uni.ac.uk/bar/meow/page --> meow.co.uk/page
meow.co.uk/page/ --> meow.co.uk/page
meow.co.uk/page shows page.html and meow.co.uk/page.html --> meow.co.uk/page
What doesn't work
Expected: foo.uni.ac.uk/bar/meow/page/ --> meow.co.uk/page
Actual: --> foo.uni.ac.uk/http://meow.co.uk/page/
Expected: foo.uni.ac.uk/bar/meow/page.html --> meow.co.uk/page
Actual: --> foo.uni.ac.uk/http://meow.co.uk/page
Why don't these work?
More posts by @Tiffany637
1 Comments
Sorted by latest first Latest Oldest Best
tl;dr You need the L flag on your redirects, ie. [R=302,L].
RewriteRule ^(.*)$ meow.co.uk/ [R=302]
Bit of an aside, but... the RewriteRule pattern should be ^bar/meow/(.*) (as mentioned in my answer on your other question), otherwise you won't get the working redirects that you've stated.
For external redirects you generally want to use the L (LAST) flag (briefly mentioned in comments on the other question). Since when you redirect you normally want the rewrite processing to stop and redirect immediately.
This would seem to be the problem here, without the L flag, the rewriting continues and matches the next RewriteRule which further rewrites the request, resulting in a malformed redirect.
This is what's happening in the cases that do not work:
Request: foo.uni.ac.uk/bar/meow/page/
The first RewriteRule matches against the URL-path (less the directory prefix, which is simply the / - slash)
bar/meow/page/ >>> meow.co.uk/page/ (should stop here)
But the second RewriteRule matches the result of the previous rewrite:
meow.co.uk/page/ >>> foo.uni.ac.uk/http://meow.co.uk/page/
Request: foo.uni.ac.uk/bar/meow/page.html
bar/meow/page.html >>> meow.co.uk/page.html (should stop here)
But the last RewriteRule now matches...
meow.co.uk/page.html >>> foo.uni.ac.uk/http://meow.co.uk/page
So, both your earlier redirects need the L flag ie. [R=302,L]. Ironically, the only place you don't need the L flag is where you have used it - in your last redirect! But it is good practise to include it anyway.
Note also, that generally, external redirects should always come before internal rewrites. Whilst your rules work ok, they would be slightly more efficient (and more logical) if you had your internal rewrite last. Currently the last RewriteRule will always match, but the RewriteCond directive prevents it being triggered.
If you reverse these rules then the RewriteRule will only match when needed:
#302 from meow.co.uk/page.html to meow.co.uk/page
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9} /.*.html HTTP/
RewriteRule ^(.*).html$ / [R=302,L]
#meow .co.uk/page will display the contents of meow.co.uk/page.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule (.+) .html [L]
#redirect from the other domains to meow.co.uk
RewriteCond %{HTTP_HOST} !^(www.)?meow.co.uk$ [NC]
RewriteRule ^(.*)$ meow.co.uk/ [R=302]
Another slight problem is that your site would seem to still be accessible by both meow.co.uk and meow.co.uk. You should probably have a second rule to resolve this and redirect one to the other:
RewriteCond %{HTTP_HOST} =www.meow.co.uk [NC]
RewriteRule (.*) meow.co.uk/ [R=302,L]
The = prefix on the CondPattern makes it an exact string match, it is no longer a regex (which is why the dots are not escaped).
Terms of Use Create Support ticket Your support tickets Stock Market News! © vmapp.org2024 All Rights reserved.