7

I want to redirect the www. version to the non-www version of the site, unless it is a subdomain. (example: redirect www.puppies.com to puppies.com but don't redirect www.cute.puppies.com).

How do I accomplish this while maintaining the full request path? (example: www.puppies.com/labradors goes to puppies.com/labradors)

Dobabeswe
  • 83
  • 1
  • 7

4 Answers4

14

In your application controller:

before_filter :redirect_subdomain

def redirect_subdomain
  if request.host == 'www.puppies.com'
    redirect_to 'http://puppies.com' + request.fullpath, :status => 301
  end
end

As @isaffe points out, you can redirect in the web server as well.

EDIT: Use permanent redirect status (301) for SEO (as suggested by @CHawk) or 307 if temporary.

noel
  • 2,095
  • 14
  • 14
  • You can use global variable like: redirect_to Rails.application.config.action_mailer.asset_host + request.fullpath instead of hard coded URL but remember to define it in production or development file as per requirement. – Dinesh Saini Nov 19 '14 at 06:10
  • True. Or just strip the `www.` from the host string if it is there, and redirect to a newly constructed url. – noel Nov 20 '14 at 00:15
  • we can also use with multi tenant site where we need to create virtual sub domains and need to restrict some sub domains like www mail – Dinesh Saini Nov 20 '14 at 07:33
  • For SEO purposes, you should make sure to specify the redirect is 301: `redirect_to 'http://puppies.com' + request.fullpath, :status => 301` – CHawk Sep 05 '16 at 18:12
  • See also: https://www.bignerdranch.com/blog/redirect-www-subdomain-to-your-apex-domain-using-the-rails-router/ – Nuno Silva Apr 05 '18 at 19:42
6

For completeness, you can use the rails' routing configuration to do this in Rails 4 using request-based routing constraints

This way has a small performance benefit over using your application controller in that the request doesn't need to hit your application code it's handled during Rails' routing middleware.

Place the following in your routes file (config/routes.rb)

eg:

Rails.application.routes.draw do

  # match urls where the host starts with 'www.' as long it's not followed by 'cute.'
  constraints(host: /^www\.(?!cute\.)/i) do 

    match '(*any)', via: :all, to: redirect { |params, request|

      # parse the current request url
      # tap in and remove www. 
      URI.parse(request.url).tap { |uri| uri.host.sub!(/^www\./i, '') }.to_s 

    }

  end

  # your app's other routes here...

end
Sam DeHaan
  • 10,246
  • 2
  • 40
  • 48
Rob
  • 7,039
  • 4
  • 44
  • 75
  • 1
    This could be `match '(*any)', to: redirect(subdomain: ''), via: :all, constraints: {subdomain: 'www'}` – Ashley Mar 26 '21 at 03:09
2

In your application controller:

  before_action :redirect_from_www_to_non_www_host

  def redirect_from_www_to_non_www_host
    domain_parts = request.host.split('.')
    if domain_parts.first == 'www'
      redirect_to(request.original_url.gsub('www.', ''), status: 301) and return  
    end
  end
Vlad Hilko
  • 1,104
  • 12
  • 17
  • removing all instances of "www." from the entire URL sounds like a bad idea. What if someone enters a URL in the search form or you use UUIDs in your URLs? – Arye Eidelman Jul 13 '20 at 22:10
  • @AryeEidelman is right. Do not use `gsub`, use `sub`. `sub` will replace only the first occurrence `request.original_url.sub('www.', '')` – mahfuz Jul 29 '22 at 17:04
0

This can be accomplished in a number of ways. If you're using nginx or apache to front-end your application, look into url rewrite.

Checkout my answer here

Is it possible to redirect a url that uses HTTPS protocol? (Heroku, Rails)

Community
  • 1
  • 1
lsaffie
  • 1,764
  • 1
  • 17
  • 22