如何使用 Swagger 3 将自定义中间件添加到 express-openapi-validator
How to add custom middleware to express-openapi-validator using Swagger 3
我有一个使用 express-openapi-validator 的节点应用程序,它采用 api 规范文件(这是一个 .yml 文件),具有请求和响应验证。 express-openapi-validator 包将请求路由到处理程序文件(在规范中定义)。这是其中一个处理程序的样子:
function getUsers(req, res) {
const { 'x-user-id': userId } = req.headers
res.status(200).json(`Your userId is ${userId}`)
}
我有一个 API 密钥功能,用户可以在其中获得一个新的 API 密钥,而其他端点则需要调用者拥有 API 密钥请求 headers 验证请求。
我知道应该可以使用中间件来验证请求,但我不知道如何在 select 端点上使用带有 express-openapi-validator 包的自定义中间件。
例如:
GET /apikey = 不需要 api key
GET /resource = 需要 api key
我该如何配置?
我的 app.js 中的 openapi 验证器代码如下所示:
new OpenApiValidator({
apiSpec,
validateResponses: true,
operationHandlers: path.join(__dirname, './handlers'),
})
.install(app)
.then(() => {
app.use((err, _, res) => {
res.status(err.status || 500).json({
message: err.message,
errors: err.errors,
});
});
});
我和你的情况相似,使用 OpenAPI/Swagger 这样的包限制了我为每个端点添加特定中间件的能力,所以我的解决方案是我创建了一个名为 @zishone/chaindler 的 npm 模块。
你可以这样使用它:
const { Chain } = require('@zishone/chaindler');
function getUsers(req, res) {
const { 'x-user-id': userId } = req.headers
res.status(200).json(`Your userId is ${userId}`)
}
function postUsers(req, res) {
// ...
}
function mw1(req, res, next) {
next()
}
function mw2(req, res, next) {
next()
}
module.exports = {
getUsers: new Chain(mw1, mw2).handle(getUsers),
postUsers: new Chain(mw1).handle(postUsers)
}
基本上它只是链接中间件,然后一个一个地调用它们,然后最后调用 handler/controller。
实际上我自己找到了解决方案。
首先,我使用的是 express-openapi-validator
的 4.10.5
版本,所以上面的代码略有不同。
这是现在的样子:
// index.js
app.use(
OpenApiValidator.middleware({
apiSpec,
validateResponses: true,
operationHandlers: path.join(__dirname, './handlers'),
validateSecurity: {
handlers: {
verifyApiKey(req, scopes) {
return middleware.verifyApiKey(req)
},
bearerAuth(req, scopes) {
return middleware.verifyToken(req)
}
}
},
}),
);
app.use((err, req, res, next) => {
res.status(err.status || 500).json({
message: err.message,
errors: err.errors,
});
我最终在路由中使用中间件的方式如下:
我在 swagger.yml 文件中添加了一个 securitySchemes
部分,如下所示:
components:
securitySchemes:
verifyApiKey:
type: apiKey
in: header
name: x-api-key
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
这里有更多关于它的信息:https://swagger.io/docs/specification/authentication/
在每条需要中间件的路由上,我添加了一个安全部分,如下所示:
/team:
post:
security:
- bearerAuth: []
description: Create a new team
operationId: createTeam
x-eov-operation-id: createTeam
x-eov-operation-handler: team
正如你在我上面的代码中看到的(在 index.js 文件中),我有一个 validateSecurity
键,一个 handlers
键,然后有相关键在我的 swagger.yml 中(verifyApiKey 和 bearerAuth)。这些函数获取请求和范围以检查它们是否有效。这些函数 return 一个布尔值,所以 true
意味着中间件让请求通过,而 false
意味着 403
响应将被 returned。
validateSecurity: {
handlers: {
verifyApiKey(req, scopes) {
return middleware.verifyApiKey(req)
},
bearerAuth(req, scopes) {
return middleware.verifyToken(req)
}
}
},
如果我在上面有任何错误,或者如果解释更清楚,请回复。如果您有任何问题,请在下方 post 提出。
您可以简单地传递处理程序数组,而不是像在 express 中那样只传递 1 个函数。
因此,在您的代码中,可能是 x-eov-operation-id 所指的 getUsers
函数将是 2 个函数的数组:
const getUsers = [
apiKeyMiddleware,
(req, res) => {
const { 'x-user-id': userId } = req.headers
res.status(200).json(`Your userId is ${userId}`)
}
];
我有一个使用 express-openapi-validator 的节点应用程序,它采用 api 规范文件(这是一个 .yml 文件),具有请求和响应验证。 express-openapi-validator 包将请求路由到处理程序文件(在规范中定义)。这是其中一个处理程序的样子:
function getUsers(req, res) {
const { 'x-user-id': userId } = req.headers
res.status(200).json(`Your userId is ${userId}`)
}
我有一个 API 密钥功能,用户可以在其中获得一个新的 API 密钥,而其他端点则需要调用者拥有 API 密钥请求 headers 验证请求。
我知道应该可以使用中间件来验证请求,但我不知道如何在 select 端点上使用带有 express-openapi-validator 包的自定义中间件。
例如:
GET /apikey = 不需要 api key GET /resource = 需要 api key
我该如何配置?
我的 app.js 中的 openapi 验证器代码如下所示:
new OpenApiValidator({
apiSpec,
validateResponses: true,
operationHandlers: path.join(__dirname, './handlers'),
})
.install(app)
.then(() => {
app.use((err, _, res) => {
res.status(err.status || 500).json({
message: err.message,
errors: err.errors,
});
});
});
我和你的情况相似,使用 OpenAPI/Swagger 这样的包限制了我为每个端点添加特定中间件的能力,所以我的解决方案是我创建了一个名为 @zishone/chaindler 的 npm 模块。
你可以这样使用它:
const { Chain } = require('@zishone/chaindler');
function getUsers(req, res) {
const { 'x-user-id': userId } = req.headers
res.status(200).json(`Your userId is ${userId}`)
}
function postUsers(req, res) {
// ...
}
function mw1(req, res, next) {
next()
}
function mw2(req, res, next) {
next()
}
module.exports = {
getUsers: new Chain(mw1, mw2).handle(getUsers),
postUsers: new Chain(mw1).handle(postUsers)
}
基本上它只是链接中间件,然后一个一个地调用它们,然后最后调用 handler/controller。
实际上我自己找到了解决方案。
首先,我使用的是 express-openapi-validator
的 4.10.5
版本,所以上面的代码略有不同。
这是现在的样子:
// index.js
app.use(
OpenApiValidator.middleware({
apiSpec,
validateResponses: true,
operationHandlers: path.join(__dirname, './handlers'),
validateSecurity: {
handlers: {
verifyApiKey(req, scopes) {
return middleware.verifyApiKey(req)
},
bearerAuth(req, scopes) {
return middleware.verifyToken(req)
}
}
},
}),
);
app.use((err, req, res, next) => {
res.status(err.status || 500).json({
message: err.message,
errors: err.errors,
});
我最终在路由中使用中间件的方式如下:
我在 swagger.yml 文件中添加了一个 securitySchemes
部分,如下所示:
components:
securitySchemes:
verifyApiKey:
type: apiKey
in: header
name: x-api-key
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
这里有更多关于它的信息:https://swagger.io/docs/specification/authentication/
在每条需要中间件的路由上,我添加了一个安全部分,如下所示:
/team:
post:
security:
- bearerAuth: []
description: Create a new team
operationId: createTeam
x-eov-operation-id: createTeam
x-eov-operation-handler: team
正如你在我上面的代码中看到的(在 index.js 文件中),我有一个 validateSecurity
键,一个 handlers
键,然后有相关键在我的 swagger.yml 中(verifyApiKey 和 bearerAuth)。这些函数获取请求和范围以检查它们是否有效。这些函数 return 一个布尔值,所以 true
意味着中间件让请求通过,而 false
意味着 403
响应将被 returned。
validateSecurity: {
handlers: {
verifyApiKey(req, scopes) {
return middleware.verifyApiKey(req)
},
bearerAuth(req, scopes) {
return middleware.verifyToken(req)
}
}
},
如果我在上面有任何错误,或者如果解释更清楚,请回复。如果您有任何问题,请在下方 post 提出。
您可以简单地传递处理程序数组,而不是像在 express 中那样只传递 1 个函数。
因此,在您的代码中,可能是 x-eov-operation-id 所指的 getUsers
函数将是 2 个函数的数组:
const getUsers = [
apiKeyMiddleware,
(req, res) => {
const { 'x-user-id': userId } = req.headers
res.status(200).json(`Your userId is ${userId}`)
}
];