TL;DR (要するに)
Swagger Petstoreは、基本的なREST原則に違反しています。一貫性のない単数形のリソース名を使用し、URLに動詞を含み、間違ったHTTPステータスコードを返し、GETリクエストでパスワードを露呈させ、メタデータなしで裸の配列を返します。モダンなPetstoreAPIは、適切なRESTful設計、RFC 9457エラー処理、および本番環境対応のパターンにより、これらの問題をすべて修正しています。
はじめに
10年以上にわたり、Swagger PetstoreはOpenAPIを学ぶためのデフォルトの例でした。何百万もの開発者がこれを研究し、そのパターンをコピーし、その設計に基づいて本番APIを構築してきました。しかし、一つ問題があります。それは、悪いAPIの構築方法を教えているということです。
Swagger Petstoreは、基本的なREST原則に違反し、セキュリティの脆弱性を含み、本番システムに害を及ぼすアンチパターンを示しています。それは、ブレーキとアクセルペダルが入れ替わった車で運転を学ぶようなものです。学習はできますが、間違った方法を学んでしまいます。
その被害は現実です。Swagger Petstoreから学んだ開発者は、これらのアンチパターンを本番コードに持ち込みます。APIは、一貫性のない命名、間違ったHTTPメソッド、セキュリティホールを持って構築されます。コードレビューでは、「Petstoreがそうしているから」という理由で見過ごされてしまいます。
このガイドでは、Swagger Petstoreの何が問題なのか、これらの問題がなぜ重要なのか、そしてModern PetstoreAPIが本番環境対応のパターンでどのようにそれらを修正するのかを正確に学びます。並列比較を見て、各違反の影響を理解し、ApidogでAPIを適切にテストする方法を発見できます。
Swagger Petstoreのレガシー問題
Swagger Petstoreは、Swagger仕様(現在のOpenAPI)の簡単な例として2011年に作成されました。その目的は果たしました。OpenAPI仕様の書き方を示すことです。しかし、REST API設計の参照として意図されたものではありませんでした。
なぜ事実上の標準になったのか
開発者がOpenAPIを学ぶとき、彼らは公式の例から始めます。Swagger Petstoreがその例です。ドキュメント、チュートリアル、コードジェネレータに登場します。Swagger UIやSwagger Codegenを使ったことがあるなら、それを見たことがあるでしょう。
問題は、「公式の例=ベストプラクティス」と開発者が思い込んでいることです。彼らは疑問を抱かずにパターンをコピーします。API設計コースはそれを教材として使用します。企業はその構造に従って内部APIを構築します。
悪い例の代償
悪い例は時間とともに積み重なります。
- ジュニア開発者がアンチパターンを学ぶ - これらが間違いであると知りません
- コードジェネレータが問題を永続化させる - 生成されたSDKが欠陥を継承します
- ドキュメントツールが悪い例を表示する - Swagger UIはデフォルトでPetstoreを表示します
- 企業が本番APIをこの方法で構築する - 「Swaggerにとって十分なら…」
Swagger Petstoreは、歴史上どの例よりも多くのAPI設計に影響を与えてきたでしょう。だからこそ、その欠陥は重要なのです。
Swagger Petstoreにおける重大なREST違反
Swagger Petstoreの具体的なREST違反と、それらがなぜ間違っているのかを見てみましょう。
1. 一貫性のないリソース命名(複数形 vs 単数形)
違反点:
GET /pet/{petId} ← 単数形
GET /store/inventory ← 複数形
POST /pet ← 単数形
GET /user/{username} ← 単数形
なぜ間違いなのか:
RESTリソースはコレクションを表します。コレクションは複数形です。/petsにアクセスするとき、あなたはペットのコレクションにアクセスしています。/pets/123にアクセスするとき、あなたはペットのコレクション内のアイテム123にアクセスしています。
単数形と複数形を混在させると、このメンタルモデルが崩れます。/pet/123はペットのコレクションにアクセスしているのか、それとも単一のペットリソースにアクセスしているのか?この一貫性のなさが混乱を生みます。
Modern PetstoreAPIによる修正:
GET /pets/{petId} ← 常に複数形
GET /stores/inventory ← 一貫性あり
POST /pets ← コレクションには複数形
GET /users/{username} ← 全て複数形
Modern PetstoreAPIは、すべて Endpointsで複数形のリソース名を一貫して使用します。REST APIドキュメントで完全なエンドポイント構造を確認してください。
2. URL中の動詞
違反点:
GET /pet/findByStatus?status=available
GET /pet/findByTags?tags=tag1,tag2
GET /user/login?username=john&password=secret
GET /user/logout
なぜ間違いなのか:
REST URLはアクション(動詞)ではなく、リソース(名詞)を表すべきです。HTTPメソッドが動詞です。GET /petsは「ペットリソースを取得する」という意味です。findByStatusを追加するのは冗長です。それはクエリパラメータの役割です。
URL中の動詞は、RESTではなくRPC(リモートプロシージャコール)の考え方をしていることを示しています。リソースではなく実装の詳細を公開していることになります。
Modern PetstoreAPIによる修正:
GET /pets?status=AVAILABLE ← リソース + フィルター
GET /pets?tags=tag1,tag2 ← フィルタリングのためのクエリパラメータ
POST /auth/login ← 認証リソースを分離
POST /auth/logout ← RESTfulな認証エンドポイント
Modern PetstoreAPIは、フィルタリングにはクエリパラメータを、認証には独立した認証リソースを使用します。認証ガイドで適切な認証パターンを参照してください。
3. 間違ったHTTPステータスコード
違反点:
POST /pet
Response: 200 OK ← 201 Createdであるべき
DELETE /pet/{petId}
Response: 200 OK ← 204 No Contentであるべき
{
"message": "Pet deleted"
}
なぜ間違いなのか:
HTTPステータスコードには特定の意味があります:
200 OKは「リクエスト成功、ここにリソースがある」という意味です201 Createdは「リソースが作成され、どこにあるかはこちら」という意味です204 No Contentは「リクエスト成功、返すボディがない」という意味です
すべてに200を使用すると、HTTPセマンティクスが崩れます。クライアントは「リソース取得」と「リソース作成」を区別できません。DELETEでボディを返すと帯域幅が無駄になります。クライアントは確認テキストを必要としません。
Modern PetstoreAPIによる修正:
POST /pets
Response: 201 Created
Location: /pets/019b4132-70aa-764f-b315-e2803d882a24
{
"id": "019b4132-70aa-764f-b315-e2803d882a24",
"name": "Fluffy",
"status": "AVAILABLE"
}
DELETE /pets/{petId}
Response: 204 No Content
(ボディなし)
Modern PetstoreAPIは正しいHTTPステータスコードを使用し、作成されたリソースにはLocationヘッダーを含めます。HTTPステータスコードガイドで完全なマッピングを確認してください。
4. メタデータなしの裸の配列
違反点:
GET /pet/findByStatus?status=available
Response: 200 OK
[
{"id": 1, "name": "Fluffy"},
{"id": 2, "name": "Buddy"}
]
なぜ間違いなのか:
裸の配列を返すことは問題を引き起こします:
- ページネーションメタデータがない - 合計アイテム数は?何ページ目?
- 拡張性がない - クライアントを壊さずにメタデータを追加できない
- HATEOASリンクがない - ナビゲーションリンクを含められない
- JSONハイジャックのリスク - 裸の配列は特定の攻撃に対して脆弱です
Modern PetstoreAPIによる修正:
GET /pets?status=AVAILABLE
Response: 200 OK
{
"data": [
{"id": "019b4132-70aa-764f-b315-e2803d882a24", "name": "Fluffy"},
{"id": "019b4127-54d5-76d9-b626-0d4c7bfce5b6", "name": "Buddy"}
],
"pagination": {
"page": 1,
"limit": 20,
"totalItems": 45,
"totalPages": 3
},
"links": {
"self": "/pets?status=AVAILABLE&page=1",
"next": "/pets?status=AVAILABLE&page=2",
"last": "/pets?status=AVAILABLE&page=3"
}
}
Modern PetstoreAPIは、すべてのコレクションをメタデータとHATEOASリンクを含むオブジェクトでラップします。ページネーションガイドで実装の詳細を参照してください。
5. エラー標準の欠如
違反点:
Response: 400 Bad Request
{
"code": 400,
"message": "Invalid input"
}
なぜ間違いなのか:
このエラー形式は非標準であり、最小限の情報しか提供しません:
- エラータイプ識別子がない
- フィールドレベルの検証エラーがない
- 機械で読み取り可能なエラーコードがない
- RFC 9457(問題詳細)に従っていない
Modern PetstoreAPIによる修正:
Response: 400 Bad Request
Content-Type: application/problem+json
{
"type": "https://petstoreapi.com/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "Request validation failed",
"instance": "/pets",
"errors": [
{
"field": "name",
"message": "Name is required",
"code": "REQUIRED_FIELD"
},
{
"field": "status",
"message": "Status must be one of: AVAILABLE, PENDING, SOLD",
"code": "INVALID_ENUM"
}
]
}
Modern PetstoreAPIは、すべてのエラーにRFC 9457 Problem Detailsを使用します。エラーハンドリングガイドで完全なエラー形式を参照してください。
古い設計におけるセキュリティ上の問題
REST違反以外にも、Swagger Petstoreには深刻なセキュリティ問題があります。
パスワードを含むGETリクエスト
違反点:
GET /user/login?username=john&password=secret123
なぜ大惨事なのか:
GETリクエストのパスワードは、次の場所に現れます:
- ブラウザ履歴 - ブラウザにアクセスできる人なら誰でもパスワードを見ることができます
- サーバーログ - ウェブサーバーはクエリパラメータを含む完全なURLをログに記録します
- リファラーヘッダー - ユーザーがログイン後にリンクをクリックすると、次のサイトがパスワードを見ることができます
- プロキシログ - 企業のプロキシはすべてのURLをログに記録します
- ブラウザのブックマーク - ユーザーがログインURLをブックマークする可能性があります
これは重大なセキュリティ脆弱性です。パスワードはURLに決して含めるべきではありません。
Modern PetstoreAPIによる修正:
POST /auth/login
Content-Type: application/json
{
"username": "john",
"password": "secret123"
}
Response: 200 OK
{
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc...",
"expiresIn": 3600
}
Modern PetstoreAPIは、JSONボディを持つPOSTを使用して認証を行います。パスワードがURLに現れることはありません。認証ガイドでOAuth 2.0およびJWTパターンを参照してください。
クエリパラメータ中のAPIキー
違反点:
GET /pet/123?api_key=abc123secret
なぜ間違いなのか:
クエリパラメータ中のAPIキーは、URL中のパスワードと同じ問題を抱えています:
- どこでもログに記録される
- ブラウザ履歴に表示される
- リファラーヘッダーで送信される
- プロキシによってキャッシュされる
Modern PetstoreAPIによる修正:
GET /pets/019b4132-70aa-764f-b315-e2803d882a24
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Modern PetstoreAPIは、APIキーとトークンに標準のAuthorizationヘッダーを使用します。セキュリティガイドで認証パターンを参照してください。
Modern PetstoreAPIがこれらの問題をどのように修正するか
Modern PetstoreAPIは、適切なREST API設計を示すためにゼロから構築されました。その違いは次のとおりです。
本番環境対応のREST設計
- 一貫した複数形のリソース名 -
/pets,/orders,/users - リソース指向のURL - 動詞なし、名詞のみ
- 正しいHTTPステータスコード - 作成は201、削除は204、適切なエラーコード
- コレクションラッパー - すべてのリストにはページネーションとメタデータが含まれる
- RFC 9457エラー - フィールドレベル検証を含む標準エラー形式
現代の標準
- OpenAPI 3.2 - すべての機能を備えた最新の仕様
- RFC 9457 - HTTP APIのプロブレム詳細
- IETFレート制限 - 標準の
RateLimit-*ヘッダー - ISO 8601 - 適切な日付/時刻形式
- UUIDv7 - ソート可能な一意の識別子
マルチプロトコルサポート
Swagger Petstore(RESTのみ)とは異なり、Modern PetstoreAPIは以下をサポートします:
- REST(OpenAPI 3.2)
- GraphQL
- gRPC
- WebSocket
- Server-Sent Events(SSE)
- MQTT
- Webhooks
- Model Context Protocol(MCP)
プロトコルガイドで実装の詳細を参照してください。
実際のビジネスロジック
Modern PetstoreAPIには現実的な機能が含まれています:
- 支払い処理
- 在庫管理
- 注文処理
- Webhook通知
- AIを活用したペットのおすすめ
- 画像アップロードと処理
APIドキュメントで完全な機能セットを確認してください。
Apidogを使用したREST API設計のテスト
Apidogは、REST API設計を検証し、本番環境に到達する前に違反を検出するのに役立ちます。
OpenAPI仕様のインポートと検証
# Modern PetstoreAPI仕様のインポート
1. Apidogを開きます
2. 「インポート」→「OpenAPI」をクリックします
3. https://petstoreapi.com/openapi.jsonと入力します
4. Apidogが仕様を検証し、テストケースを作成します
Apidogは自動的に以下を検出します:
- 一貫性のないリソース命名
- 不足しているHTTPステータスコード
- 無効なレスポンス構造
- 認証におけるセキュリティ問題
REST原則のテスト
REST準拠を検証するテストケースを作成します。
テスト: リソース名は複数形であること
// Apidogテストスクリプト
pm.test("エンドポイントは複数形のリソース名を使用している", function() {
const url = pm.request.url.toString();
pm.expect(url).to.match(/\/pets\/|\/orders\/|\/users\//);
pm.expect(url).to.not.match(/\/pet\/|\/order\/|\/user\//);
});
テスト: 正しいステータスコード
pm.test("POSTは201 Createdを返す", function() {
if (pm.request.method === "POST") {
pm.response.to.have.status(201);
pm.response.to.have.header("Location");
}
});
pm.test("DELETEは204 No Contentを返す", function() {
if (pm.request.method === "DELETE") {
pm.response.to.have.status(204);
pm.expect(pm.response.text()).to.be.empty;
}
});
テスト: コレクションにメタデータがあること
pm.test("コレクション応答にページネーションが含まれている", function() {
const response = pm.response.json();
pm.expect(response).to.have.property("data");
pm.expect(response).to.have.property("pagination");
pm.expect(response.pagination).to.have.property("page");
pm.expect(response.pagination).to.have.property("totalItems");
});
古いPetstoreと新しいPetstoreの比較
両方の仕様をApidogにインポートし、並行比較を実行します:
- Swagger Petstoreをインポート:
https://petstore.swagger.io/v2/swagger.json - Modern PetstoreAPIをインポート:
https://petstoreapi.com/openapi.json - 両方で自動テストを実行します
- 結果を比較して違いを確認します
Apidogは、Swagger Petstoreの設計違反を強調し、Modern PetstoreAPIがそれらをどのように修正するかを示します。
移行ガイド: 古いPetstoreからモダンな設計へ
Swagger Petstoreに基づいてAPIを構築した場合、適切なREST設計に移行する方法は次のとおりです。
ステップ1: リソース名を修正する
変更前:
GET /pet/{petId}
POST /pet
DELETE /pet/{petId}
変更後:
GET /pets/{petId}
POST /pets
DELETE /pets/{petId}
移行戦略:
- 移行期間中は両方のエンドポイントをサポートする
- 古いエンドポイントに非推奨の警告を追加する
- 新しいエンドポイントを表示するようにドキュメントを更新する
- 使用状況を監視し、6ヶ月後に古いエンドポイントを削除する
ステップ2: 動詞を削除する
変更前:
GET /pet/findByStatus?status=available
GET /pet/findByTags?tags=tag1,tag2
変更後:
GET /pets?status=AVAILABLE
GET /pets?tags=tag1,tag2
移行戦略:
- 古いエンドポイントを新しいエンドポイントに301 Moved Permanentlyでリダイレクトする
- 新しいエンドポイントを使用するようにクライアントSDKを更新する
- クエリパラメータの検証を追加する
ステップ3: HTTPステータスコードを修正する
変更前:
POST /pet → 200 OK
DELETE /pet/{petId} → 200 OK with body
変更後:
POST /pets → 201 Created with Location header
DELETE /pets/{petId} → 204 No Content (no body)
移行戦略:
- これはステータスコードをチェックするクライアントにとっては破壊的変更です
- 正しいステータスコードを含むAPIをバージョン管理(v2)する
- 変更点を明確に文書化する
- 移行のタイムラインを提供する
ステップ4: コレクションをラップする
変更前:
[
{"id": 1, "name": "Fluffy"},
{"id": 2, "name": "Buddy"}
]
変更後:
{
"data": [...],
"pagination": {...},
"links": {...}
}
移行戦略:
- これは破壊的変更です
- ラップされた応答を含むv2エンドポイントを作成する
- v1エンドポイントを非推奨にする
- 新しい構造を処理するようにクライアントコードを更新する
ステップ5: RFC 9457エラーを実装する
変更前:
{
"code": 400,
"message": "Invalid input"
}
変更後:
{
"type": "https://petstoreapi.com/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "Request validation failed",
"errors": [...]
}
}
移行戦略:
Content-Type: application/problem+jsonヘッダーを追加する- 移行期間中は古いエラー形式と新しいエラー形式の両方を含める
- クライアントのエラー処理を更新する
- 移行期間後に古い形式を削除する
悪いAPI設計の現実世界への影響
悪いAPI設計には実際のコストがかかります。
開発者の混乱
APIがREST原則に違反すると、開発者は時間を無駄にします:
- 使用すべきHTTPメソッドを推測する
- 一貫性のない命名パターンを理解する
- 予期しないステータスコードのデバッグ
- 適切な構造なしにエラーを処理する
コスト: 統合あたり数時間の開発者時間
クライアント側のバグ
一貫性のないAPIはクライアント側のバグにつながります:
- 予期しない応答構造からの解析エラー
- 間違ったHTTPメソッドからの認証失敗
- メタデータがないことによるページネーションの問題
- 非標準形式からのエラー処理の失敗
コスト: 本番環境でのインシデントと顧客への影響
セキュリティの脆弱性
設計上の欠陥はセキュリティリスクを生み出します:
- URL中のパスワードがログに記録される
- クエリパラメータ中のAPIキーがキャッシュされる
- 機密性の高いエンドポイントでの認証の欠如
- 不適切なエラーメッセージがシステム情報を漏洩する
コスト: データ侵害とコンプライアンス違反
技術的負債
悪い例は時間とともに積み重なります:
- 新しい開発者がアンチパターンを学ぶ
- コードジェネレータが欠陥のあるSDKを生成する
- ドキュメントが誤った例を示す
- 企業が同じ間違いで新しいAPIを構築する
コスト: 長期的なメンテナンスの負担
結論
Swagger Petstoreは、OpenAPIの簡単な例としての役割を果たしましたが、もう先に進む時が来ています。そのREST違反、セキュリティ問題、およびアンチパターンは、あまりにも多くの本番APIに影響を与えてきました。
Modern PetstoreAPIは、業界が必要とするリファレンス実装を提供します。それは、適切なREST設計、現代の標準、マルチプロトコルサポート、および本番環境対応のパターンを備えています。学習リソースとして、またAPI設計のリファレンスとして使用してください。
ApidogでAPIをテストし、設計違反を早期に検出してください。OpenAPI仕様をインポートし、自動テストを実行して、APIが本番環境に到達する前にREST原則に従っていることを確認してください。
次のステップ:
- Modern PetstoreAPIドキュメントを探究する
- 自身のAPI設計をModern PetstoreAPIのパターンと比較する
- 検証のために自身のOpenAPI仕様をApidogにインポートする
- 上記の移行ガイドを使用してREST違反を修正する
- エラー処理のためにRFC 9457を採用する
悪いAPIの例の時代は終わりました。Modern PetstoreAPIで正しい方法でAPIを構築しましょう。
FAQ
なぜSwaggerは悪い例を作成したのですか?
Swagger Petstoreは、Swagger仕様の簡単なデモンストレーションとして2011年に作成されました。REST API設計のリファレンスとして意図されたものではありませんでした。問題は、それが事実上の標準例となり、その欠陥が何百万もの開発者によってコピーされたことです。
Swagger Petstoreの使用をやめるべきですか?
はい、REST API設計の学習にはやめるべきです。Modern PetstoreAPIを使用してください。これは、適切なREST原則、現代の標準、および本番環境対応のパターンを示しています。古いPetstoreは、本番システムに害を及ぼすアンチパターンを教えています。
Modern PetstoreAPIは本番環境対応ですか?
はい。Modern PetstoreAPIには、現実的なビジネスロジック、適切なエラー処理、認証、レート制限、およびセキュリティ機能が含まれています。最小限の変更でデプロイすることも、自身のAPI設計のリファレンスとして使用することもできます。
自分のAPIがREST原則に従っているかどうかをどのようにテストできますか?
自身のOpenAPI仕様をApidogにインポートし、自動テストを実行してください。Apidogは、リソース命名、HTTPステータスコード、応答構造、およびセキュリティパターンを検証します。また、自身のAPIをModern PetstoreAPIと並行して比較することもできます。
Swagger Petstoreの最大の間違いは何ですか?
GET /user/loginでクエリパラメータにパスワードを使用することです。これは、ブラウザ履歴、サーバーログ、およびリファラーヘッダーにパスワードを露出させます。これは重大なセキュリティ脆弱性です。認証には常にJSONボディを持つPOSTを使用してください。
Swagger Petstoreのパターンから段階的に移行できますか?
はい、移行期間中は古いエンドポイントと新しいエンドポイントの両方をサポートしてください。古いエンドポイントに非推奨の警告を追加し、ドキュメントを更新し、使用状況を監視してください。クライアントが移行した後(通常6〜12ヶ月後)に古いエンドポイントを削除してください。
Modern PetstoreAPIはGraphQLとgRPCをサポートしていますか?
はい。Swagger Petstore(RESTのみ)とは異なり、Modern PetstoreAPIは、REST、GraphQL、gRPC、WebSocket、SSE、MQTT、Webhooks、およびMCPを含む複数のプロトコルをサポートしています。プロトコルガイドで詳細を参照してください。
チームにAPI設計の修正を納得させるにはどうすればよいですか?
開発者の混乱、クライアント側のバグ、セキュリティの脆弱性、技術的負債など、実際のコストを彼らに示してください。Apidogを使用して、現在のAPIの違反を実演してください。自身の設計をModern PetstoreAPIと比較し、改善点を示してください。
