Slide 1

Slide 1 text

All rights reserved by Postman Inc 現場で役立つ API デザイン 草薙 昭彦 テクノロジーエバンジェリスト #devsumi

Slide 2

Slide 2 text

テクノロジーエバンジェリスト Postman 株式会社 草薙 昭彦 @postman_japan @nagix

Slide 3

Slide 3 text

https://http.cat/422 @postman_japan

Slide 4

Slide 4 text

はじめに ● 対象:Web API を使ったことはあるけど設計に初めて取り組む方 ● REST API の話をします ● 基本的に、ここ 20年くらい API デザインの原則は大きくは変わっていませんが、な るべく最近の事情に沿った話をします ● 詳細なデザインパターンは他にもたくさん ありますので、あとは書籍などで @postman_japan

Slide 5

Slide 5 text

なぜ API デザイン = API 仕様が重要なのか ● API 仕様書作ってますか? どのフェーズで作ってますか? ● よくあるフロー ○ 実装しながら API を整備、最後にアノテーションなどから API spec を出力、 補足を文書や Wiki などに記述 ● 残念ながら、負債になることが多い・・ ● どうする?→ API ファースト 開発 ○ 関係者間で共同で API 仕様を定め、常に 最新の変更を反映し、仕様を元にテスト、 実装、ドキュメントを開発する @postman_japan

Slide 6

Slide 6 text

API デザインのアプローチ @postman_japan インサイドアウト アウトサイドイン アジャイル 既存のバックエンドシステム が出発点 。バックエンドの内部 実装の詳細と機能が、 API を 通して公開される。 きめ細かな制御、内部プロセス への直接アクセス、豊富な機 能を提供するが、API が密結 合になり、利用者の複雑さが増 す可能性がある。 API 利用者のニーズと要件に 基づいて API を設計すること に重点を置き、内部の複雑さを 抽象化する。シンプルさ、使い やすさ、柔軟性を優先し、利用 者が基礎となる実装を知らなく ても API と対話できるようにす る。 保守と進化が容易な疎結合の API を生み出すことが多い。 開発者は完成した仕様書なし に API の作業を開始する。開 発プロセス全体を通して、柔軟 性、コラボレーション、変化へ の対応力が重視される。開発 者は、進化する要件や優先事 項に適応しながら迅速に反復 しなければならない。 開発者、利害関係者、エンド ユーザー間の緊密なコラボ レーションを奨励 する。

Slide 7

Slide 7 text

API で実現する 意図を決定する 仕様書により API コントラクトを定義 する モックとテストによ り仮説を 検証する API を 文書化する API ファーストでは @postman_japan https://www.postman.com/api-platform/api-design/

Slide 8

Slide 8 text

良い API を目指す ● HTTP 標準、Restful の原則に従おう ○ 良い API の設計には HTTP 標準、Restful の原則の理解が必要 ○ 標準を使用することで、理解がしやすい、バグの混入を防ぐ、パフォーマンス の最適化、再利用しやすくなるなどのメリットを得られる ● 同時に、ポピュラーな API で使われている「現実解」にも目を向けよう ○ 原則だけではうまくいかないケースがある ○ 現実の API には深い検討や試行錯誤を経て落とし込まれたものがある ○ API のユーザー(開発者)は、よく見る API のスタイルに慣れている @postman_japan

Slide 9

Slide 9 text

RESTful の原則 ● 統一インターフェースの使用 コンポーネントの動作を定めるための複数のアーキテクチャ制約と、単一の URL で識別できる一意のリソース ● クライアントとサーバーの分離 それぞれの関心事を分離することで、独立して開発して柔軟に機能強化することができる ● ステートレスな操作 リクエストには必要な情報をすべて含むようにし、サーバーはクライアントの状態に関する情報を保持しない ● キャッシュ可能なレスポンス レスポンス内のデータは、キャッシュ可能か不可能かラベル付けされている必要がある ● レイヤー化されたシステムアーキテクチャ 階層的なレイヤーで構成されるアーキテクチャで実現され、異なるレイヤーの中は見えないようになっている ● コード・オン・デマンド サーバーは必要に応じて実行可能コードを送信することもでき、クライアントの機能を拡張することができる @postman_japan

Slide 10

Slide 10 text

Zalando RESTful API ガイドライン ● ファッション EC を展開するヨーロッパ最大手 Zalando による、RESTful API の設計ガイ ドライン https://github.com/zalando/restful-api-guidelines ● 日本語訳 by @kawasima さん https://restful-api-guidelines-ja.netlify.app/ ● API を運用する方は、自分たちのサービス に合わせたガイドラインを整備するのがおす すめ @postman_japan

Slide 11

Slide 11 text

代表的なガイドライン ● API エンドポイントには明確で一貫性のある名前を使う ● 必須情報にはパスパラメーターを使い、追加情報にはクエリ文字列を使う ● エンドポイントが何をするかに基づいて正しい HTTP メソッドを使用する ● API がデータを正しく受け取り、応答できるように設計する ● よく使うデータをキャッシュして API を高速化する ● 目的にあった認証・認可方式を選定 ● API の使い方を明確かつ詳細に説明するドキュメントを作る @postman_japan

Slide 12

Slide 12 text

良い API エンドポイント の設計とは @postman_japan

Slide 13

Slide 13 text

URL の名前 ● リソース名には明確な名詞を使う(名前に動詞や短縮形を使わない) ○ RESTful の原則通り、リソースは「ものや事象」である ○ リソースは集合を表すことが多く、その場合複数形が適切 ● 例外もある: search @postman_japan 良い例 悪い例 /products /getProducts /customers /cust /orders /order-info

Slide 14

Slide 14 text

パスパラメーターの使用 ● リソースを一意に絞り込むためにはパスパラメーター を使用 ○ リソースの集合の指定までは同じパスを共有する /products/:id @postman_japan リソース 例 特定の製品情報 /products/12345 特定の顧客情報 /customers/23456 特定の注文情報 /orders/34567

Slide 15

Slide 15 text

クエリパラメーターの使用 ● 取得するデータのバリエーションを指定するためにクエリパラメーター を使う ● 必須の情報にはクエリパラメーターを使わない @postman_japan 目的 例 フィルター /products?category=electronics 並べ替え /products?price=desc 結果の限定 /orders?status=pending&limit=10

Slide 16

Slide 16 text

関係を表す URL ● 物事がどのように関連しているかをユーザーが理解するのに役立つ @postman_japan 関係 例 商品の注文 /products/:product_id/orders 顧客の住所 /customers/:customer_id/addresses

Slide 17

Slide 17 text

適切な抽象化を ● 実装に依存する構造を見せるのは不適切 ○ 例: データベースのテーブルをそのまま API にマッピング ● アプリの用途に合わせすぎるのも不適切 ○ 例: Web ページ毎に API を用意する ○ ただし内部 API の場合は適切なケースがある ● 複数の用途で共通化できるか、将来に渡り有効か、管理の手間は大きすぎない か、などを検討 @postman_japan

Slide 18

Slide 18 text

HTTP メソッドを 正しく使おう @postman_japan

Slide 19

Slide 19 text

要点 ● REST API は HTTP プロトコルのしくみを活用 ○ 標準を使用することで、理解がしやすい、バグの混入を防ぐ、再利用しやすく なるなどのメリット ● REST API を作る場合、CRUD (Create、Read、Update、Delete) 操作のために HTTP メソッドを正しい 方法で使うことが重要 @postman_japan

Slide 20

Slide 20 text

よく使う HTTP メソッド @postman_japan メソッド CRUD 操作 リクエスト レスポンス GET 読み込み 空 求める情報 POST 新規作成 新規データ ID 付きの新規データ PUT 更新・置き換え データ全体 更新済みデータ DELETE 削除 空 成功メッセージ PATCH 更新・置き換え データの一部 更新済みデータ HEAD 情報取得 空 ヘッダー OPTIONS 許可メソッド取得 空 許可メソッド

Slide 21

Slide 21 text

リクエストとレスポンス のデータ設計 @postman_japan

Slide 22

Slide 22 text

リクエストデータ形式 ● Content-Type ヘッダーは、リクエストボディのデータ形式を指定 ● API ドキュメントに受け付けるデータ形式を明示することが重要 @postman_japan Content-Type の値 データ形式 application/json JSON application/x-www-form-urlencoded フォームデータ multipart/form-data マルチパートフォームデータ application/octet-stream バイナリデータ

Slide 23

Slide 23 text

レスポンスデータ形式とネゴシエーション ● クライアントが受け付ける形式を Accept リクエストヘッダーで指定 ○ q Quality Value) をつけることで優先度を明示することができる Accept: application/json, text/javascript, */*;q=0.01 ● サーバーはクライアントの希望を考慮してデータ形式を決定し、Content-Type レスポンスヘッダーでレスポンスボディの形式を指定 ● ただし、クエリパラメータで希望の形式を指定する方法もよく使われる ○ 例:/products?format=json @postman_japan

Slide 24

Slide 24 text

適切なステータスコードを返す ● HTTP 標準のステータスコードを利用 @postman_japan ステータ スコード 説明 100 番台 情報 200 番台 成功 300 番台 リダイレクト 400 番台 クライアント起因のエラー 500 番台 サーバー起因のエラー 200 標準の成功レスポンス 207 レスポンスは複数のステータスを含む 304 リソースは未変更 400 一般的なエラー・未知のエラー 404 リソースのアクセス権限がない 415 リソースが存在しない 429 リクエスト数が超過 503 サーバは一時的に利用不可 主な例

Slide 25

Slide 25 text

Postman ステータスコード福引 レアなステータスコードを出して豪華賞品をゲット! 418 Iʼm a Teapot (私はティーポット 🫖) 451 Unavailable for Legal Reasons (法的な理由により利用不可 🚫) 218 This is Fine (これでいいのだ 🙆) 420 Enhance Your Calm (冷静さを高めよう 😎) 530 Site Frozen (サイト凍結中 🥶) 1等 103 Early Hints (早めのヒント 💡) 300 Multiple Choices (複数選択 ✅) 410 Gone (なくなった 👋) 422 Unprocessable Entity (処理不可の項目 🙅) 426 Upgrade Required (要アップグレード ⤴) 2等 ステータスコード 1xx (大丈夫? 🤨) 3等 ステータスコード 3xx (他を当たれ ➡) ステータスコード 4xx (お前が悪い 🫵) ステータスコード 5xx (サーバーが悪い 💢) 5等 ステータスコード 2xx (いい調子 😚) 4 等 6等 6等

Slide 26

Slide 26 text

エラーレスポンス ● 標準的な HTTP ステータスコードを使用する ● レスポンスボディにも明確なエラーメッセージとエラーの詳細を含める ○ 詳細な情報を返すことで API 利用者がすべき振る舞いが明確になる ○ RFC7807 Problem Details for HTTP APIs の利用 ● API のどこでも同じ エラー形式を使用する @postman_japan HTTP/1.1 403 Forbidden Content-Type: application/problem+json Content-Language: en { "type": "https://example.com/probs/out-of-credit", "title": "You do not have enough credit.", "detail": "Your current balance is 30, but that costs 50.", "instance": "/account/12345/msgs/abc", "balance": 30, "accounts": ["/account/12345", "/account/67890"] }

Slide 27

Slide 27 text

API バージョン管理 @postman_japan

Slide 28

Slide 28 text

API のバージョン管理 ● API を変更しても従来からのユーザーが API を使用し続けられることが重要 ● セマンティックバージョニング (major.minor.patch) ○ メジャーバージョン: 後方互換性のない変更 → 新・旧 API を併存させる ○ マイナーバージョン・パッチバージョン: 後方互換性のある変更 @postman_japan 指定方法 例 説明 URL バージョニング /v1/products URL にメジャーバージョンを含める クエリパラメータ /products?price=desc クエリとしてバージョンを指定 ヘッダー Accept: application/ vnd.api+json;version=1 コンテンツネゴシエーションを使用

Slide 29

Slide 29 text

API パフォーマンス を考慮した設計 @postman_japan

Slide 30

Slide 30 text

キャッシング ● よく使うデータを近くに保存すると、毎回遠くから取得する必要がなくなる ○ API がより速くなり、サーバーの消費電力も少なくなる ● 各リソースのキャッシュ制御ヘッダを適切に定める ○ 頻繁に変更されないリソースは 長いキャッシュ期間 ○ 動的なデータは短いキャッシュ 期間、もしくはキャッシュしない @postman_japan

Slide 31

Slide 31 text

キャッシングはヘッダーで制御 ● Cache-Control ヘッダーでキャッ シュの挙動を制御 ● ETag ヘッダーはコンテンツの全体や一 部を特定する固有値を示す ○ If-None-Match リクエストヘッ ダーと対で使われ、一致しない場 合のみコンテンツを返却するように サーバに指示 @postman_japan https://web.dev/articles/http-cache no-store no-cache キャッシュ期限を設けるか max-age=... ETag ヘッダーを使う レスポンスは再利用可能か はい いいえ 中間キャッシュを有効にするか private public 毎回検証が必要か はい いいえ いいえ はい

Slide 32

Slide 32 text

ページネーションとフィルタリング ● 返されるデータが巨大になる場合に必要な機能 ● クエリパラメーターで取得位置、取得数を指定するパターンが多い ● レスポンスには hasNext:true のようなプロパティを含めたり、次のページを取 得するための URL を含める場合が多い @postman_japan パラメーター 例 取得位置 offset、cursor、page 取得数 limit、count、per_page

Slide 33

Slide 33 text

バッチ処理用エンドポイント ● バッチ処理を受け付けるエンドポイントを用意すれば、1 回の API コールで多くのこ とができる ○ 呼び出し回数が減り、スピードが向上 @postman_japan POST /product-import [ { "name": "Cool Gadget", "price": "$ 12.45 USD" }, { "name": "Very cool Gadget", "price": "$ 19.99 USD" }, ... ]

Slide 34

Slide 34 text

ロングランオペレーション ● 返されるデータが巨大になる場合に必要な機能 ○ バッチ処理、アップロードなど ● 処理の開始、状態の確認、処理のキャンセルのエンドポイントを用意して、ジョブ ID と状態をレスポンスとして返すことが多い ● 2 つの実装方法 ○ ステータスの URL を含むレスポンスを返す→ポーリング ○ 完了時に Webhook コールバックを通じて通知を受ける @postman_japan

Slide 35

Slide 35 text

API セキュリティ @postman_japan

Slide 36

Slide 36 text

認証・認可 ● どの認証・認可を使うべきか ○ API 利用時に認証を求めるか ○ 認可をどのように実装するか (認可情報をトークンに内包するか) @postman_japan 認可方式 特徴 API キー 期限の長いトークン、認可テーブルを都度確認 OAuth 2.0 + 識別子 期限の短いトークン、認可サーバーに都度問い合わせ OAuth 2.0 + JWT 期限の短いトークン、トークンに認可情報が内包

Slide 37

Slide 37 text

CORS(オリジン間リソース共有) ● どの Web サイトが API を使用できるかを制御する。いくつかのタイプの攻撃を阻 止するのに役立つ ● CORS ルールを返すレスポンスヘッダー @postman_japan CORS ルール 使用するヘッダー どのウェブサイトが API を使用できるか Access-Control-Allow-Origin API でできること Access-Control-Allow-Methods リクエストに含めることができる情報 Access-Control-Allow-Headers これらのルールを覚えておく期間 Access-Control-Allow-Age

Slide 38

Slide 38 text

レートリミット ● ユーザーまたはアプリ単位で単位時間あたりの API アクセス上限を設定 ● 上限に達した時のステータスコードは「429 Too Many Requests」 ● ヘッダーでレートリミットの情報をユーザーに伝えるのがデファクト標準 @postman_japan ヘッダー名 説明 X-RateLimit-Limit 単位時間あたりのアクセス上限 X-RateLimit-Remaining 残り回数 X-RateLimit-Reset アクセス回数がリセットされるタイミング

Slide 39

Slide 39 text

まとめ:代表的なガイドライン ● API エンドポイントには明確で一貫性のある名前を使う ● エンドポイントが何をするかに基づいて正しい HTTP メソッドを使用する ● API がデータを正しく受け取り、応答できるように設計する ● 必須情報にはパラメーターを使い、追加情報にはクエリ文字列を使う ● よく使うデータをキャッシュして API を高速化する ● 目的にあった認証・認可方式を選定 ● API の使い方を明確かつ詳細に説明するドキュメントを作る @postman_japan

Slide 40

Slide 40 text

OpenAPI 仕様 OAS OpenAPI(最新は2021年2月リリースの3.1)は、RESTful API を記述するための API 標準仕様で、API 定義 の詳細を人間とコンピュータが理解できるような形式で提供 info メタデータ (バージョン、タイトル、ライセンス ) OpenAPI Specification 3.1 webhooks tags externalDocs 記述形式:JSON、YAML @postman_japan servers APIサーバーURLや環境 security 認証認可 OAuth2, APIキー) paths APIエンドポイント、 HTTPメソッドなど定義 components 再利用可能なスキーマ、リクエスト・レスポンスモデルなど ● 目的: API の設計・ドキュメントの標準化、 API構 造定義に焦点 ● 内容: API のメタ情報、パラメータ、リクエスト・レス ポンス情報、認証・認可情報など ● 機械可読形式であるため、 API の設計、ドキュメ ント作成、テスト、モック、クライアントやサーバー の自動生成を容易にする

Slide 41

Slide 41 text

Postman コレクション = 実行可能 API ドキュメント ● コレクション は API リクエストをグループにして整理した、基本となるデータ構造 ● コレクションを一言でいうと、実行可能な API ドキュメント コレクション APIリクエスト テスト サンプル APIリクエスト テスト サンプル APIリクエスト テスト サンプル @postman_japan

Slide 42

Slide 42 text

Postman Connpass グループ API Night(勉強会)& ワークショップ https://postman.connpass.com/ Postman イベントにぜひご参加ください Postman Japan X アカウント @postman_japan @postman_japan

Slide 43

Slide 43 text

Postman Japan コミュニティ Discord Discord サーバーを開設しました! 今後 Postman のプロダクトアップデートやイベン ト情報の配信や、みなさんとの交流の場として活 用していきたいと思います。 https://discord.gg/G4SQWDDqVa @postman_japan

Slide 44

Slide 44 text

ありがとうございました @postman_japan