快递空 req.params 路线到上一条路线
Express empty req.params route to the previous route
假设我有以下 REST 端点
/api/companies
/api/companies/:id
/api/companies/name/:slug
第一个路由 /api/companies
POST 将 post 一个新公司,而 GET 将获取所有公司的列表。
第二条路线 /api/companies/:id
GET 将通过其 id
获取该特定公司,PUT 将更新它,DELETE 将其删除。
第三条路线/api/companies/name/:slug
将获取以name
开头的公司列表。
我的 router.js
文件看起来像这样
// /api/companies
router
.route('/')
.post(controllers.createCompany)
.get(controllers.getByPriority)
// /api/companies/:id
router
.route('/:id')
.put(controllers.updateOne)
.delete(controllers.removeOne)
.get(controllers.getOne)
// /api/companies/name/:slug
router
.route('/name/:slug?')
.get(controllers.getByName)
问题是如果第三条路由中没有slug
参数,它将与第二条路由匹配,这将return投射错误。
例如:GET /api/companies/name/
return出现以下错误
CastError: Cast to ObjectId failed for value "name" (type string) at path "_id" for model "company"
at model.Query.exec (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\query.js:4545:21)
at D:\Projects\StackInfo\stack-info\backend\dist\utils\crud.js:91:15
at Layer.handle [as handle_request] (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\layer.js:95:5)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:137:13)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14) {
messageFormat: undefined,
stringValue: '"name"',
kind: 'ObjectId',
value: 'name',
path: '_id',
reason: TypeError: Argument passed in must be a Buffer or string of 12 bytes or a string of 24 hex characters
at new BSONTypeError (D:\Projects\StackInfo\stack-info\backend\node_modules\bson\lib\error.js:39:42)
at new ObjectId (D:\Projects\StackInfo\stack-info\backend\node_modules\bson\lib\objectid.js:62:23)
at castObjectId (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\cast\objectid.js:25:12)
at ObjectId.cast (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\schema\objectid.js:245:12)
at ObjectId.SchemaType.applySetters (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\schematype.js:1135:12)
at ObjectId.SchemaType._castForQuery (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\schematype.js:1567:15)
at ObjectId.SchemaType.castForQuery (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\schematype.js:1557:15)
at ObjectId.SchemaType.castForQueryWrapper (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\schematype.js:1534:20)
at cast (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\cast.js:336:32)
at model.Query.Query.cast (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\query.js:4968:12),
valueType: 'string'
}
crud.js
getOne 看起来也是这样
export const getOne = model => async (req, res) => {
try {
const id = req.params.id
const doc = await model
.findOne({ _id: id })
.lean().exec() // Where the error exists
if (!doc) {
return res.status(404).end()
}
res.status(200).json({ data: doc })
} catch (e) {
console.error(e)
res.status(400).end()
}
}
我尝试添加其他路由,以便在没有传递 slug
的情况下处理请求
// /api/companies
router
.route('/')
.post(controllers.createCompany)
.get(controllers.getByPriority)
// /api/companies/:id
router
.route('/:id')
.put(controllers.updateOne)
.delete(controllers.removeOne)
.get(controllers.getOne)
// in case /api/companies/name/:slug did not match
router
.route('/name')
.get(controllers.getByPriority)
// /api/companies/name/:slug
router
.route('/name/:slug?')
.get(controllers.getByName)
但它仍然与 /api/companies/:id
路由匹配并且 return 出现相同的错误。那么,当我在 /api/companies/name/
上请求时,即使参数为空,是否有任何解决方案可以避免使用 /api/companies/:id
进行路由?
从上到下表达执行代码。所以你可以在代码中颠倒端点的顺序。由于/name/:slug
比较具体,所以在/:id
之前定义:
router
.route('/')
.post(controllers.createCompany)
.get(controllers.getByPriority)
router
.route('/name/:slug?')
.get(controllers.getByName)
router
.route('/:id')
.put(controllers.updateOne)
.delete(controllers.removeOne)
.get(controllers.getOne)
假设我有以下 REST 端点
/api/companies
/api/companies/:id
/api/companies/name/:slug
第一个路由 /api/companies
POST 将 post 一个新公司,而 GET 将获取所有公司的列表。
第二条路线 /api/companies/:id
GET 将通过其 id
获取该特定公司,PUT 将更新它,DELETE 将其删除。
第三条路线/api/companies/name/:slug
将获取以name
开头的公司列表。
我的 router.js
文件看起来像这样
// /api/companies
router
.route('/')
.post(controllers.createCompany)
.get(controllers.getByPriority)
// /api/companies/:id
router
.route('/:id')
.put(controllers.updateOne)
.delete(controllers.removeOne)
.get(controllers.getOne)
// /api/companies/name/:slug
router
.route('/name/:slug?')
.get(controllers.getByName)
问题是如果第三条路由中没有slug
参数,它将与第二条路由匹配,这将return投射错误。
例如:GET /api/companies/name/
return出现以下错误
CastError: Cast to ObjectId failed for value "name" (type string) at path "_id" for model "company"
at model.Query.exec (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\query.js:4545:21)
at D:\Projects\StackInfo\stack-info\backend\dist\utils\crud.js:91:15
at Layer.handle [as handle_request] (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\layer.js:95:5)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:137:13)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14)
at next (D:\Projects\StackInfo\stack-info\backend\node_modules\express\lib\router\route.js:131:14) {
messageFormat: undefined,
stringValue: '"name"',
kind: 'ObjectId',
value: 'name',
path: '_id',
reason: TypeError: Argument passed in must be a Buffer or string of 12 bytes or a string of 24 hex characters
at new BSONTypeError (D:\Projects\StackInfo\stack-info\backend\node_modules\bson\lib\error.js:39:42)
at new ObjectId (D:\Projects\StackInfo\stack-info\backend\node_modules\bson\lib\objectid.js:62:23)
at castObjectId (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\cast\objectid.js:25:12)
at ObjectId.cast (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\schema\objectid.js:245:12)
at ObjectId.SchemaType.applySetters (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\schematype.js:1135:12)
at ObjectId.SchemaType._castForQuery (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\schematype.js:1567:15)
at ObjectId.SchemaType.castForQuery (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\schematype.js:1557:15)
at ObjectId.SchemaType.castForQueryWrapper (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\schematype.js:1534:20)
at cast (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\cast.js:336:32)
at model.Query.Query.cast (D:\Projects\StackInfo\stack-info\backend\node_modules\mongoose\lib\query.js:4968:12),
valueType: 'string'
}
crud.js
getOne 看起来也是这样
export const getOne = model => async (req, res) => {
try {
const id = req.params.id
const doc = await model
.findOne({ _id: id })
.lean().exec() // Where the error exists
if (!doc) {
return res.status(404).end()
}
res.status(200).json({ data: doc })
} catch (e) {
console.error(e)
res.status(400).end()
}
}
我尝试添加其他路由,以便在没有传递 slug
的情况下处理请求
// /api/companies
router
.route('/')
.post(controllers.createCompany)
.get(controllers.getByPriority)
// /api/companies/:id
router
.route('/:id')
.put(controllers.updateOne)
.delete(controllers.removeOne)
.get(controllers.getOne)
// in case /api/companies/name/:slug did not match
router
.route('/name')
.get(controllers.getByPriority)
// /api/companies/name/:slug
router
.route('/name/:slug?')
.get(controllers.getByName)
但它仍然与 /api/companies/:id
路由匹配并且 return 出现相同的错误。那么,当我在 /api/companies/name/
上请求时,即使参数为空,是否有任何解决方案可以避免使用 /api/companies/:id
进行路由?
从上到下表达执行代码。所以你可以在代码中颠倒端点的顺序。由于/name/:slug
比较具体,所以在/:id
之前定义:
router
.route('/')
.post(controllers.createCompany)
.get(controllers.getByPriority)
router
.route('/name/:slug?')
.get(controllers.getByName)
router
.route('/:id')
.put(controllers.updateOne)
.delete(controllers.removeOne)
.get(controllers.getOne)