cover

概念圖

什麼是 Swagger?

Swagger 是一套用於描述、設計、建置和文件化 RESTful API 的工具集。2016 年後,規範部分改名為 OpenAPI Specification (OAS),而 Swagger 則成為工具的品牌名稱。

┌─────────────────────────────────────────────────┐
│                 Swagger 生態系                   │
│                                                  │
│  ┌─────────────┐  ┌─────────────┐              │
│  │   OpenAPI   │  │   Swagger   │              │
│  │    Spec     │→ │     UI      │→ 互動式文件  │
│  │  (規範)     │  │   (介面)    │              │
│  └─────────────┘  └─────────────┘              │
│         ↓                                       │
│  ┌─────────────┐  ┌─────────────┐              │
│  │   Swagger   │  │   Swagger   │              │
│  │   Editor    │  │   Codegen   │→ 產生程式碼  │
│  │  (編輯器)   │  │  (產生器)   │              │
│  └─────────────┘  └─────────────┘              │
└─────────────────────────────────────────────────┘

OpenAPI 規範基礎

基本結構

# openapi.yaml
openapi: 3.0.0
info:
  title: 使用者 API
  description: 使用者管理相關 API
  version: 1.0.0
  contact:
    name: API Support
    email: support@example.com
 
servers:
  - url: https://api.example.com/v1
    description: 正式環境
  - url: https://staging-api.example.com/v1
    description: 測試環境
 
paths:
  /users:
    get:
      summary: 取得使用者列表
      # ...
    post:
      summary: 建立使用者
      # ...
 
components:
  schemas:
    User:
      # ...
  securitySchemes:
    bearerAuth:
      # ...

定義 API 端點

paths:
  /users:
    get:
      tags:
        - Users
      summary: 取得使用者列表
      description: 回傳所有使用者,支援分頁
      operationId: getUsers
      parameters:
        - name: page
          in: query
          description: 頁碼
          required: false
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          description: 每頁筆數
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                  total:
                    type: integer
        '401':
          description: 未授權
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
 
  /users/{id}:
    get:
      tags:
        - Users
      summary: 取得單一使用者
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          description: 找不到使用者

定義資料模型

components:
  schemas:
    User:
      type: object
      required:
        - email
        - name
      properties:
        id:
          type: integer
          readOnly: true
          example: 1
        name:
          type: string
          minLength: 2
          maxLength: 50
          example: "John Doe"
        email:
          type: string
          format: email
          example: "john@example.com"
        age:
          type: integer
          minimum: 0
          maximum: 150
        role:
          type: string
          enum: [admin, user, guest]
          default: user
        createdAt:
          type: string
          format: date-time
          readOnly: true
 
    CreateUserRequest:
      type: object
      required:
        - email
        - name
        - password
      properties:
        name:
          type: string
        email:
          type: string
          format: email
        password:
          type: string
          format: password
          minLength: 8
 
    Error:
      type: object
      properties:
        code:
          type: integer
        message:
          type: string

認證設定

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
 
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
 
    oauth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://example.com/oauth/authorize
          tokenUrl: https://example.com/oauth/token
          scopes:
            read: 讀取權限
            write: 寫入權限
 
# 全域套用認證
security:
  - bearerAuth: []
 
# 或在特定端點套用
paths:
  /users:
    get:
      security:
        - bearerAuth: []
        - apiKey: []

Node.js 整合(Express)

使用 swagger-jsdoc + swagger-ui-express

npm install swagger-jsdoc swagger-ui-express
// swagger.js
import swaggerJsdoc from 'swagger-jsdoc';
import swaggerUi from 'swagger-ui-express';
 
const options = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: 'My API',
      version: '1.0.0',
    },
    servers: [
      { url: 'http://localhost:3000' }
    ],
  },
  apis: ['./routes/*.js'], // 讀取 JSDoc 註解
};
 
const specs = swaggerJsdoc(options);
 
export function setupSwagger(app) {
  app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));
}
// routes/users.js
/**
 * @swagger
 * /api/users:
 *   get:
 *     summary: 取得使用者列表
 *     tags: [Users]
 *     responses:
 *       200:
 *         description: 成功
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 $ref: '#/components/schemas/User'
 */
router.get('/', async (req, res) => {
  const users = await User.findAll();
  res.json(users);
});
 
/**
 * @swagger
 * /api/users:
 *   post:
 *     summary: 建立使用者
 *     tags: [Users]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/CreateUserRequest'
 *     responses:
 *       201:
 *         description: 建立成功
 */
router.post('/', async (req, res) => {
  const user = await User.create(req.body);
  res.status(201).json(user);
});

Laravel 整合

使用 L5-Swagger

composer require darkaonline/l5-swagger
php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"
// app/Http/Controllers/UserController.php
 
/**
 * @OA\Info(
 *     title="My API",
 *     version="1.0.0"
 * )
 */
 
/**
 * @OA\Get(
 *     path="/api/users",
 *     summary="取得使用者列表",
 *     tags={"Users"},
 *     @OA\Response(
 *         response=200,
 *         description="成功",
 *         @OA\JsonContent(
 *             type="array",
 *             @OA\Items(ref="#/components/schemas/User")
 *         )
 *     )
 * )
 */
public function index()
{
    return User::all();
}
 
/**
 * @OA\Schema(
 *     schema="User",
 *     required={"email", "name"},
 *     @OA\Property(property="id", type="integer"),
 *     @OA\Property(property="name", type="string"),
 *     @OA\Property(property="email", type="string", format="email")
 * )
 */
# 產生文件
php artisan l5-swagger:generate

Swagger 工具

工具功能
Swagger UI互動式 API 文件介面
Swagger Editor線上編輯 OpenAPI 規範
Swagger Codegen從規範產生 Client/Server 程式碼
Swagger InspectorAPI 測試工具

最佳實踐

  1. 先寫規範再實作(API First Design)
  2. 使用 $ref 重用定義,避免重複
  3. 提供清楚的 example
  4. 完整的錯誤回應描述
  5. 版本化 API(/v1, /v2)
  6. 整合 CI/CD 自動產生文件

延伸閱讀

OpenAPI 官方規範 Swagger Editor RESTFul API API