zoukankan      html  css  js  c++  java
  • 从零开始的野路子React/Node(7)将Swagger(OpenAPI)运用于后端API

    之前公司做项目是用过swagger来配置python模型的API,感觉非常好用。swagger可以提供request, response甚至error的验证机制,十分便利。node当然也可以用啦。

    我们需要使用的库主要是swagger-ui-express,它将提供swagger的相关功能以及一个UI,方便查看和调试。

    1、初始设定

    老规矩,我们还是通过express work_with_swagger来新建一个叫work_with_swagger的项目。然后依旧是删除bin文件夹,改改app.js以及将package.json中的start改为node app.js(当然,用nodemon会更好,可以安装npm install nodemon,然后将start改为nodemon app.js)。

    var express = require('express');
    
    var app = express();
    
    app.use(express.urlencoded({extended: true}));  //解析json用
    app.use(express.json()); //解析json用
    
    app.listen(5000, function() {
        console.log('App listening on port 5000...')
    });

    然后我们来做些设置:

    我们会有一个Controller来负责request -> response的逻辑。

    我们将原来的routes删掉,增加自己的路由Routes,对接到对应的controller。

    我们添加一个swagger文件夹,并在其中加入我们的配置文件swagger.yml。

    2、添加swagger-ui-express

    现在,我们需要改动一下app.js来把swagger配置文件包含进去。由于我们的swagger文件是yaml文件,所以我们需要yamljs库来读取它(默认只能读取json格式的swagger文件,直接抄https://www.npmjs.com/package/swagger-ui-express提供的方法)。

    此外,我们把路由文件也加入进去。

    var express = require('express');
    var swaggerUi = require('swagger-ui-express');
    var YAML = require('yamljs');
    
    const swaggerDocument = YAML.load('./swagger/swagger.yml');
    const RandomRouter = require('./Routes/RandomRouter');
    
    var app = express();
    
    app.use(express.urlencoded({extended: true}));  //解析json用
    app.use(express.json()); //解析json用
    app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
    app.use('/', RandomRouter)
    
    app.listen(5000, function() {
        console.log('App listening on port 5000...')
    });

    我们现在可以象征性地写几个controllers并把他们加入路由文件中,2个get,1个post:

    var express = require('express');
    var YAML = require('yamljs');
    
    exports.healthCheck = (req, res) => {
        const swaggerDocument = YAML.load('./swagger/swagger.yml');
        res.status(200).send(
            {
                message:'耗子尾汁',
                version:swaggerDocument['info']['version']
            }
        )
    };
    
    exports.setAge = (req, res) => {
        console.log(req)
        var age = req.query.number
        res.status(200).send(`来骗,来偷袭,我${age}岁的老同志`)
    };
    
    exports.tricks = (req, res) => {
        var tricks = req.body.tricks
        var comment = req.body.comment
    
        var line = tricks.join(', ') + ', ' + comment
        res.status(200).send(line)
    };
    var express = require('express');
    const RandomController = require('../Controllers/RandomController');
    
    var router = express.Router();
    
    router.get('/age', RandomController.setAge);
    router.post('/tricks', RandomController.tricks);
    router.get('/', RandomController.healthCheck);
    
    module.exports = router;

    接下来,我们来配置一下swagger.yml(yaml文件写长了真是需要游标卡尺……):

    openapi: 3.0.0
    info:
      title: Work with Swagger
      description: This is just an experiment
      version: v1.0

    servers:
    - url: http://localhost:5000

    paths:
      /:
        get:
          summary: Health check endpoint
          operationId: healthCheck
          responses:
            200:
              description: Successful operation
            400:
              description: Bad request
            404:
              description: Not found

      /age:
        get:
          summary: Set the age of the user
          parameters:
          - name: number
            in: query
            description: The age of the user
            required: true
            schema:
              type: integer
              format: int64
          responses:
            200:
              description: Successful operation
            400:
              description: Bad request
            404:
              description: Not found

      /tricks:
        post:
          summary: Hit by some tricks
          requestBody:
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/tricks'
          responses:
            200:
              description: Successful operation
            400:
              description: Bad request
            404:
              description: Not found

    components:
      schemas:
        tricks:
          type: object
          required:
          - tricks
          - comment
          properties:
            tricks:
              type: array
            comment:
              type: string

    这里我们对每个路由节点做出了一些规定,比如对于/age,我们规定query中传入的参数number只能是整数;比如对于/tricks,传入的json一定要包含tricks和comment等等(也就是规定了schema)。

    这里我们可以用2种不同的方式来规定schema:一种是直接在节点部分的schema下继续下写去(例如/age节点那样);另一种是单独写在components的schemas下面,而在节点的schema处用$ref来指定引用(例如/tricks节点那样)。

    OK,差不多完工了,现在我们进入UI界面看一看效果,输入http://localhost:5000/api-docs/,会出现这样一个界面:

    点开某个节点(此处为/age/{number}),就能看到我们对该节点的一些设置:

    点击Try it out之后就可以输入query,我们输入一个整数试试,点击Execute:

    如果我们试图输入string,会发现无法Execute:

    看来效果不错。但swagger-ui-express毕竟只是类似于一个文档工具,点到为止。我们在Postman中试试,会发现其实根本没有验证机制的存在……

    3、补上验证机制

    虽然验证要以和为贵,但不能光点到为止啊,看来我们还需要另一个验证工具,那就是openapi-express-validator。

    我们用npm install openapi-express-validator来完成安装,然后再在app.js中加入一些内容:

    var express = require('express');
    var swaggerUi = require('swagger-ui-express');
    var YAML = require('yamljs');
    var OpenApiValidator = require('express-openapi-validator');
    
    const swaggerDocument = YAML.load('./swagger/swagger.yml');
    const RandomRouter = require('./Routes/RandomRouter');
    
    var app = express();
    
    app.use(express.urlencoded({extended: true}));  //解析json用
    app.use(express.json()); //解析json用
    app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
    
    // 新增,指定一下swagger文件
    const spec = './swagger/swagger.yml';
    app.use('/spec', express.static(spec));
    
    // 将OpenApiValidator加入中间件
    app.use(
      OpenApiValidator.middleware({
        apiSpec: './swagger/swagger.yml',
        validateRequests: true,
        //validateResponses: true, // 如果需要验证response,则设为true
      }),
    );
    
    app.use('/', RandomRouter)
    
    app.use((err, req, res, next) => {
      // 配置错误信息
      res.status(err.status || 500).json({
        message: err.message,
        errors: err.errors,
      });
    });
    
    app.listen(5000, function() {
      console.log('App listening on port 5000...')
    });

    现在我们再来试试:

    这次没问题了,我们得到了一个错误信息,提示我们params中的number应该是整数。

    输入整数则没有问题,验证功能完成了。

    代码见:

    https://github.com/SilenceGTX/work_with_swagger

  • 相关阅读:
    74HC165并转串级联芯片学习记录
    道砟电阻 钢轨阻抗 列车分路电阻
    电压的有效值、平均值与峰值
    铁路信号继电器
    C语言语法记录
    程序编译过程中错误记录
    min-max容斥
    矩阵树定理
    题解 SP1812 【LCS2
    杜教筛
  • 原文地址:https://www.cnblogs.com/silence-gtx/p/14001863.html
Copyright © 2011-2022 走看看