Swagger UI

GitHub概要

swagger-api/swagger-ui

Swagger UI is a collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.

スター28,026
ウォッチ643
フォーク9,179
作成日:2011年7月15日
言語:JavaScript
ライセンス:Apache License 2.0

トピックス

hacktoberfestoasopen-sourceopenapiopenapi-specificationopenapi3openapi31restrest-apiswaggerswagger-apiswagger-jsswagger-ossswagger-ui

スター履歴

swagger-api/swagger-ui Star History
データ取得日時: 2025/8/13 01:43

API開発ツール

Swagger UI

概要

Swagger UI(スワッガーUI)は、OpenAPI仕様書から自動生成されるインタラクティブなAPIドキュメントツールです。業界標準のAPI文書化ツールとして、開発チームや利用者がAPIリソースを視覚化し、実装ロジックなしに直接操作できます。API-Firstな開発手法の普及により、現代のAPI開発において必須のツールとなっています。

詳細

Swagger UIは、OpenAPI(旧Swagger)仕様に基づいてAPIドキュメントを動的に生成するWebベースのツールです。HTML、JavaScript、CSSアセットの集合体として提供され、OpenAPI定義から美しく機能的なドキュメントを自動構築します。最大の特徴は、ドキュメントが単なる情報表示ではなく、実際にAPIエンドポイントを呼び出せるインタラクティブな環境を提供することです。開発者は実装コードやネットワークトラフィック調査なしに、APIの機能を理解し検証できます。OpenAPI仕様では、RESTfulAPIに対する標準インターフェースを定義し、人間とコンピュータの両方がソースコードやドキュメントに直接アクセスすることなく、サービス機能を理解できるようにします。SmartBear社が提供するSwaggerエコシステムの一部として、Swagger Codegen(サーバー・クライアントコード生成)、Swagger Editor(ブラウザベースエディタ)、Swagger Core(Java関連ライブラリ)と統合され、包括的なAPI開発・管理プラットフォームを構成しています。Web標準技術のみで動作するため、プラットフォーム非依存でありながら、リアルタイムでのAPI探索とテストを可能にします。

メリット・デメリット

メリット

  • 標準仕様準拠: OpenAPI仕様の業界標準として広く採用
  • インタラクティブ操作: ドキュメント内で直接APIを実行・検証可能
  • 自動生成: OpenAPI定義から美しいドキュメントを自動構築
  • プラットフォーム非依存: Webブラウザがあればどこでもアクセス可能
  • 開発・利用者両対応: バックエンド実装とクライアント利用の両方をサポート
  • Swaggerエコシステム: Codegen、Editorなどと完全統合
  • カスタマイズ可能: テーマやレイアウトのカスタマイズに対応
  • 無料・オープンソース: Apache 2.0ライセンスで自由に利用可能

デメリット

  • OpenAPI依存: OpenAPI仕様書の品質に完全依存
  • 動的機能制限: 静的生成のため高度なインタラクション機能に限界
  • 認証複雑性: 複雑な認証フローの表現・テストが困難
  • パフォーマンス: 大規模APIでは表示・操作が重くなる場合
  • バージョン管理: API仕様変更時の文書更新管理が課題

参考ページ

書き方の例

基本的なOpenAPI仕様書(swagger.yaml)

openapi: 3.0.0
info:
  title: User Management API
  description: ユーザー管理システムのAPI仕様書
  version: 1.0.0
  contact:
    name: API Support
    email: [email protected]
servers:
  - url: https://api.example.com/v1
    description: 本番環境
  - url: https://api-staging.example.com/v1
    description: ステージング環境

paths:
  /users:
    get:
      summary: ユーザー一覧取得
      description: システムに登録されているユーザーの一覧を取得します
      parameters:
        - name: page
          in: query
          description: ページ番号
          required: false
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          description: 1ページあたりの件数
          required: false
          schema:
            type: integer
            default: 10
            maximum: 100
      responses:
        '200':
          description: ユーザー一覧の取得に成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  users:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
        '400':
          description: リクエストパラメータが不正
        '500':
          description: サーバー内部エラー

    post:
      summary: ユーザー作成
      description: 新しいユーザーを作成します
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
      responses:
        '201':
          description: ユーザー作成成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          description: バリデーションエラー
        '401':
          description: 認証が必要
        '409':
          description: ユーザーが既に存在

  /users/{userId}:
    get:
      summary: ユーザー詳細取得
      description: 指定されたIDのユーザー情報を取得します
      parameters:
        - name: userId
          in: path
          required: true
          description: ユーザーのID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: ユーザー詳細の取得に成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          description: ユーザーが見つからない

    put:
      summary: ユーザー更新
      description: 指定されたIDのユーザー情報を更新します
      security:
        - ApiKeyAuth: []
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserRequest'
      responses:
        '200':
          description: ユーザー更新成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          description: バリデーションエラー
        '401':
          description: 認証が必要
        '404':
          description: ユーザーが見つからない

    delete:
      summary: ユーザー削除
      description: 指定されたIDのユーザーを削除します
      security:
        - ApiKeyAuth: []
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '204':
          description: ユーザー削除成功
        '401':
          description: 認証が必要
        '404':
          description: ユーザーが見つからない

components:
  schemas:
    User:
      type: object
      required:
        - id
        - name
        - email
      properties:
        id:
          type: string
          format: uuid
          description: ユーザーID
          example: "123e4567-e89b-12d3-a456-426614174000"
        name:
          type: string
          description: ユーザー名
          example: "田中太郎"
        email:
          type: string
          format: email
          description: メールアドレス
          example: "[email protected]"
        age:
          type: integer
          minimum: 0
          maximum: 120
          description: 年齢
          example: 30
        created_at:
          type: string
          format: date-time
          description: 作成日時
          example: "2025-01-15T10:30:00Z"
        updated_at:
          type: string
          format: date-time
          description: 更新日時
          example: "2025-01-15T14:45:00Z"

    CreateUserRequest:
      type: object
      required:
        - name
        - email
      properties:
        name:
          type: string
          description: ユーザー名
          example: "田中太郎"
        email:
          type: string
          format: email
          description: メールアドレス
          example: "[email protected]"
        age:
          type: integer
          minimum: 0
          maximum: 120
          description: 年齢
          example: 30

    UpdateUserRequest:
      type: object
      properties:
        name:
          type: string
          description: ユーザー名
          example: "田中花子"
        email:
          type: string
          format: email
          description: メールアドレス
          example: "[email protected]"
        age:
          type: integer
          minimum: 0
          maximum: 120
          description: 年齢
          example: 32

    Pagination:
      type: object
      properties:
        page:
          type: integer
          description: 現在のページ番号
          example: 1
        limit:
          type: integer
          description: 1ページあたりの件数
          example: 10
        total:
          type: integer
          description: 総件数
          example: 150
        total_pages:
          type: integer
          description: 総ページ数
          example: 15

  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: APIキーによる認証
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWTトークンによる認証

security:
  - ApiKeyAuth: []
  - BearerAuth: []

HTML形式でのSwagger UI統合

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>User Management API Documentation</title>
    <link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/swagger-ui.css" />
    <style>
        html {
            box-sizing: border-box;
            overflow: -moz-scrollbars-vertical;
            overflow-y: scroll;
        }
        *, *:before, *:after {
            box-sizing: inherit;
        }
        body {
            margin:0;
            background: #fafafa;
        }
    </style>
</head>
<body>
    <div id="swagger-ui"></div>
    
    <script src="https://unpkg.com/[email protected]/swagger-ui-bundle.js"></script>
    <script src="https://unpkg.com/[email protected]/swagger-ui-standalone-preset.js"></script>
    <script>
        window.onload = function() {
            // Begin Swagger UI call region
            const ui = SwaggerUIBundle({
                url: './swagger.yaml',
                dom_id: '#swagger-ui',
                deepLinking: true,
                presets: [
                    SwaggerUIBundle.presets.apis,
                    SwaggerUIStandalonePreset
                ],
                plugins: [
                    SwaggerUIBundle.plugins.DownloadUrl
                ],
                layout: "StandaloneLayout",
                tryItOutEnabled: true,
                requestInterceptor: function(request) {
                    // APIキーを自動追加
                    request.headers['X-API-Key'] = 'your-api-key-here';
                    return request;
                },
                responseInterceptor: function(response) {
                    // レスポンスログ
                    console.log('API Response:', response);
                    return response;
                }
            });
            // End Swagger UI call region
        };
    </script>
</body>
</html>

Node.js Express統合例

// package.json dependencies:
// "express": "^4.18.0",
// "swagger-ui-express": "^4.6.0",
// "yamljs": "^0.3.0"

const express = require('express');
const swaggerUi = require('swagger-ui-express');
const YAML = require('yamljs');
const path = require('path');

const app = express();

// OpenAPI仕様書を読み込み
const swaggerDocument = YAML.load(path.join(__dirname, 'swagger.yaml'));

// カスタムCSS
const customCss = "\\n" + 
  "  .topbar-wrapper { display: none; }\\n" +
  "  .swagger-ui .topbar { background-color: #2c3e50; }\\n" +
  "  .swagger-ui .info .title { color: #2c3e50; }\\n";

// Swagger UI オプション
const swaggerOptions = {
  explorer: true,
  customCss: customCss,
  customSiteTitle: "User Management API",
  swaggerOptions: {
    persistAuthorization: true,
    tryItOutEnabled: true,
    filter: true,
    displayRequestDuration: true
  }
};

// Swagger UI のセットアップ
app.use('/api-docs', swaggerUi.serve);
app.get('/api-docs', swaggerUi.setup(swaggerDocument, swaggerOptions));

// ルートエンドポイント
app.get('/', (req, res) => {
  res.redirect('/api-docs');
});

// APIエンドポイント(実装例)
app.use(express.json());

app.get('/v1/users', (req, res) => {
  const { page = 1, limit = 10 } = req.query;
  
  // モックデータ
  const users = [
    {
      id: "123e4567-e89b-12d3-a456-426614174000",
      name: "田中太郎",
      email: "[email protected]",
      age: 30,
      created_at: "2025-01-15T10:30:00Z",
      updated_at: "2025-01-15T14:45:00Z"
    }
  ];
  
  res.json({
    users: users,
    pagination: {
      page: parseInt(page),
      limit: parseInt(limit),
      total: 150,
      total_pages: Math.ceil(150 / limit)
    }
  });
});

app.post('/v1/users', (req, res) => {
  const { name, email, age } = req.body;
  
  // バリデーション
  if (!name || !email) {
    return res.status(400).json({ error: 'Name and email are required' });
  }
  
  // モックレスポンス
  const newUser = {
    id: Date.now() + "-" + Math.random().toString(36).substr(2, 9),
    name,
    email,
    age,
    created_at: new Date().toISOString(),
    updated_at: new Date().toISOString()
  };
  
  res.status(201).json(newUser);
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log("Server running on http://localhost:" + PORT);
  console.log("API Documentation: http://localhost:" + PORT + "/api-docs");
});

Docker統合とデプロイ

# Dockerfile
FROM node:18-alpine

WORKDIR /app

# 依存関係をインストール
COPY package*.json ./
RUN npm ci --only=production

# アプリケーションファイルをコピー
COPY . .

EXPOSE 3000

CMD ["npm", "start"]
# docker-compose.yml
version: '3.8'
services:
  api-docs:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    volumes:
      - ./swagger.yaml:/app/swagger.yaml:ro
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - api-docs
    restart: unless-stopped

CI/CD統合とAPI仕様検証

# .github/workflows/api-docs.yml
name: API Documentation

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  validate-openapi:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Validate OpenAPI Spec
      uses: char0n/swagger-editor-validate@v1
      with:
        definition-file: swagger.yaml
    
    - name: Generate API Documentation
      run: |
        npm install -g swagger-ui-dist
        swagger-ui-dist-cli -f swagger.yaml -d api-docs/
    
    - name: Deploy to GitHub Pages
      if: github.ref == 'refs/heads/main'
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./api-docs