John Hawthorn

Rails redirect plugin

A common requirement for websites is to have redirects from removed content or legacy URLs to new locations. Redirects drive links to old content from external websites to the correct location. 301 permanent redirects additionally will help carry the existing page’s search engine ranking over to the new page.

Until now, we’ve always handled our redirects in nginx because it

However, making changes to a live nginx config is a terrible, terrible idea. What we’ve been doing is checking in the nginx redirects and then including them from the nginx config file. Under this situation one can setup nginx on their development machine to test the redirects locally. Capistrano tasks can check the validity of the redirects, and have nginx reload its config on deployments and rollbacks.

This still leaves a lot to be desired, since this solution is

So I’ve been trying to think of a way to have redirects in ruby which could either perform redirections in rack (ideal for development) or generate the redirect rules for the web server. Here’s the DSL I’ve come up with

Rewrite.draw do redirect '/about' => '/about-us', :status => :rewrite redirect '/temp' => '/', :status => 302 redirect '/rewrite' => '/target' ['/one', '/two'].each do |from| redirect from => '/three' end redirect '/articles/:title/:lang' => '/news/:lang/:title' redirect '/news/archive/*path' => '/news/:path' redirect '/media/:ignored/*path' => '/news/:path' end

which will generate the following nginx rewrite rules

rewrite ^/about$ /about-us ; rewrite ^/temp$ / rewrite; rewrite ^/rewrite$ /target permanent; rewrite ^/one$ /three permanent; rewrite ^/two$ /three permanent; rewrite ^/articles/([^/]+)/([^/]+)$ /news/$2/$1 permanent; rewrite ^/news/archive/(.+)$ /news/$1 permanent; rewrite ^/media/([^/]+)/(.+)$ /news/$2 permanent;

It can also generate (currently slightly incorrect) rewrite and redirect rules for apache and lighttpd. Next is adding the ability to perform the rewrites and redirects in rack for development use.

This is still hugely an untested work in progress with many parts known to not be working. Expect source on github and another blog post in a couple days.