使用Swagger编写Nodejs API文档

138 阅读3分钟

什么是API?

API文档是一本技术手册,包含有关如何使用API的信息。文档还描述了API在请求中期望的数据格式以及返回的格式。

为什么我们需要API文档?

与每项技术一样,必须有一个指南来帮助其他人了解如何使用它。API文档可以帮助人们了解可以执行什么类型的操作。

今天,我们将重点介绍如何创建一个简单的REST API,并与swagger与Open API 3.0规范集成在一起。我们的文档将以图形形式提供,可通过浏览器访问。

在这个例子中,我们将使用nodejs和express。

我们的API文档将包括哪些内容?

让我们开始吧!

├── controllers
│   └── hero.controller.js
├── index.js
├── package.json
├── routes
│   ├── hero.routes.js
│   └── index.js
└── swagger.js
npm install express swagger-jsdoc swagger-ui-express

在package.json中,我们将添加:

"type":"module"

启用ES6模块。

index.js中,我们创建基本的express应用程序并导入swagger配置。

import express from 'express'
import router from './routes/index.js'
import swaggerDocs from './swagger.js'

const app = express()
const port = 5000

app.use(express.json())
app.use(router)

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
  swaggerDocs(app, port)
})

swagger.js中的配置:

import swaggerJsdoc from 'swagger-jsdoc'
import swaggerUi from 'swagger-ui-express'

const options = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: 'Hero API',
      description: 'Example of CRUD API ',
      version: '1.0.0',
    },
  },
  // looks for configuration in specified directories
  apis: ['./routes/*.js'],
}

const swaggerSpec = swaggerJsdoc(options)

function swaggerDocs(app, port) {
  // Swagger Page
  app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec))

  // Documentation in JSON format
  app.get('/docs.json', (req, res) => {
    res.setHeader('Content-Type', 'application/json')
    res.send(swaggerSpec)
  })
}

export default swaggerDocs

为了更好的可访问性和可读性,我们将把文档放在路由之上。

mkdir routes cd routes
import express from 'express'
import heroRoutes from './hero.routes.js'
const router = express.Router()

/**
 * @openapi
 * /healthcheck:
 *  get:
 *     tags:
 *     - Healthcheck
 *     description: Returns API operational status
 *     responses:
 *       200:
 *         description: API is  running
 */
router.get('/healthcheck', (req, res) => res.sendStatus(200))

router.use(heroRoutes)

export default route

对于每个请求,我们将编写规范,让API用户知道我们的API期望什么类型的输入,以及它返回格式。

import express from 'express'
import {
  getHeroesHandler,
  addHeroHandler,
  deleteHeroHandler,
  editHeroHandler,
} from '../controllers/hero.controller.js'

const router = express.Router()

/**
 * @openapi
 * '/api/heroes':
 *  get:
 *     tags:
 *     - Hero
 *     summary: Get all heroes
 *     responses:
 *       200:
 *         description: Success
 *         content:
 *          application/json:
 *            schema:
 *              type: array
 *              items:
 *                type: object
 *                properties:
 *                  id:
 *                    type: number
 *                  name:
 *                    type: string
 *       400:
 *         description: Bad request
 */

router.get('/api/heroes', getHeroesHandler)

/**
 * @openapi
 * '/api/hero':
 *  post:
 *     tags:
 *     - Hero
 *     summary: Create a hero
 *     requestBody:
 *      required: true
 *      content:
 *        application/json:
 *           schema:
 *            type: object
 *            required:
 *              - id
 *              - name
 *            properties:
 *              id:
 *                type: number
 *                default: 2
 *              name:
 *                type: string
 *                default: New Hero Name
 *     responses:
 *      201:
 *        description: Created
 *      409:
 *        description: Conflict
 *      404:
 *        description: Not Found
 */
router.post('/api/hero', addHeroHandler)

/**
 * @openapi
 * '/api/hero':
 *  put:
 *     tags:
 *     - Hero
 *     summary: Modify a hero
 *     requestBody:
 *      required: true
 *      content:
 *        application/json:
 *           schema:
 *            type: object
 *            required:
 *              - id
 *              - name
 *            properties:
 *              id:
 *                type: number
 *                default: 1
 *              name:
 *                type: string
 *                default: Hulk
 *     responses:
 *      200:
 *        description: Modified
 *      400:
 *        description: Bad Request
 *      404:
 *        description: Not Found
 */
router.put('/api/hero', editHeroHandler)

/**
 * @openapi
 * '/api/hero/{id}':
 *  delete:
 *     tags:
 *     - Hero
 *     summary: Remove hero by id
 *     parameters:
 *      - name: id
 *        in: path
 *        description: The unique id of the hero
 *        required: true
 *     responses:
 *      200:
 *        description: Removed
 *      400:
 *        description: Bad request
 *      404:
 *        description: Not Found
 */
router.delete('/api/hero/:id', deleteHeroHandler)

export default router

接下来,我们将创建负责处理返回数据的函数。

hero_controler.js

let heroes = [
  {
    id: 1,
    name: 'Batman',
  },
  { id: 2, name: 'Spiderman' },
]

export async function getHeroesHandler(req, res) {
  res.status(200).json(heroes)
}

export async function addHeroHandler(req, res) {
  if (heroes.find((hero) => hero.id === req.body.id)) {
    res.status(409).json('Hero id must be unique')
  }
  else{
    heroes.push(req.body)
    res.status(200).json(heroes)
  }
}

export async function deleteHeroHandler(req, res) {
  const index = heroes.findIndex((hero) => hero.id == req.params.id)
  if (index >= 0) {
    heroes.splice(index, 1)
    res.status(200).json(heroes)
  } else res.status(400).send()
}

export async function editHeroHandler(req, res) {
  const index = heroes.findIndex((hero) => hero.id == req.body.id)
  if (index >= 0) {
    heroes.splice(index, 1, req.body)
    res.status(200).json(heroes)
  } else res.status(400).send()

现在,我们可以使用node index.js启动。

导航到localhost:4000/docs查看我们的文档,或者我们从localhost:4000/docs.json获取JSON格式。

总之,这只是一个简单的例子,演示如何在express应用程序中使用swagger和OpenAPI 3.0。我认为swagger是一个很好的工具,因为它可以帮助我们创建清晰整洁的文档,为用户提供一个优秀的可视化页面,让他们可以快速地测试API功能。

代码:github.com/przpiw/CRUD…

原文: <dev.to/przpiw/docu…