Swagger Node js

前端工程師邁向後端之路 8 – Swagger Node.js 教學:用 Swagger 自動產生 API document

1. 為什麼需要 API document

在上一篇 前端工程師邁向後端之路 7 – 實作 Node.js RESTful API 寫完 API 後,接著就是要來寫 document 了,通常後端工程師寫完 API 後必須產生相對應的 API document 才能讓前端工程師知道丟什麼樣格式的 http request 才會拿到什麼樣的 http response,以 Foreca 這個網站為例,他們有提供 API 給開發者串接,因此 API 的 document 就需要寫得越清楚越好:

Swagger Node.js
▲ Foreca API document

而今天要用來寫 API document 的工具是 Swagger,Swagger 強大的地方在於,只需要寫一個 json 檔,就可以動產生出 API document 在網頁上瀏覽,還可以直接發送 http request 來測試 API。

2. Install swagger-ui-express dependency

$ yarn add swagger-ui-express

這個 dependency 會直接將我們的 json 轉換為 API document。

3. 新增 swagger.json

在 src 底下新增 swagger.json。

{
  "openapi": "3.0.0",
  "info": {
    "title": "User API",
    "description": "Simple RESTful API in Node.js with TypeScript",
    "version": "0.0.1"
  },
  "servers": [
    {
      "url": "http://localhost:3000/api",
      "description": "Local server"
    }
  ],
}

這裡可以填一些 server 和 API k的相關資訊。

填完之後要在 index.ts import 這個檔案:

import swaggerUi from 'swagger-ui-express';

const swaggerDocument = require('./swagger.json');

app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
...

把 server 跑起來後,用瀏覽器打開 http://localhost:3000/api/docs,會出現以下的畫面:

Swagger Node.js

這樣就代表有成功產生 API document 了!接著我們就可以來寫 API document 了,一些詳細的規格可以參考:OpenAPI-Specification/3.0.3.md at main · OAI/OpenAPI-Specification,如果想要快速入門可以參考:Swagger: API Documentation & Design Tools for Teams,這邊先以 GET /api/users 取得所有 user 資料的 API 為例:

{
  "openapi": "3.0.0",
  "info": {
    "title": "User API",
    "description": "Simple RESTful API in Node.js with TypeScript",
    "version": "0.0.1"
  },
  "servers": [
    {
      "url": "http://localhost:3000/api",
      "description": "Local server"
    }
  ],
  "paths": {
    "/users": {
      "get": {
        "summary": "Return all users with list.",
        "description": "Return all existed users.",
        "responses": {
          "200": {
            "description": "A JSON array of user names",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/User"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "User": {
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "username": {
            "type": "string",
            "example": "Jimmy"
          },
          "email": {
            "type": "string",
            "example": "[email protected]"
          }
        },
        "required": ["id", "username", "email"]
      }
    }
  }
}

最後一個 property: components 裡的 schema 是為了讓 API document 可以重複使用所以才定義在外面的,否則每一個 API 都要重新定義 schema 會變得太冗長,寫完之後重新整理網頁:

Swagger Node.js

發現剛剛寫的 API 變成 document 的形式了!點開之後會有這支 API 的詳細資料: request 的格式,response 的 schema 等等:

Swagger Node.js
Swagger Node.js

點擊 Try it out 後會出現一個 Execute button,點擊 Execute 會直接 send http request,就像 Postman 一樣。

完整的 Swagger.json:

{
  "openapi": "3.0.0",
  "info": {
    "title": "User API",
    "description": "Simple RESTful API in Node.js with TypeScript",
    "version": "0.0.1"
  },
  "servers": [
    {
      "url": "http://localhost:3000/api",
      "description": "Local server"
    }
  ],
  "paths": {
    "/users": {
      "get": {
        "summary": "Return all users with list.",
        "description": "Return all existed users.",
        "responses": {
          "200": {
            "description": "A JSON array of user names",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/User"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a new user.",
        "description": "Create a new user.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success create user.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/users/{id}": {
      "get": {
        "summary": "Return the specific user.",
        "description": "Return the specific user.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "user id which wants to get",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "A JSON object of user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update the specific user.",
        "description": "Update the specific user.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "user id which wants to update",
            "required": true,
            "type": "string"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserInput"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Success update user.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete the specific user.",
        "description": "Delete the specific user.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "user id which wants to delete",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "204": {
            "description": "Success delete user.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "User": {
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "username": {
            "type": "string",
            "example": "Jimmy"
          },
          "email": {
            "type": "string",
            "example": "[email protected]"
          }
        },
        "required": ["id", "username", "email"]
      },
      "UserInput": {
        "properties": {
          "username": {
            "type": "string",
            "example": "Jimmy"
          },
          "email": {
            "type": "string",
            "example": "[email protected]"
          }
        },
        "required": ["username", "email"]
      }
    }
  }
}

以上的編寫規則都是按照 OpenAPI-Specification/3.0.3.md at main · OAI/OpenAPI-Specification 的規範。寫完之後重新整理頁面:

Swagger Node.js

所有的 API document 都完成了!而且定義的所有 schema 也都會顯示在 API 底下,簡單完成了 RESTful API document。

這系列的在 Node.js 實作 RESTful API 就到這邊啦,希望這系列的文章對你有幫助~完整的 code 可以參考:https://github.com/jimmy2952/Node.js-RESTful-API-tutorial

4. 參考資料

Swagger: API Documentation & Design Tools for Teams
OpenAPI-Specification/3.0.3.md at main · OAI/OpenAPI-Specification
Swagger-自動產生API文件 (Node.js 實作+範例程式碼)
How To Add Swagger To NodeJS REST API — Typescript Version

如果覺得我的文章有幫助的話,歡迎幫我的粉專按讚哦~謝謝你!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top