2014-03-05 23 views
0

是否有可能與expressjs有多個路由調用相同的資源,這樣的事情:多種途徑與型動物參數,可以調用相同的ressource

app.get('/users/:user_id', users.getOne) 
app.get('/users/:username', users.getOne) 

我想能夠調用users.getOne爲準在獲取請求中使用params(:user_id或:username)。

在users.getOne函數中,如何確定使用哪一個並根據它構建我的查詢?

exports.getOne = function(req, res){ 

    var queryParams = ? // I need help here 

    Users 
    .find(queryParams) 
    ... 

謝謝!

可能相關:express.js - single routing handler for multiple routes in a single line

+0

如果某人選擇與您的某個用戶ID衝突的用戶名,該怎麼辦? – loganfsmyth

+0

用戶名限制爲16個字符。而user_id是mongoDB生成的散列願望是24個字符。 – inwpitrust

回答

1

那些實際上,從明確的觀點,同樣的路線。

不,他們不是。一條路線有:user_id參數,另一條路線有:username

這將是一個妥善的解決辦法:

var OBJECT_ID_RE = /^[a-f\d]{24}$/i; 

app.param('user_id', function(req, res, next, value, name) { 
    if (OBJECT_ID_RE.test(value)) { 
    next() 
    } else { 
    next('route') 
    } 
}) 

app.get('/users/:user_id', users.getOne) 
app.get('/users/:username', users.getOne) 

app.param設定的路線被稱爲先決條件。這樣當user_id匹配一個模式時,第一個路由被調用,否則第二個。

+0

好的,澄清一下,他們都匹配相同的URL,因此需要'next('route')'這是一種代碼味道,可能你試圖過分喜歡你的路由。我不喜歡幻想路由。我喜歡簡單,明顯,非魔術,易於調試的路由。這就是說,你的解決方案對於快車來說確實是很好的慣用語。 –

+0

'next('route')'是忽略中間件中特定路由的標準方式。唯一的缺點是調用取決於順序,但它可以很容易地修復。 – alex

4

從明確的觀點,這兩個路線將匹配同一組的請求的URL。你只需要其中的一個,你可以將其命名更有意義:

app.get('/users/:key', users.getOne); 

//... 
// http://stackoverflow.com/a/20988824/266795 
var OBJECT_ID_RE = /^[a-f\d]{24}$/i; 
exports.getOne = function(req, res) { 
    var conditions = {_id: req.params.key}; 
    if (!OBJECT_ID_RE.test(req.params.key)) { 
    conditions = {username: req.params.key}; 
    } 
    Users.find(conditions)... 

如果你最終整個代碼庫想在很多航線這種模式,你可以提取它變成一個/users/:user PARAM和使用app.param作爲per @ alex的答案,但封裝代碼以定位用戶並將其粘貼到req.user,以便實際的路由處理程序可以假定用戶在執行時已正確找到並加載,並且404處理也可以集中處理。

+0

感謝您的解決方案,它的工作,但我想知道是否存在一個完全不同的解決方法。我的意思是,首先,我是否以正確的方式處理問題?這是一個想法嗎?如果你想達到這樣的目標,你會怎麼做? – inwpitrust

+0

@inwpitrust否,兩次創建完全相同的路線不是正確的方法。彼得展示了一個好方法。 – MikeSmithDev

+0

是的,不,我的意思是,忘記我的代碼,但是在設計RESTful API時,是否可以解決這個問題?通過以下方式檢索用戶數據:id或:username,您認爲我應該啓用此功能嗎? – inwpitrust