views:

362

answers:

3

Simple issue but can't seem to find an answer doing some quick Googling. What's the Rails way of doing this 301 direct (http://x.com/abc > http://www.x.com/abc). A before_filter?

+7  A: 

Ideally you'd do this in your web server (Apache, nginx etc.) configuation so that the request doesn't even touch Rails at all.

Add the following before_filter to your ApplicationController:

class ApplicationController < ActionController::Base
  before_filter :add_www_subdomain

  private
  def add_www_subdomain
    unless /^www/.match(request.host)
      redirect_to("#{request.protocol}x.com#{request.request_uri}",
                  :status => 301)
    end
  end
end

If you did want to do the redirect using Apache, you could use this:

RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.x\.com [NC]
RewriteRule ^(.*)$ http://www.x.com/$1 [R=301,L]
John Topley
Great answer John. If you are using Rails >= 2.3, I would suggest to use a Metal instead. :)
Simone Carletti
Thanks! Yes, good point about the Metal.
John Topley
Thanks so much John.
Newy
You're welcome!
John Topley
For a 301 redirect in the code above, you need to include the status. Otherwise it's just a 302 Temporary Redirect.redirect_to("#{request.protocol}x.com#{request.request_uri}", :status=>301)
Terrell
@Terrell Good point.
John Topley
+5  A: 

While John's answer is perfectly fine, if you are using Rails >= 2.3 I would suggest to create a new Metal. Rails Metals are more efficient and they offers better performance.

$ ruby script/generate metal NotWwwToWww

Then open the file and paste the following code.

# Allow the metal piece to run in isolation
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails)

class NotWwwToWww
  def self.call(env)
    if env["HTTP_HOST"] != 'www.example.org'
      [301, {"Content-Type" => "text/html", "Location" => "www.#{env["HTTP_HOST"]}"}, ["Redirecting..."]]
    else
      [404, {"Content-Type" => "text/html"}, ["Not Found"]]
    end
  end
end

Of course, you can customize further the Metal.

If you want to use Apache, here's a few configurations.

Simone Carletti
Simone, any advice on how to use this with Rails 3? I'd like to redirect `www.foo.com` to `foo.com`.
macek
With Rails 3 it's even more easier: use the routing `redirect` method. No need to use a Metal.
Simone Carletti
A: 

I found this article when trying to achieve the opposite (www to root domain redirection). So I wrote the piece of code that redirects all pages from www to the root domain.

Aymeric