Node express 使用 Swagger 自動生成 API 文件

使用 Express-Generator 來自動產生環境

參考epxress generator 安裝
node版本 14.20.1
全域方法安裝express-generator

1
npm install express-generator -g

项目初始化:專案名稱

1
express -e 專案名稱

cd 專案名稱

1
2
到專案
cd 專案名稱

//啟動

1
2
npm start

到此網址觀看
http://localhost:3000

如何使用環境

將打包好的 dist 內的資料放到 public /
改完后,重新启动express项目

如果是在vercel放置Node express 專案

  • 注意要將根目錄的app.js改為 index.js
  • “注意”bin/www/ require改為index,var app = require('../index');
      專案根目錄內新增 一個vercel.json
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      {
      "version": 2,
      "builds": [
      {
      "src": "./index.js",
      "use": "@vercel/node"
      }
      ],
      "routes": [
      {
      "src": "/(.*)",
      "dest": "/"
      }
      ]
      }

      安裝 swagger-ui-express

      1
      2
      3
      4
      //安裝 swagger-ui-express

      npm install swagger-ui-express@4.6.3 --save
      npm install swagger-jsdoc@6.2.8 --save

      https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.18.3/swagger-ui.css 另存到
      public css資料夾內 新增swagger-ui.css
      swagger-ui.css
      swagger_style

      在index.js載入swaggerUi,swaggerFile

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      // const express = require('express')之後

      const swaggerUi = require('swagger-ui-express')
      const swaggerFile = require('./swagger.json')

      // const app = express()後面
      var options = {
      customCssUrl: '網址/css/swagger-ui.css',

      };
      //swagger 路徑
      app.use('/swagger', swaggerUi.serve, swaggerUi.setup(swaggerFile,options))

      安裝 swagger-autogen 自動產生

      1
      npm install swagger-autogen@2.23.1 --save

      新增檔案swagger.js載入swaggerAutogen

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      const swaggerAutogen = require('swagger-autogen')();

      //內容
      const doc = {
      info: {
      "version": "1.0.0",
      "title": "Node MongoDB Resful Api",
      description: "swagger autogen自動生成的Api文檔"
      },

      host: "localhost:8080",
      basePath: "/",
      //localhost端時為schemes=>http
      //遠端端時為schemes=>https
      schemes: ['http', 'https'],
      consumes: ['application/json'],
      produces: ['application/json'],
      //安全定義
      securityDefinitions: {
      //api密鑰授權
      apiKeyAuth:{
      type: "apiKey",
      // 可以是“header”、“query”或“cookie”
      in: "header",
      //標頭、查詢參數或 cookie 的名稱
      name: "Authorization",
      description: ""
      }
      },
      //定義
      definitions: {
      //參數欄位與schema 對照=>Add開頭我設定為Post
      AddProduct: {
      $name: "蘋果",
      $quantity: 1,
      $price: 199,
      $image:'https://cdn.pixabay.com/photo/2016/10/25/17/58/apple-1769553_1280.jpg',
      },
      //參數欄位與schema 對照
      AddNew: {
      $subject: "今天天氣很好",
      $image: 'https://cdn.pixabay.com/photo/2015/07/05/10/18/tree-832079_1280.jpg',
      content:''
      },
      AddUser: {
      $user: "Lara",
      $email: 'lara1105huang@gmail.com',
      $password:"Lara1234567"
      }
      }
      }
      // 輸出的文件名稱
      const outputFile = './swagger.json';
      // 要指向的啟動 API
      const endpointsFiles = ['./server.js'];
      swaggerAutogen(outputFile, endpointsFiles,doc);

      啟動swaggerAutogen 的方法
      package.json 增加一行指令

      1
      "swagger-autogen": "node swagger.js"

      終端機啟動

      1
      npm run swagger-autogen

      Swagger-autogen: Success ✔

      router/api.js
      Post
      /* swagger 內容*/
      //schema => AddProduct
      //schema => AddNew

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      router.post('/product', async(req, res) => {
      try {
      /* #swagger.tags = ['Product']
      #swagger.description = '' */

      /* #swagger.parameters['obj'] = {
      in: 'body',
      description: '',
      required: true,
      schema: { $ref: "#/definitions/AddProduct" }
      } */

      /* #swagger.security = [{
      "apiKeyAuth": []
      }] */
      const product = await Product.create(req.body)
      res.status(200).json(product);
      }catch (error) {
      console.log(error.message);
      res.status(500).json({message: error.message})
      }

      )

      router.post('/new', async(req, res) => {
      try {
      /* #swagger.tags = ['New']
      #swagger.description = '' */

      /* #swagger.parameters['obj'] = {
      in: 'body',
      description: '',
      required: true,
      schema: { $ref: "#/definitions/AddNew" }
      } */

      /* #swagger.security = [{
      "apiKeyAuth": []
      }] */
      const news = await New.create(req.body)
      res.status(200).json(news);

      } catch (error) {
      console.log(error.message);
      res.status(500).json({message: error.message})
      }
      })

      //註冊

      //schema => AddUser

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      router.post('/register', async(req, res) =>
      {
      try {
      const newUser = new User(req.body);
      newUser.password = bcrypt.hashSync(req.body.password, 12);
      const token = jwt.sign({email: newUser.email, user: newUser.email, _id: newUser._id}, 'RESTFULAPI').toString();
      let userArr = {
      user: newUser.user,
      email: newUser.email,
      password: newUser.password,
      created: newUser.created,
      token:token
      }
      /* #swagger.tags = ['User']
      #swagger.description = '' */

      /* #swagger.parameters['obj'] = {
      in: 'body',
      description: '',
      required: true,
      schema: { $ref: "#/definitions/AddUser" }
      } */

      /* #swagger.security = [{
      "apiKeyAuth": []
      }] */
      const user = await User.create(userArr);

      res.status(200).json(user);
      } catch (error) {
      res.status(500).json({message: error.message})
      }
      })

      上傳

      安裝multer,imgur
      載入multer,imgur
      設定 Multer

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      const multer = require('multer')
      const imgur = require('imgur')
      //// 設定 Multer
      const upload = multer({

      limits: {
      //大小為 1MB
      fileSize: 1000000
      },

      fileFilter(req, file, cb)
      {
      //只接受三種檔案格式:jpg、png、jpeg — 若篩選失敗,丟出錯誤訊息
      //originalname獲得檔案的原始名稱(名稱+檔案格式)
      //.match:確認檔案格式是篩選時所設定
      if (!file.originalname.match(/\.(png|jpg|jpeg)$/)) {
      return cb(new Error('Please upload a picture!'))
      }
      cb(undefined, true)
      }
      }).any();

      router.post('/upload', (req, res, next) =>
      {
      upload(req, res, () => {
      imgur.setCredentials(
      process.env.IMGUR_EMAIL,
      process.env.IMGUR_PASSWORD,
      process.env.IMGUR_CLIENTID
      );
      imgur.uploadBase64(
      req.files[0].buffer.toString('base64'),
      process.env.IMGUR_ALBUM_ID
      )
      .then((json) => {
      res.send({ url: json.link });
      /*
      #swagger.consumes = ['multipart/form-data']
      #swagger.parameters['singleFile'] = {
      in: 'formData',
      type: 'file',
      required: 'true',
      description: '',
      } */
      })
      .catch((err) => {
      res.send(err.message);
      });
      })
      });