Bulk redirects with Apache RewriteMap
I recently ran into a situation where a client wanted us to add custom redirects for over a hundred domains. They wanted to redirect legacy URIs to their new locations and what they sent us was a giant .txt file containing thousands of old and new URI combinations.
After a quick clean-up, the rewrite file looked something like this:
# domain.com
domain.com/products.html domain.com/products
domain.com/about-us.html domain.com/about# subdomain1.domain.com
subdomain1.domain.com/tos.html subdomain1.domain.com/# domain2.com - no longer in use
domain2.com domain1.com/domain2
As with any problem, there are multiple solutions. However, I wanted to avoid adding anything to the project and solve it with Apache. While Apache does have the RewriteMap directive, I didn’t manage to find an example of this that worked for this case.
The solution ended up pretty simple, but it took a few attempts to get it to work correctly. This is a snippet from our vhost:
RewriteEngine On
RewriteMap redirects txt:/var/www/domain.com/redirect/rewrite-map.txt# redirect if full URL is found in the map
RewriteCond ${redirects:%{HTTP_HOST}%{REQUEST_URI}} ^.+$
RewriteRule .* https://${redirects:%{HTTP_HOST}%{REQUEST_URI}} [redirect=permanent,last,qsdiscard]# redirect whole domain if host only without trailing / is found in the map
RewriteCond ${redirects:%{HTTP_HOST} ^.+$
RewriteRule .* https://${redirects:%{HTTP_HOST}}%{REQUEST_URI} [redirect=permanent,last]
The first redirect looks for the full URI in the map and redirects to the value it found. The second redirect looks for just the domain in the file and redirects the request with its path and query parameters appended to the found value.
And there you have it. Your old URIs are getting redirected to your new ones, the SEO guys are happy and all the old links to the site keep working.