Sails 允許您在您的 config/routes.js 檔案中,以幾種不同的方式明確地路由 URL。每個路由設定都包含一個位址和一個目標,例如
'GET /foo/bar': 'UserController.subscribe'
^^^address^^^ ^^^^^^^^^^target^^^^^^^^^^
路由位址指示應該比對哪個 URL,以套用目標所定義的處理常式和選項。路由包含一個選用的動詞和一個必要的路徑
'POST /foo/bar'
^verb^ ^^path^^
如果未指定動詞,路由將比對任何 CRUD 方法 (GET、PUT、POST、DELETE 或 PATCH)。如果指定 ALL
作為動詞,路由將比對任何方法。
請注意路徑中開頭的 /
-- 所有路徑都應該以它開頭才能正常運作。
除了指定像 foo/bar 這樣的靜態路徑,您可以使用 *
作為萬用字元
'/*'
將比對所有路徑,而
'/user/foo/*'
將比對開頭為 /user/foo 的所有路徑。
注意: 當使用帶有萬用字元的路由時,例如
'/*'
,請注意這也會比對對靜態資源 (即/js/dependencies/sails.io.js
) 的請求並覆蓋它們。為了防止這種情況,請考慮使用 下方描述 的skipAssets
選項。
若要在 現代 Sails 動作 中接收與此萬用字元 (*
) 對應的執行階段值,請在您的動作定義的頂層使用 urlWildcardSuffix
來指示您想要用來表示動態值的輸入名稱
urlWildcardSuffix: 'template',
inputs: {
template: {
description: 'The relative path to an EJS template within our `views/emails/` folder -- WITHOUT the file extension.',
extendedDescription: 'Use strings like "foo" or "foo/bar", but NEVER "foo/bar.ejs" or "/foo/bar". For example, '+
'"internal/email-contact-form" would send an email using the "views/emails/internal/email-contact-form.ejs" template.',
example: 'email-reset-password',
type: 'string',
required: true
},
},
fn: async function({ template }) {
// …
}
- 或者,在傳統的 (req,res) 動作中,您可以使用
req.param('0')
來存取路由 URL 萬用字元後綴 (*
) 的動態值。- 如需更多背景資訊,請參閱 https://www.npmjs.com/package/machine-as-action
另一種捕捉位址部分的方法是使用模式變數。這讓路由透過使用 :paramName
模式變數語法而不是 *
,來比對從不包含任何 /
字元的特殊命名參數
'/user/foo/bar/:name'
或者,對於選用的路徑參數,在模式變數的末尾添加 ?
'/user/foo/bar/:name?'
這將比對與 /user/foo/bar/*
幾乎相同的請求,但會將路由 URL 動態部分的數值作為參數值提供給路由處理常式 (例如 req.param('name')
)。
請注意,萬用字元 (
*
) 語法比對斜線,而 URL 模式變數 (:
) 語法則不比對。所以在上面的範例中,給定路由位址GET /user/foo/bar/*
,帶有像/user/foo/bar/baz/bing/bong/bang
這樣 URL 的傳入請求將會比對 (然而,如果您使用:name
語法,相同的 URL 將不會比對。)
模式變數的常見用例是設計網址別名或 虛名 URL。例如,考慮 Github 上儲存庫的 URL,http://www.github.com/balderdashy/sails
。在 Sails 中,我們可能會在我們的 config/routes.js
檔案底部定義這個路由,如下所示
'get /:account/:repo': {
controller: 'RepoController',
action: 'show',
skipAssets: true
}
在您的 RepoController
的 show
動作中,我們將使用 req.param('account')
和 req.param('repo')
來查找適當儲存庫的資料,然後將其作為 locals 傳遞到適當的 視圖。skipAssets
選項確保虛名路由不會意外地比對到我們的任何 資源 (例如 /images/logo.png
),因此它們仍然可以存取。
除了萬用字元位址語法之外,您也可以使用正規表示式來定義路由應該比對的 URL。使用正規表示式定義位址的語法是
'r|<正規表示式字串>|<逗號分隔的參數名稱列表>'
那是字母 "r",後面跟著一個管道字元 |
,一個不帶分隔符號的正規表示式字串,另一個管道,以及應該對應到正規表示式中括號群組的參數名稱列表。例如
'r|^/\\d+/(\\w+)/(\\w+)$|foo,bar": "message/my-action'
將比對 /123/abc/def
,執行 api/controllers/message/my-action.js 中的動作,並分別提供數值 abc
和 def
作為 req.param('foo')
和 req.param('bar')
。
請注意 \\d
和 \\w
中的雙反斜線;這種跳脫對於正規表示式正常運作是必要的!
雖然您可以隨意以任何順序將項目添加到您的 config/routes.js 檔案中,但請注意 Sails 會在內部按包含性對您的路由進行排序,包含性衡量一個位址可以處理多少潛在請求。一般來說,不包含動態元件的位址路由將首先比對,其次是帶有動態參數的路由,然後是帶有萬用字元的路由。這可以防止路由彼此封鎖 (例如,如果 /*
路由保留在列表的頂部,它將回應所有請求,並且永遠不會比對到其他路由)。
如果您有任何 正規表示式位址,它們將保留在您指定的順序中。例如,如果您的 config/routes.js 檔案包含一個 GET /foo/bar
路由,然後是一個 GET r|^/foo/\\d+$|
路由,則第二個路由將始終被排序為緊跟在 GET /foo/bar
之後出現。這是由於極難確定正規表示式路由的包含性。在指定這些路由時,請注意對它們進行排序,使其比對的請求不會超出預期。
自訂路由的位址部分指定路由應比對哪些 URL。目標部分指定 Sails 在比對成功後應執行的操作。目標可以採用幾種不同的形式。在某些情況下,您可能希望透過將多個目標放在陣列中,將它們鏈結到單個位址,但在大多數情況下,每個位址將只有一個目標。下面討論不同類型的目標,然後討論可以應用於它們的各種選項。
此語法將路由繫結到 控制器檔案 中的動作。以下四個路由是等效的
'GET /foo/go': 'FooController.myGoAction',
'GET /foo/go': 'foo.myGoAction',
'GET /foo/go': { controller: 'foo', action: 'myGoAction' },
'GET /foo/go': { controller: 'FooController', action:'myGoAction' },
每一個都將 GET /foo/go
對應到 api/controllers/FooController.js 中控制器的 myGoAction
動作,或對應到 api/controllers/foo/mygoaction.js 中控制器的動作。如果不存在這樣的控制器或動作,Sails 將輸出錯誤訊息並忽略該路由。否則,每當向 /foo/go 發出 GET 請求時,將執行該動作中的程式碼。
此語法中的控制器和動作名稱不區分大小寫。
此語法將位址繫結到 獨立 Sails 動作。只需指定動作的路徑 (相對於 api/controllers
)
'GET /': { action: 'index' }, // Use the action in api/controllers/index.js
'GET /foo/go': { action: 'foo/go-action' } // Use the action in api/controllers/foo/go-action.js OR
// the "go-action" action in api/controllers/FooController.js
'GET /bar/go': 'foo/go-action' // Binds to the same action as above, using shorthand notation
藍圖 API 為您的每個模型添加了幾個動作,所有這些動作都可用於路由。例如,如果您在 api/models/User.js
中定義了一個模型,您將自動能夠執行
'GET /foo/go': 'user/find' // Return a list of users
或
'GET /foo/go': 'UserController.find' // Same as above
如果您在 api/controllers/user/find.js
或 api/controllers/UserController.js
中有一個自訂動作,則將執行該動作,而不是預設的藍圖 find
。如需為您的模型提供的動作的完整列表,請參閱 藍圖 API 參考。
另一個常見的目標是將路由繫結到 視圖 的目標。這對於將靜態視圖繫結到自訂 URL 特別有用,並且這是新專案的預設首頁設定方式。
視圖目標的語法很簡單:它只是視圖檔案的路徑,不帶檔案擴展名 (例如 .ejs
),並且相對於 views/ 資料夾
'GET /team': { view: 'brochure/about' }
這告訴 Sails 透過提供位於 views/brochure/about.ejs
的視圖範本來處理對 /team
的 GET
請求 (假設使用了預設的 EJS 範本引擎)。只要該視圖檔案存在,對 /home 的 GET 請求就會顯示它。為了與 Express/consolidate 保持一致,如果指定的相對路徑與視圖檔案不符,則 Sails 將尋找具有相同名稱的子資料夾 (例如 pages/brochure
),並提供該子資料夾中的 "index" 視圖 (例如 pages/brochure/index.ejs
),如果存在。
請注意,由於此路由直接繫結到視圖,因此不會套用您設定的任何政策。如果您需要設定政策,請從控制器動作中使用
res.view()
。如需更多背景資訊,請參閱 此 StackOverflow 問題。
您可以讓一個位址重新導向到另一個位址,無論是在您的 Sails 應用程式內還是在完全不同的伺服器上。只需將重新導向 URL 指定為字串即可完成此操作
'/alias' : '/some/other/route/url',
'GET /google': 'http://www.google.com'
在 Sails 應用程式內重新導向時,請小心避免重新導向迴圈!
請注意,重新導向時,原始請求的 HTTP 方法 (以及任何額外的標頭/參數) 很可能會遺失,並且請求將轉換為簡單的 GET 請求。在上面的範例中,對 /alias 的 POST 請求將導致對 /some/other/route 的 GET 請求。這在某種程度上取決於瀏覽器的行為,但不建議您期望請求方法和其他資料在重新導向後仍然存在。
您可以使用此語法將位址直接對應到預設或自訂的 回應
'/foo': { response: 'notFound' }
只需在您的 api/responses 資料夾中指定回應檔案的名稱,不帶 .js 擴展名。此語法中的回應名稱區分大小寫。如果您嘗試將路由繫結到不存在的回應,Sails 將輸出錯誤並忽略該路由。
在大多數情況下,您將希望使用 config/policies.js 設定檔將 政策 應用於您的控制器動作。但是,在某些情況下,您會希望將政策直接應用於自訂路由,特別是當您使用 視圖 目標語法時。政策目標語法為
'/foo': { policy: 'my-policy' }
請注意,您始終希望使用陣列將政策鏈結到至少另一種類型的目標
'/foo': [
{ policy: 'my-policy' },
{ view: 'dashboard' }
]
這將把 my-policy 政策應用於路由,如果通過,則繼續顯示 views/dashboard.ejs 視圖。
對於一次性工作 (例如快速測試),您可以將路由直接指派給函數
'/foo': function(req, res) {
return res.send('hello!');
},
您也可以使用陣列將此語法與其他語法結合使用。這允許您定義快速的內聯中間件
'/foo': [
function(req, res, next) {
sails.log('Quick and dirty test:', req.allParams());
return next();
},
{ controller: 'user', action: 'find' }
],
您也可以使用帶有 fn
鍵的字典來指派函數。這允許您同時指定 其他路由目標選項
'GET /*': {
skipAssets: true,
fn: function(req, res) {
return res.send('hello!');
}
},
最佳實務是僅將函數語法用於臨時路由,因為這樣做違背了使 Sails 有用的結構慣例! (此外,您的 routes.js 檔案越不雜亂越好。)
除了上面各種路由目標語法中討論的選項之外,添加到路由目標物件的任何其他屬性都將透過 req.options
物件傳遞到路由處理常式。有幾個保留屬性可用於影響路由處理常式的行為。這些屬性在下表中列出。
屬性 | 適用目標類型 | 資料類型 | 詳細資訊 |
---|---|---|---|
skipAssets |
全部 | 如果您不希望路由比對帶有點的 URL (例如 myImage.jpg),則設定為 true 。這將使您的帶有 萬用字元表示法 的路由不會比對靜態資源的 URL。在建立 URL 網址別名 時很有用。 |
|
skipRegex |
全部 | 如果跳過每個包含點的 URL 過於寬鬆,或者您需要根據完全不同的條件跳過路由的處理常式,則可以使用 skipRegex 。此選項允許您指定一個正規表示式或正規表示式陣列來比對請求 URL;如果任何比對成功,則會跳過處理常式。請注意,與使用正規表示式繫結處理常式的語法不同,skipRegex 期望實際的 RegExp 物件,而不是字串。 |
|
locals |
控制器、視圖、藍圖、回應 | 設定預設的 本地變數,以傳遞給在處理請求時呈現的任何視圖。 | |
cors |
全部 | 指定如何處理來自不同來源的此路由的請求。有關更多資訊,請參閱 主要 CORS 文件。 | |
csrf |
全部 | 指示是否應保護路由,要求在請求中傳遞 CSRF 令牌。有關更多資訊,請參閱 主要 CSRF 文件。 | |
parseBlueprintOptions |
藍圖 | 提供此函數以覆蓋藍圖動作的預設行為 (包括搜尋條件、skip、limit、sort 和 population)。有關更多資訊,請參閱 藍圖設定參考。 |