Forum Moderators: phranque
RedirectMatch 301 ^/de/(.*)$ http://de.example.com/$1
RedirectMatch 301 ^/es/(.*)$ http://es.example.com/$1
I also did a 301 to redirect requests for example.com to www.example.com. So far, so good.
But now I have bought a better domain name (newdomain.com) for this site and I am doing a 301 of everything to the new domain name - redirecting normal requests, redirecting requests without the "www" and making sure the duplicate content problem with sub-directories and sub-domians is avoided. This is what I have at the moment:-
Options +FollowSymLinks
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteOptions inherit
RewriteCond %{HTTP_HOST} example.com$ [NC]
RewriteRule ^(.*) http://www.newdomain.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^newdomain\.com
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=permanent,L]
RedirectMatch 301 ^/es/(.*)$ http://es.newdomain.com/$1
RedirectMatch 301 ^/pt/(.*)$ http://pt.newdomain.com/$1
RedirectMatch 301 ^/de/(.*)$ http://de.newdomain.com/$1
RedirectMatch 301 ^/it/(.*)$ http://it.newdomain.com/$1
RedirectMatch 301 ^/fr/(.*)$ http://fr.newdomain.com/$1
RedirectMatch 301 ^/nl/(.*)$ http://nl.newdomain.com/$1
RedirectMatch 301 ^/jp/(.*)$ http://jp.newdomain.com/$1
</IfModule>
Everything is working, but when I make a request for de.example.com, I get two 301 redirects, the first one to www.newdomain.com/de/ and the second one to de.newdomain.com. This seems to me excessive.
Is there any way of configuring my .htaccess to deal with all situations more efficiently and have just 1 redirect? Is there anything else wrong with my code?
Thanks a lot!
Rules are processed in per-module order. So, it may be that all the RedirectMatch stuff is being processed *before* the RewriteRule stuff. Should you ever move to a different server, the order might change to be the reverse. That would cause odd effects. The order of processing is dependent on the order that the modules are loaded into memory in the server.
It therefore follows, that should you happen to use RewriteRule for some of your redirects and/or rewrites, that you should use it for *all* of them.
You also need to optimise the per-module order of processing. Aim it so that stuff affecting only a small number of files (very specific names) is listed first, and more general stuff (like non-www to www) is listed last. This avoids a redirection chain.
Note also that your use of [NC] is sporadic, and you use '301' in one rule and 'permanent' in another. Use the same conventions for all rules to avoid mis-reading your code.
Options +FollowSymLinks
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteOptions inherit
RewriteCond %{HTTP_HOST} ^(www\.)?newdomain\.com
RewriteRule ^/es/?(.*) http://es.newdomain.com/$1 [R=301,L]
RewriteRule ^/pt/?(.*) http://pt.newdomain.com/$1 [R=301,L]
RewriteRule ^/de/?(.*) http://de.newdomain.com/$1 [R=301,L]
RewriteRule ^/it/?(.*) http://it.newdomain.com/$1 [R=301,L]
RewriteRule ^/fr/?(.*) http://fr.newdomain.com/$1 [R=301,L]
RewriteRule ^/nl/?(.*) http://nl.newdomain.com/$1 [R=301,L]
RewriteRule ^/jp/?(.*) http://jp.newdomain.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} example.com$ [NC]
RewriteRule ^(.*) http://www.newdomain.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^newdomain\.com
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]
</IfModule>
I'm afraid I don't know where to go from here. Can you give me a clue as to how to do this?
Thanks.
RewriteCond %{HTTP_HOST} ^(www\.)?newdomain\.com [OR]
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com
Simply take each of your problematic URLs, and "think through" the code asking, "how will this specific URL" be affected by my rules?" The trouble should be easy to find if you do that.
And of course, be sure to completely flush your browser cache after changing any code on the server in order to avoid seeing stale browser-cached responses.
Jim
[edited by: jdMorgan at 2:53 pm (utc) on April 20, 2009]
Alternately, simply merge the two rules by adding an [OR] flag to the first RewriteCond and deleting the first RewriteRule directive of the two.
RewriteCond %{HTTP_HOST} example\.com [NC,OR]
RewriteCond %{HTTP_HOST} ^newdomain\.com [NC]
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]
Options +FollowSymLinks
RewriteEngine on
RewriteOptions inherit
RewriteCond %{HTTP_HOST} ^(www\.)?newdomain\.com [OR]
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com
RewriteRule ^/es/?(.*) http://es.newdomain.com/$1 [R=301,L]
RewriteRule ^/pt/?(.*) http://pt.newdomain.com/$1 [R=301,L]
RewriteRule ^/de/?(.*) http://de.newdomain.com/$1 [R=301,L]
RewriteRule ^/it/?(.*) http://it.newdomain.com/$1 [R=301,L]
RewriteRule ^/fr/?(.*) http://fr.newdomain.com/$1 [R=301,L]
RewriteRule ^/nl/?(.*) http://nl.newdomain.com/$1 [R=301,L]
RewriteRule ^/jp/?(.*) http://jp.newdomain.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} example\.com [NC,OR]
RewriteCond %{HTTP_HOST} ^newdomain\.com [NC]
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]
One more thing: The first two RewriteConds in your code apply only to the first RewriteRule in your code, but I suspect you don't need them at all. You can confirm by testing any/all of the rules past the first one - the one that handles "/es/xyz" URLs.
If you do have a problem with the additional language rules, then you'll either need to replicate the first two RewriteConds for each language rule, or make a "skip" rule at the top to skip over all of the language redirects if the requested hostname is NOT newdomain.com and NOT example.com.
Jim
[edited by: jdMorgan at 9:13 pm (utc) on April 20, 2009]
RewriteCond %{HTTP_HOST} ^(www\.)?newdomain\.com [OR]
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com
RewriteRule ^/es/?(.*) http://es.newdomain.com/$1 [NC,R=301,L]
RewriteCond %{HTTP_HOST} ^(www\.)?newdomain\.com [OR]
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com
RewriteRule ^/pt/?(.*) http://pt.newdomain.com/$1 [NC,R=301,L]
...
... etc.
One last thing is to add a blank line after each RewriteRule line in the code, and to add a
# comment after the blank line, with the comment describing the code that follows the comment.
Options +FollowSymLinks
RewriteEngine on
RewriteOptions inherit
#
# Externally redirect subfolder requests to subdomains
# Skip next seven rules if NOT newdomain.com and NOT example.com
RewriteCond %{HTTP_HOST} !^(www\.)?newdomain\.com
RewriteCond %{HTTP_HOST} !^(www\.)?example\.com
RewriteRule . - [S=7]
RewriteRule ^/es/?(.*) http://es.newdomain.com/$1 [R=301,L]
RewriteRule ^/pt/?(.*) http://pt.newdomain.com/$1 [R=301,L]
RewriteRule ^/de/?(.*) http://de.newdomain.com/$1 [R=301,L]
RewriteRule ^/it/?(.*) http://it.newdomain.com/$1 [R=301,L]
RewriteRule ^/fr/?(.*) http://fr.newdomain.com/$1 [R=301,L]
RewriteRule ^/nl/?(.*) http://nl.newdomain.com/$1 [R=301,L]
RewriteRule ^/jp/?(.*) http://jp.newdomain.com/$1 [R=301,L]
#
# Externally redirect requests for non-canonical hostnames to www.newdomain.com
RewriteCond %{HTTP_HOST} example\.com [NC,OR]
RewriteCond %{HTTP_HOST} ^newdomain\.com [NC]
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]
I don't know why, but now nothing concerning the subdomains is working. I've tried following the advice in this thread step by step and also simply copying your last example directly, but now only simple redirects work, not the subdomains.
For example, a request for example.com/es now gives:
example.com/es -> www.newdomain.com/es -> newdomain.com/es/ -> www.newdomain.com/es/
This is the current code:
AddHandler application/x-httpd-php .htm .html
#
Options +FollowSymLinks
RewriteEngine on
RewriteOptions inherit
#
# Externally redirect subfolder requests to subdomains
# Skip next seven rules if NOT newdomain.com and NOT example.com
RewriteCond %{HTTP_HOST} !^(www\.)?newdomain\.com
RewriteCond %{HTTP_HOST} !^(www\.)?example\.com
RewriteRule . - [S=7]
RewriteRule ^/es/?(.*) http://es.newdomain.com/$1 [R=301,L]
RewriteRule ^/pt/?(.*) http://pt.newdomain.com/$1 [R=301,L]
RewriteRule ^/de/?(.*) http://de.newdomain.com/$1 [R=301,L]
RewriteRule ^/it/?(.*) http://it.newdomain.com/$1 [R=301,L]
RewriteRule ^/fr/?(.*) http://fr.newdomain.com/$1 [R=301,L]
RewriteRule ^/nl/?(.*) http://nl.newdomain.com/$1 [R=301,L]
RewriteRule ^/jp/?(.*) http://jp.newdomain.com/$1 [R=301,L]
#
# Externally redirect requests for non-canonical hostnames to www.newdomain.com
RewriteCond %{HTTP_HOST} example\.com [NC,OR]
RewriteCond %{HTTP_HOST} ^newdomain\.com [NC]
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]
Note: I'm using a server header check tool to test this, as well as my own browser.
I don't know whether it is best to alter the CanonicalName entry to be www.example.com or to set CanonicalName to OFF. There's arguments either way.
Is this due to the CNAME configuration you mention or is there a way round it in .htaccess?
Requests for example.com/es and example.com/es/ are both redirected correctly to es.newdomain.com/
Current code:
AddHandler application/x-httpd-php .htm .html
#
Options +FollowSymLinks
RewriteEngine on
RewriteOptions inherit
#
# Externally redirect subfolder requests to subdomains
# Skip next seven rules if NOT newdomain.com and NOT example.com
RewriteCond %{HTTP_HOST} !^(www\.)?newdomain\.com
RewriteCond %{HTTP_HOST} !^(www\.)?example\.com
RewriteRule . - [S=7]
RewriteRule ^es(.*) http://es.newdomain.com$1 [R=301,L]
RewriteRule ^pt(.*) http://pt.newdomain.com$1 [R=301,L]
RewriteRule ^de(.*) http://de.newdomain.com$1 [R=301,L]
RewriteRule ^it(.*) http://it.newdomain.com$1 [R=301,L]
RewriteRule ^fr(.*) http://fr.newdomain.com$1 [R=301,L]
RewriteRule ^nl(.*) http://nl.newdomain.com$1 [R=301,L]
RewriteRule ^jp(.*) http://jp.newdomain.com$1 [R=301,L]
#
# Externally redirect requests for non-canonical hostnames to www.newdomain.com
RewriteCond %{HTTP_HOST} example\.com [NC,OR]
RewriteCond %{HTTP_HOST} ^newdomain\.com [NC]
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]
I am asking because you have no rule shown here that rewrites cc.example.com to example.com/cc/, although you do have redirects that go the opposite way. Note that in this file es.example.com would be redirected to www.newdomain.com, and the "es" would be lost.
As such, it looks like the problem is outside of this code and outside of this .htaccess file. The only way to fix the problem is to go find that code and fix it there.
Jim
The first redirect is shown also by Brent's Server Header Checker. The second one is shown by other tools.
I believe it is a problem with how subdomains are set up by my host. I've logged a ticket with them.
Thanks for your help with the htacess code.