Goodbye .htaccess, Hello Rails
Remember the good old days of PHP? Mastering a redirect was nearly impossible without complicated PHP code or writing a server instruction (.htaccess
). Let's take a minute to examine the past and present, and then compare and contrast some of the advantages and disadvantages of each.
Pre-Rails
Before Rails, redirects were done primarily server-side or via complicated application logic. For example, in PHP, one would do something like the following:
<?php
define('APP_DOMAIN', 'https://example.com');
if($_SERVER['HTTP_HOST'] != APP_DOMAIN) {
header('HTTP/1.1 301 Moved Permanently');
header('Location: ' + APP_DOMAIN);
}
?>
Then, we'd need to include this in every file:
<?php require('ensure_domain.php') ?>
Well, this soon became cumbersome to add to every file, so we decided to just let the server handle it. This was most often accomplished via a .htaccess
file:
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{HTTP_HOST} [^example\.com]
RewriteRule ^(.*)$ <a href="https://www.example.com/%241">https://www.example.com/$1</a> [R=301,L]
Not only is this difficult to read, but this file was automatically hidden in Unix-based systems (because it's prefixed with a dot ["."]). It was often missed under source control because developers simply forgot to include it. Furthermore, it creates a very tight tie between the application and the server. Finally, not all hosting providers actually allowed modifying the web server configuration, at which point you were stuck.
Rails
The Rails framework makes it very easy to ensure a domain. Understanding that, by default, all requests go through the application_controller.rb allows us to write our ensure domain code once:
class ApplicationController < ActionController::Base
protect_from_forgery
APP_DOMAIN = 'www.example.com'
before_filter :ensure_domain
def ensure_domain
unless request.env['HTTP_HOST'] == APP_DOMAIN || Rails.env.development?
redirect_to "https://#{APP_DOMAIN}", :status => 301
end
end
end
We simply define a constant and they quickly ask Rails if the HTTP_HOST == APP_DOMAIN
. If it doesn't, we redirect with a 301. NOTE: We don't want to redirect on development - hence the || Rails.env.development?
Advantages
- Rails approach is much easier to read and much cleaner
- Rails approach is easily checked into version control
- Rails approach is easily flexible
- Rails approach is server-independent
Disadvantages
- Rails is slow - the request needs to travel all the way up the stack
- Rails server needs to restart after a change
What do you think?
About Seth
Seth Vargo is a Distinguished Software Engineer at Google. Previously he worked at HashiCorp, Chef Software, CustomInk, and some Pittsburgh-based startups. He is the author of Learning Chef and is passionate about reducing inequality in technology. When he is not writing, working on open source, teaching, or speaking at conferences, Seth advises non-profits.