Swagger PetstoreがひどいREST API設計である理由

Ashley Innocent

Ashley Innocent

13 3月 2026

Swagger PetstoreがひどいREST API設計である理由

Apidog エンタープライズ

オンプレミスデプロイ

SSO & RBAC

SOC 2 準拠

Apidog Enterpriseを見る

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がそうしているから」という理由で見過ごされてしまいます。

💡
REST APIを構築またはテストしている場合、ApidogはREST原則に対するAPI設計の検証、エンドポイントの動作テスト、および設計上の欠陥が本番環境に到達する前の検出を支援します。OpenAPI仕様をインポートし、自動テストを実行して、APIが適切なREST規約に従っていることを確認できます。
button

このガイドでは、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を構築します。

悪い例の代償

悪い例は時間とともに積み重なります。

  1. ジュニア開発者がアンチパターンを学ぶ - これらが間違いであると知りません
  2. コードジェネレータが問題を永続化させる - 生成されたSDKが欠陥を継承します
  3. ドキュメントツールが悪い例を表示する - Swagger UIはデフォルトでPetstoreを表示します
  4. 企業が本番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を使用すると、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"}
]

なぜ間違いなのか:

裸の配列を返すことは問題を引き起こします:

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"
}

なぜ間違いなのか:

このエラー形式は非標準であり、最小限の情報しか提供しません:

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に決して含めるべきではありません。

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設計

現代の標準

マルチプロトコルサポート

Swagger Petstore(RESTのみ)とは異なり、Modern PetstoreAPIは以下をサポートします:

プロトコルガイドで実装の詳細を参照してください。

実際のビジネスロジック

Modern PetstoreAPIには現実的な機能が含まれています:

APIドキュメントで完全な機能セットを確認してください。

Apidogを使用したREST API設計のテスト

Apidogは、REST API設計を検証し、本番環境に到達する前に違反を検出するのに役立ちます。

OpenAPI仕様のインポートと検証

# Modern PetstoreAPI仕様のインポート
1. Apidogを開きます
2. 「インポート」→「OpenAPI」をクリックします
3. https://petstoreapi.com/openapi.jsonと入力します
4. Apidogが仕様を検証し、テストケースを作成します

Apidogは自動的に以下を検出します:

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にインポートし、並行比較を実行します:

  1. Swagger Petstoreをインポート: https://petstore.swagger.io/v2/swagger.json
  2. Modern PetstoreAPIをインポート: https://petstoreapi.com/openapi.json
  3. 両方で自動テストを実行します
  4. 結果を比較して違いを確認します

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}

移行戦略:

ステップ2: 動詞を削除する

変更前:

GET /pet/findByStatus?status=available
GET /pet/findByTags?tags=tag1,tag2

変更後:

GET /pets?status=AVAILABLE
GET /pets?tags=tag1,tag2

移行戦略:

ステップ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)

移行戦略:

ステップ4: コレクションをラップする

変更前:

[
  {"id": 1, "name": "Fluffy"},
  {"id": 2, "name": "Buddy"}
]

変更後:

{
  "data": [...],
  "pagination": {...},
  "links": {...}
}

移行戦略:

ステップ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": [...]
}
}

移行戦略:

悪いAPI設計の現実世界への影響

悪いAPI設計には実際のコストがかかります。

開発者の混乱

APIがREST原則に違反すると、開発者は時間を無駄にします:

コスト: 統合あたり数時間の開発者時間

クライアント側のバグ

一貫性のないAPIはクライアント側のバグにつながります:

コスト: 本番環境でのインシデントと顧客への影響

セキュリティの脆弱性

設計上の欠陥はセキュリティリスクを生み出します:

コスト: データ侵害とコンプライアンス違反

技術的負債

悪い例は時間とともに積み重なります:

コスト: 長期的なメンテナンスの負担

結論

Swagger Petstoreは、OpenAPIの簡単な例としての役割を果たしましたが、もう先に進む時が来ています。そのREST違反、セキュリティ問題、およびアンチパターンは、あまりにも多くの本番APIに影響を与えてきました。

Modern PetstoreAPIは、業界が必要とするリファレンス実装を提供します。それは、適切なREST設計、現代の標準、マルチプロトコルサポート、および本番環境対応のパターンを備えています。学習リソースとして、またAPI設計のリファレンスとして使用してください。

ApidogでAPIをテストし、設計違反を早期に検出してください。OpenAPI仕様をインポートし、自動テストを実行して、APIが本番環境に到達する前にREST原則に従っていることを確認してください。

次のステップ:

  1. Modern PetstoreAPIドキュメントを探究する
  2. 自身のAPI設計をModern PetstoreAPIのパターンと比較する
  3. 検証のために自身のOpenAPI仕様をApidogにインポートする
  4. 上記の移行ガイドを使用してREST違反を修正する
  5. エラー処理のために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と比較し、改善点を示してください。

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる