我在Chris的回答中提到您可以在server_name中使用通配符和正則表達式,並且這些將會傳遞給您的rails實例。
server_name *; # handle requests from all domains
有四種方法可以在你的Rails應用程序中使用它(我知道這一點)。
「內容的大包」方法
什麼都不做
如果你讓Nginx的把所有的域相同的Rails應用程序,他們都得到了相同的內容。在這種情況下,www.abc.com和www.xyz.com可以訪問相同的數據。這是最容易做到的,因爲你什麼都不做。
此解決方案的侷限性在於您希望讓域具有不同的內容。例如,如果www.abc.com/about和www.xyz.com/about應該是不同的頁面,那麼它就會變得棘手。
的「幕後的那個人」方法
使用的Nginx的「改寫」
在某些情況下,你可以讓Nginx的重寫域名成子域,並傳遞到您的Rails應用程序。例如:
server_name *; # handle requests from all domains
rewrite ^(?:www.)?([^.]*)\..*$ $1.yourdomain.com last;
該正則表達式需要一點解釋。它只是說從任何這些獲得xyz:www.xyz.com,xyz.com,xzy.co.uk,www.xyz.co.uk.重寫將這些請求中的任何一個更改爲xyz.yourdomain.com。
這樣做的好處是Nginx很快就做到了這一點,rails應用程序直到以後纔會涉及,並且請求的內容可以限制在子域。例如,Page.where(subdomain: request.subdomain, permalink: params[:permalink])
。
雖然這是相當嚴格的,因爲它意味着子域名和域名必須相同。也許這對你的應用程序來說是一個問題,可能不是。但是,儘管我在此子域中使用了$1
,但您可以輕鬆地將其作爲url中的參數插入。例如,yourdomain.com/$1
會將來自www.xyz.com的請求重寫到yourdomain.com/xyz。
此問題的另一個問題是「幕後男子」。雖然用戶訪問www.xyz.com重寫意味着他們會在地址欄中看到xyz.yourdomain.com。
的「Rails的路」法
在ApplicationController中
使用Rails的請求對象,你可以使用你的應用程序控制器範圍使用Rails的request
對象域名相關的內容。
在本例中,我們將使用ApplicationController來查找與域名關聯的用戶帳戶。假設你有一個用戶模型與domain_name
屬性:
def domain_user
@domain_user ||= User.where(domain_name: request.domain()).take
end
Redis的可用於如果附加命中你的數據庫中創建一個性能障礙緩存這些查找。到目前爲止,我的應用還沒有達到這一點。
這個解決方案的弱點是,雖然查找可能會發現www.xyz.com,它會錯過xyz.com。爲了適應這種情況,我們可以使用一些正則表達式:
def domain_user
request.domain.match /(?:www.)?(.*)/
@domain_user ||= User.where(domain_name: $1).take
end
這個正則表達式去掉www。如果它存在。剩下的就成了域名(我們在$1
裏爲我們存儲紅寶石)。
與Nginx重寫解決方案不同,如果用戶訪問www.xyz.com,那麼他們在地址欄中仍然可以看到。
使用路由約束
的「對我不起作用」法
另外,Rails的3及以上的有約束的,存在於產生路由表半動態的路由文件的功能。我說「半動態」,因爲路由表是在應用程序啓動時生成的。如果用戶模型(在我們的示例中)發生變化,則需要特別注意重建路由表。對於分佈在多個服務器上的應用程序,這可能難以管理,儘管people have done it。
到目前爲止,我的所有應用程序最終(如果不是最初的話)都使用ApplicationController解決方案,因爲它實際上是最乾淨和最容易實現的。從MCV的角度來看,這也很有意義。
+1設置多個別名並讓你的Rails應用程序檢測應執行哪一個檢查主機變量。 – 2010-09-01 19:18:28
感謝您的評論。 – Chamnap 2010-09-02 10:49:52
我們完全按照克里斯描述的方式完成了Simone的建議,並且它工作正常。 – pjmorse 2010-10-18 11:55:10