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.
トピックス
スター履歴
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仕様変更時の文書更新管理が課題
参考ページ
- Swagger UI公式サイト
- GitHub - swagger-api/swagger-ui
- OpenAPI Specification
- Swagger Documentation
- Swagger Tools
書き方の例
基本的な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