Как добавить собственное промежуточное ПО в express-openapi-validator с помощью Swagger 3

У меня есть приложение Node с использованием 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 в заголовках запроса для проверки запроса.

Я знаю, что можно использовать промежуточное программное обеспечение для проверки запроса, но я не могу понять, как использовать настраиваемое промежуточное программное обеспечение с пакетом express-openapi-validator на выбранных конечных точках.

Например:

GET / apikey = не требует ключа api GET / resource = требуется ключ api

Как мне это настроить?

Вот как выглядит код валидатора openapi в моем app.js:

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,
      });
    });
  });

person nkhil    schedule 07.11.2020    source источник
comment
Вы можете использовать этот пакет для добавления промежуточного программного обеспечения swagger-routes-express   -  person Sabbiu Shah    schedule 09.11.2020


Ответы (3)


На самом деле я сам нашел решение для этого.

Прежде всего, я использую версию 4.10.5 из express-openapi-validator, поэтому приведенный выше код немного отличается.

Вот как это выглядит сейчас:

// 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,
    });

Ниже показано, как я использовал промежуточное ПО в своих маршрутах:

Я добавил раздел securitySchemes в свой файл swagger.yml, например:

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). Эти функции получают запрос и область действия, чтобы проверить, действительны ли они. Эти функции возвращают логическое значение, поэтому true означает, что промежуточное ПО пропускает запрос, а false означает, что будет возвращен ответ 403.

validateSecurity: {
        handlers: {
          verifyApiKey(req, scopes) {
            return middleware.verifyApiKey(req)
          },
          bearerAuth(req, scopes) {
            return middleware.verifyToken(req)
          }
        }
      },

Пожалуйста, ответьте, если у меня что-то не так, или если объяснение может быть более ясным. Если у вас есть вопросы, разместите их ниже.

person nkhil    schedule 28.01.2021

Вы можете просто передать массив обработчиков вместо одной функции, как в экспрессе. Итак, в вашем коде функция getUsers, на которую, вероятно, ссылается x-eov-operation-id, будет массивом из двух функций:

const getUsers = [
  apiKeyMiddleware,
  (req, res) => {
    const { 'x-user-id': userId } = req.headers
    res.status(200).json(`Your userId is ${userId}`)
  }
];
person Giorgi Mamatelashvili    schedule 18.02.2021

Я был в такой же ситуации, как и вы, использование подобных пакетов OpenAPI / Swagger ограничивало мою способность добавлять определенное промежуточное ПО для каждой конечной точки, поэтому моим решением было создание модуля npm под названием @ zishone / chaindler.

Вы можете использовать это так:

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)
}

В основном он просто связывает промежуточное ПО, затем вызывает их по одному, а затем вызывает обработчик / контроллер последним.

person zishone    schedule 26.01.2021
comment
Спасибо, я действительно нашел способ сделать это без использования каких-либо пакетов! - person nkhil; 28.01.2021