I need to redirect URLs from an old Drupal site to a new WordPress site with a different domain name. The Drupal site contains thousands of genetic tests, but the client will only continue to offer a hundred tests on the WordPress site.
In the .htaccess file on the WordPress site I created the redirects and tested them all. They're working fine. Here's an example:
Redirect 301 /test/detail/kptn-defect-syndrome-targeted-testing https://www.example.org/genetic_test/kptn-disorder-kptn-targeted-testing/
Redirect 301 /test/detail/herc2-defect-syndrome-targeted-testing https://www.example.org/genetic_test/herc2-disorder-herc2-targeted-testing/
Redirect 301 /test/detail/hemophilia-b-f9-targeted-testing https://www.example.org/genetic_test/hemophilia-b-f9-targeted-testing/
I also created a wildcard redirect so that all other tests that are no longer being offered will resolve to their new lab page:
RedirectMatch 301 /test/(.*) https://www.example.org/about-our-lab/
This too is working fine.
My question is where in the .htaccess file do I place the rewriterule pointing the old domain to the new domain? And does it all come before the WordPress generated directives?
Here's my rewriterule:
#RewriteCond %{HTTP_HOST} ^(?:www\.)old\.example$ [NC]
#RewriteRule ^https://www.newexample.org%{REQUEST_URI} [L,R=301]
I want to get this right so when I shut down the old Drupal site and point the domain to the server with the WordPress site everything works without issues. Currently I have all redirects above the WordPress directives. Would the rewriterule go above also, and would it go above the redirects?
UPDATE:
This is not working. I created the .htaccess file like this:
RewriteCond %{HTTP_HOST} ^(www\.)?newexample\.org [NC]
RewriteRule ^ - [S=52]
RewriteRule ^(index\.php/)?test/detail/factor-v-leiden-f5-targeted-testing$ https://www.newexample.org/genetic_test/factor-v-leiden-f5-targeted-testing/ [R=301,L]
RewriteRule ^(index\.php/)?test/detail/dystonia-6-torsion-thap1-targeted-testing$ https://www.newexample.org/genetic_test/torsion-dystonia-6-thap1-targeted-testing/ [R=301,L]
RewriteRule ^(index\.php/)?test/detail/deafness-and-myopia-slitrk6-targeted-testing$ https://www.newexample.org/genetic_test/deafness-and-myopia-slitrk6-targeted-testing/ [R=301,L]
(... and so on ...)
# Redirect all other tests to generic page
RewriteRule ^(index\.php/)?test/ https://www.newexample.org/about-our-lab/ [R=301,L]
# Redirect everything else to new domain (same URL)
RewriteRule ^ https://www.newexample.org%{REQUEST_URI} [R=301,L]
Worpress directives below.
But it is not working when I test newexample.org/test/detail/factor-v-leiden-f5-targeted-testing it does not redirect me to the new test page corresponding to the end of the applicable RewriteRule. Instead WordPress responds "Post not found."
Why is this not working?
UPDATE:
It does work as shown above. To test it I had to change the RewriteCond to another domain and comment out the generic RewriteRule. Thanks for pointing that our Mr White.
All is well. And many many thanks to Mr White.
If the old and new domains are going to be pointing to the same host then you need to convert all the redirects you have just implemented that use mod_alias
RedirectandRedirectMatchdirectives to use mod_rewriteRewriteRuleinstead.This is because mod_rewrite is processed first, despite the apparent order of the directives in the
.htaccessfile, so your generic redirect (that uses mod_rewrite) to redirect all remaining URLs would be processed first - resulting in 2 redirects for all your/test/URLs. Ok, it will still "work", but it's not ideal.Generally, you should not mix redirects from both mod_alias and mod_rewrite in the same context as you can get unexpected redirects due to the order of processing.
Another potential issue with the redirects you have implemented is that you aren't checking the hostname, so you can't have URLs that start
/test/on the new domain. You don't need to check the hostname for every rule, as they can be "grouped" together.All these redirects (that use mod_rewrite) must go before the WordPress code block, otherwise they will simply never be processed. mod_alias redirects could potentially be placed anywhere.
You are missing a space between the
RewriteRulepattern (1st arg) and the substitution string (2nd arg), so this will fail to redirect as written.You are also missing the
?after the parenthesised subpattern in the CondPattern, assuming thewwwsubdomain is intended to be optional.Bringing the above points together, the redirects could be written like this:
You just need to be careful to count the number of rules to skip. I've used 102 above as you said they would "continue to offer a hundred tests" (so, 100 redirects), plus the 2 generic redirects that follow.
You don't need to repeat the
RewriteEngine Ondirective, since that already occurs later in the file (in the WordPress code block). It is the last instance of this directive that does anything anyway, so if you repeatRewriteEngineit is arguably misleading.Alternatively, you could have a second
.htaccessfile in a/redirect-old-urlssubdirectory and internally rewrite all requests for the old domain to this subdirectory first. This has an advantage of keeping all the "old" redirects out of the main.htaccessfile, with only a minimal change to the main.htaccessfile.For example:
In the main
.htaccessfile in the root:Then, in the
/redirect-old-urls/.htaccessfile:Note that the
RewriteRulepattern matches the URL-path relative to the directory-prefix, so it does not includeredirect-old-urls/. It is for this reason that I also changed the last "catch-all" rule to use a backreference and not theREQUEST_URIserver variable, that includes the full URL-path (including the arbitraryredirect-old-urls/URL-path prefix).Any direct requests to the subdirectory (if any) would be redirected back to root by the last rule.
Alternatively, If you have access to the main server config then this could be implemented more efficiently with a
RewriteMapthat contains the mapping of old "test" URLs to new.