Reputation: 7866
I have a Rails 2.3.2 Application hosted on Heroku.
The naked domain and the www subdomain were added years ago and they both have some authority for search engines.
However the problem is that search engines are seeing the content as duplicate so I want to do 301 redirect from the naked domain to the www subdomain.
I have asked Zerigo DNS if I can do this via their platform and they said no, that I have to do it on Heroku's side. Heroku does not allow access to the server so I need some Rack middleware to perform this.
According to this answer here the gem rack-rewrite can do this.
However I really am a NOOB about this and I don't know how to set this up so that any url from the naked domain will be 301 redirected to the www subdomain.
Example:
example.com/products/12 => www.example.com/products/12
I am currently doing the wrong things in the application controller as follows:
before_filter :ensure_domain
protected
def ensure_domain
app_domain = "www.example.com"
naked_domain = "example.com"
page_path = request.fullpath
if request.env['HTTP_HOST'] == naked_domain && RAILS_ENV == 'production'
#HTTP 301 is a permanent redirect
redirect_to "http://#{app_domain}#{page_path}", :status => 301
end
end
This works but I know I should be doing this in Rack Middleware.
Can someone show me how to set this up with the rack-rewrite gem?
I have added the following to my application_controller.rb file:
config.middleware.insert_before(Rack::Lock, Rack::Rewrite) do
r301 %r{.*}, 'http://www.example.com$&', :if => Proc.new {|rack_env|
rack_env['SERVER_NAME'] != 'www.example.com'
}
end
Which produces the following error:
NameError (undefined local variable or method `config' for ApplicationController:Class):
Any ideas on how I can get this setup working?
Upvotes: 4
Views: 2218
Reputation: 7866
I turns out that I had two problems when using this gem.
The first was that I was putting the redirect code in the Application_Controller instead of the config.ru file.
The second was that the code I was using was not correct.
Here is the code I put in the config.ru file:
if RAILS_ENV =='production'
use Rack::Rewrite do
r301 %r{.*}, 'http://www.example.com$&', :if => Proc.new {|rack_env|
rack_env['SERVER_NAME'] != 'www.example.com'
}
end
end
Upvotes: 0
Reputation: 2860
Also you can use rack-host-redirect
gem. Add to Gemfile:
gem 'rack-host-redirect'
in config/environments/production.rb
:
config.middleware.use Rack::HostRedirect, {
'yourdomain.com' => 'www.yourdomain.com'
}
With this configuration, all requests to yourdomain.com
will be 301 redirected to www.yourdomain.com
.
Upvotes: 2
Reputation: 1001
According to the gem's README, you need to add the following to your application's config/application.rb
:
config.middleware.insert_before(Rack::Lock, Rack::Rewrite) do
moved_permanently /.*/, 'http://www.example.com$&', if: ->(env){env['SERVER_NAME'] != 'www.example.com'}
end
I have modernized the example code and tested it on a Rails 3 application.
The arguments to the moved_permanently
method are:
/.*/
is a regular expression matching any request path and url parameters, therefore, any page on the site.'http://www.example.com$&'
is the new full URL of the page (after the redirect). It has the right domain name and the original request path attached to it — the $&
symbols mean "whatever is matched by the first parameter" and it matches everything.if: ->(env){env['SERVER_NAME'] != 'www.example.com'}
is a hash of options for this rewrite rule. In this case it only has one option named if
. The option's value is a lambda function: ->(env){env['SERVER_NAME'] != 'www.example.com'}
. The gem will call this lambda for each request. It will pass a hash of all environment variables to it as a parameter. (I called the parameter env
but the name can be any.)
The lambda reads from it the domain name that the client used to make a request to the site: env['SERVER_NAME']
. It checks if the domain is the right one.
true
if the domain is incorrect. In this case, and in this case only, will the gem rewrite the URL and return status 301 to the client. false
if the domain is the right one. In this case, no action will be taken and the request will "fall through" to the application (to the other middlewares).Upvotes: 0
Reputation: 7043
example.com/products/12 => www.example.com/products/12
In order to tackle this problem with Heroku I had to set up my domain hoster's setting correctly. What you are looking for is called Forwarding. Next, you want to enable the 'keep relative path' option.
So, look for:
This should all be available on your domain registrar's level.
Upvotes: 0