如何使用Rails 3 / Rack不使用www进行redirect?

我知道有很多问题可以回答这个问题。 我熟悉.htaccessnginx.conf方法,但是我不能在heroku上使用这种传统的configuration方法。

Simone Carletti给出了利用Rails 2.x Metals的答案,但我使用的是Rails 3 ,这不兼容。 将非www请求redirect到Rails中的www urls

请注意:

我不是在我的ApplicationController中寻找一个简单的before_filter 。 我想完成类似于Simone的重写。 我相信这是最起码的Web服务器或中间件的工作,所以我想离开这个实际的应用程序代码。

目标

 redirect to status ---------------------------------------------------- www.foo.com foo.com 301 www.foo.com/whatever foo.com/whatever 301 

只有匹配/^www\./主机应该redirect。 所有其他请求应该被忽略。

Rails 4中删除www。 从任何URL,同时保持path名可以简单地通过使用:

 # config/routes.rb constraints subdomain: 'www' do get ':any', to: redirect(subdomain: nil, path: '/%{any}'), any: /.*/ end 

相反,添加www。 到任何尚未有它的URL的开始可以通过以下方式实现:

 # config/routes.rb constraints subdomain: false do get ':any', to: redirect(subdomain: 'www', path: '/%{any}'), any: /.*/ end 

如果您使用Rails 3,还有更好的方法。只要利用路由迷人的优势。

 Foo::Application.routes.draw do constraints(:host => /^example.com/) do root :to => redirect("http://www.example.com") match '/*path', :to => redirect {|params| "http://www.example.com/#{params[:path]}"} end end 

我真的很喜欢使用Rails路由器这样的事情。 以前的答案是好的,但我想要的东西,我可以使用任何以“www”开头的url的通用目的。

我认为这是一个很好的解决scheme:

 constraints(:host => /^www\./) do match "(*x)" => redirect { |params, request| URI.parse(request.url).tap {|url| url.host.sub!('www.', '') }.to_s } end 

看看这个中间件,它应该做你想要的:

http://github.com/iSabanin/www_ditcher

让我知道,如果这对你有用。

杜克解决scheme的单行版本。 只需添加到routes.rb的顶部

 match '(*any)' => redirect { |p, req| req.url.sub('www.', '') }, :constraints => { :host => /^www\./ } 

在Rails 3中

 #config/routes.rb Example::Application.routes.draw do constraints(:host => "www.example.net") do match "(*x)" => redirect { |params, request| URI.parse(request.url).tap { |x| x.host = "example.net" }.to_s } end # .... # .. more routes .. # .... end 

如果您要从顶级域名(TLD)redirect到www子域名,请使用以下代码:

 constraints :subdomain => '' do match '(*any)' => redirect { |p, req| req.url.sub('//', '//www.') } end 

注意:这段代码使用的是sub,而不是gsub,因为sub会replace第一次出现的双斜杠,其中gsub会replace所有的双斜杠。

对于Rails 4,上面的解决scheme必须附加动词结构,例如via: [:get, :post] 。 杜克的解决scheme变成:

  constraints(:host => /^www\./) do match "(*x)" => redirect { |params, request| URI.parse(request.url).tap {|url| url.host.sub!('www.', '') }.to_s }, via: [:get, :post] end 

上面的方法没有错,但也有一些提供Rack中间件的gem来做到这一点。

我喜欢他们保持这种行为与应用程序本身分开的方式,但这不是一个特别强烈的论点。 在使用Sinatra时,我也使用中间件来做到这一点,所以更喜欢使用一种技术,我可以使用Rails和/或Sinatra构build的应用程序(我经常运行embedded在Rails中的Nesta)。

无论如何,在这里他们是:

第一个更简单(和我一直使用),而第二个提供了更多的function(我还没有需要,但欣赏)。

Interesting Posts