2010-10-28 59 views
37

我知道有很多問題可以回答這個問題。我熟悉.htaccessnginx.conf方法,但我不能在heroku上訪問這樣的傳統配置方法。如何使用Rails 3/Rack不使用www進行重定向?

Simone Carletti給出了這個答案,利用Rails 2.x金屬,但我使用Rails 3,這是不兼容的。 Redirect non-www requests to www urls in Rails

請注意:

我不希望在我的ApplicationController簡單before_filter。我想完成類似於Simone的重寫。我相信這是最起碼的web服務器或者中間件的工作,所以我想把這些東西留給實際的應用代碼。

目標

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

只有主機配套/^www\./應該重定向。所有其他請求應該被忽略。

+0

非常感謝:) – Robin 2011-11-14 14:53:32

+0

我不明白需要每種方法。我的中間件沒有它,它們像魅力一樣工作。 – radiospiel 2013-06-01 12:46:47

+0

啊,現在我看到:自我在重定向的情況下作爲響應主體返回,並且主體必須respond_to? :每。這可能不是規範的方式。我建議只是返回一個空字符串或[]作爲響應正文。 – radiospiel 2013-06-01 12:59:22

回答

50

軌道4,5去除WWW。從任何URL,同時維持路徑可以簡單地通過以下方式實現:

# config/routes.rb 

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

相比之下,加入萬維網。到任何網址的開始尚未有它可以實現:

# config/routes.rb 

constraints subdomain: false do 
    get ':any', to: redirect(subdomain: 'www', path: '/%{any}'), any: /.*/ 
end 
+0

標記此答案爲Rails 4用戶接受。如果您使用rails'<= 3',請參閱此主題中的其他答案。 – 2014-01-31 01:49:09

+0

這真是太棒了! – alexzg 2015-02-15 21:52:45

+2

我不確定它是否是我正在做的事情,但是當使用'constraints subdomain:false'時,它實際上由於某種原因會執行兩個重定向,最終會在'www.www.localhost:3000'中結束。在瀏覽器中,我可以看到它重定向了'localhost:3000' =>'www.localhost:3000' =>'www.www.localhost:3000' – 2015-09-10 17:17:43

7

在這個中間件看看,它應該做的正是你想要的東西:

http://github.com/iSabanin/www_ditcher

讓我知道這是否爲你工作。

+0

伊利亞,我將此視爲已被接受,但我想出了一個稍微更優雅/強大的解決方案。根據[Rack Spec](http://rack.rubyforge.org/doc/SPEC.html),「Body本身不應該是String的一個實例,因爲這將在Ruby 1.9中打破。」所以,我在這裏做了調整。另外,我正在使用Rack :: Request對象來處理URL並使代碼更清晰。 – 2010-10-29 08:59:13

13

如果您使用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 
+0

當www被指定時,我想在沒有** www的情況下重定向**。你能適應你的答案嗎?如果它有效,我會將其標記爲已接受。 :) – 2010-11-01 05:51:37

+1

是否有可能你可以使它不可知域?例如''#{params [:protocol]}://#{params [:host]} /#{params [:path]}''? – 2010-11-01 05:53:02

6

在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 
+0

鏈接已損壞。 – iamnotmaynard 2016-10-31 20:08:22

+0

@iamnotmaynard我的答案中有相關的代碼。 – 2016-11-02 16:27:44

12

我真的很喜歡使用Rails的路由器這樣的事情。以前的答案很好,但我想要一些通用的東西,我可以使用任何以「www」開頭的網址。

我認爲這是一個很好的解決方案:

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

公爵的解決方案的一個行版本。只需添加到routes.rb中的頂部

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

謝謝!你能不能讓另一個版本包含從onedomain.com到onedomain.net的重定向?如果兩個域共享相同的名稱,是否可以像req.url.sub('www。','')。sub('net','com')? – 2013-03-05 18:55:10

3

如果你想從頂級域名(TLD)到WWW子域名重定向,使用此代碼:

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

注:此代碼使用sub而不是gsub,因爲sub會替換第一次出現的雙斜槓,其中gsub將替換所有雙斜槓。

+0

答案與此問題相反,但非常有用 - 謝謝! – Troy 2012-07-23 23:22:16

2

上述方法沒有錯,但也有一些gem提供Rack中間件來做到這一點。

我喜歡他們保持這種行爲與應用程序本身分開的方式,但它不是一個特別強烈的論點。在使用Sinatra時,我也使用中間件來完成這項工作,所以更願意使用我可以在Rails和/或Sinatra構建的應用程序上使用的技術(我經常運行內嵌在Rails中的Nesta)。

無論如何,它們是:

第一個是簡單的(和一個我一直在使用),而第二提供了一些更多的功能(我還沒有需要,但感激)。

3

對於導軌4,上述解決方案必須附加動詞構造,例如, via: [:get, :post]。杜克大學的溶液變成:

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 
相關問題