如何使用Rails 3 / Rack不使用www进行redirect?
我知道有很多问题可以回答这个问题。 我熟悉.htaccess
和nginx.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
杜克解决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(我还没有需要,但欣赏)。