@@ -48,15 +48,15 @@ Web APIのサーバサイドの設計についてまとめる。クライアン
4848
4949各要素ごとのWeb APIの表記は以下のルールとする。表記形式を統一することで設計時の考慮事項や、Web API利用時のミスを減らすことを目的とする。
5050
51- | 対象 | 推奨 | 例 | 理由 |
52- | :------------------------- | :------------------ | :----------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
53- | ホスト名 | kebab-case | api.example.com | ホスト名にはアンダースコア(\_ )の使用をRFC 952、RFC 1123では許容していない。RFC1123では大文字と小文字を区別しなくても良いとあるため。必然的に文字の区切りはハイフンであるkebab-caseを利用する |
54- | パス(リソース名) | kebab-case \+ 複数形 | delivery-schedules | ホスト名がkebab-caseであるため、それと整合性を取る。 また、REST志向という前提であるため、リソース名の最後は複数形にする |
55- | リクエストヘッダ | kebab-case | x-debug-enabled | ※1 |
56- | クエリパラメータ | snake_case | order_id | |
57- | リクエストボディのJSON項目 | snake_case | order_id | ※2 |
58- | レスポンスヘッダ | kebab-case | x-debug-logs | ※1 |
59- | レスポンスボディのJSON項目 | snake_case | order_id | |
51+ | 対象 | 推奨 | 例 | 理由 |
52+ | :------------------------- | :------------------ | :---------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
53+ | ホスト名 | kebab-case | api.foo-bar. example.com | ホスト名にはアンダースコア(\_ )の使用をRFC 952、RFC 1123では許容していない。RFC1123では大文字と小文字を区別しなくても良いとあるため。必然的に文字の区切りはハイフンであるkebab-caseを利用する |
54+ | パス(リソース名) | kebab-case \+ 複数形 | delivery-schedules | ホスト名がkebab-caseであるため、それと整合性を取る。 また、REST志向という前提であるため、リソース名の最後は複数形にする |
55+ | リクエストヘッダ | kebab-case | x-debug-enabled | ※1 |
56+ | クエリパラメータ | snake_case | order_id | |
57+ | リクエストボディのJSON項目 | snake_case | order_id | ※2 |
58+ | レスポンスヘッダ | kebab-case | x-debug-logs | ※1 |
59+ | レスポンスボディのJSON項目 | snake_case | order_id | |
6060
6161※1 ヘッダーフィールドについて
6262
@@ -232,10 +232,10 @@ Web APIのホスティング戦略とは、Web APIのエンドポイントをど
232232
233233後方互換性のある改修のうち、パッチバージョンアップやマイナーバージョンアップと呼ばれるような改修には以下がある。
234234
235- | 項目 | 改修例 |
236- | :----------------------- | :------------------------------------------------------------------ |
237- | パッチバージョンアップ | ・小さなバグ修正 ・エラーメッセージのtypo修正 ・APIドキュメント修正 |
238- | マイナーバージョンアップ | ・新しいオプションが追加 ・性能改善、セキュリティ強化など |
235+ | 項目 | 改修例 |
236+ | :----------------------- | :-------------------------------------------------------------------------- |
237+ | パッチバージョンアップ | ・小さなバグ修正< br > ・エラーメッセージのtypo修正< br > ・APIドキュメント修正 |
238+ | マイナーバージョンアップ | ・新しいオプションが追加< br > ・性能改善、セキュリティ強化など |
239239
240240本規約の推奨は以下の通り。
241241
@@ -511,10 +511,10 @@ Idempotency-Keyヘッダという[IETF Draft(2024年12月時点ではDraft 05
511511
512512PATCHメソッドはリソースの部分更新をサポートするが、どのような形式にするかはRFC 5789で決まっていない。一般的には以下の形式が考えられる。
513513
514- | 観点 | JSON Patch | JSON Merge Patch★推奨 |
515- | :------- | :----------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ |
516- | 説明 | RFC 6902。操作が明確に定義でき、細かい制御が得意 | RFC 7386。シンプルな構文で、元のJSONに対して新しい値を上書きするだけのため、直感的である。 |
517- | 主な制約 | ・フォーマットがやや複雑で学習コストが必要 | ・配列のある要素だけ更新といった高度な操作はできない ・フィールドの削除をnullで表現するため、nullの値を持つことができる場合は、仕様通りにならない |
514+ | 観点 | JSON Patch | JSON Merge Patch★推奨 |
515+ | :------- | :----------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- |
516+ | 説明 | RFC 6902。操作が明確に定義でき、細かい制御が得意 | RFC 7386。シンプルな構文で、元のJSONに対して新しい値を上書きするだけのため、直感的である。 |
517+ | 主な制約 | ・フォーマットがやや複雑で学習コストが必要 | ・配列のある要素だけ更新といった高度な操作はできない< br > ・フィールドの削除をnullで表現するため、nullの値を持つことができる場合、表現が難しい |
518518
519519以下に ` PATCH /users/123 ` する場合に以下の操作を行った場合のリクエスト例を上げる。
520520
@@ -558,11 +558,28 @@ JSON Merge Patch:
558558
559559- PATCHのリクエストボディはJSON Merge Patch形式に従う
560560- JSON Merge Patchでハマりやすい、部分更新が出てきた場合は、PUTで処理できるエンドポイント設けるなど、PATCHにこだわりすぎない
561- - ` null ` が指定された場合、バックエンドがPostgreSQLなどRDBの場合はnull値に更新し、項目の削除はしてもしなくてもどちらでも良い。以降のレスポンスは項目ごと送信しないか、null値で送信するかは、これとは別の方針で決定する
561+ - 本規約では、 [ #nullの扱い ] ( #nullの扱い ) の章の通り値が存在しないことを ` undefined ` で表現し ` null ` を利用しない。そのため、PATCHで項目削除のために ` null ` を利用することは問題ない
562562- ` Content-Type: application/merge-patch+json ` で送信する。フレームワークなどの都合で対応できない場合は、 ` Content-Type: application/json ` も許容する
563563
564564参考: [ Web API 設計のベスト プラクティス \- Azure Architecture Center] ( https://learn.microsoft.com/ja-jp/azure/architecture/best-practices/api-design#patch-methods )
565565
566+ # リクエストヘッダ
567+
568+ 下表にてリクエストヘッダーについて推奨をまとめる。
569+
570+ | 項目 | 推奨 |
571+ | :-------------- | :---------------------------------------------------------------------------------------------------------------- |
572+ | Authorization | 認証トークンなどは Authorizationヘッダ(またはCookie)に設定する。クエリパラメータやボディには設定しない |
573+ | Content-Type | APIが対応しているメディアタイプを指定する(多くは ` application/json ` になる想定) |
574+ | User-Agent | クライアントが対向システムである場合、利用実績の把握の把握のため ` User-Agent: SystemABC/1.0 ` などと指定しても良い |
575+ | Accept-Language | 多言語対応しているWeb APIの場合は指定可能にする |
576+
577+ カスタムヘッダーについて、本規約の推奨は以下の通り。
578+
579+ - カスタムヘッダを追加する際は、その用途を明確化する
580+ - カスタムヘッダが増えることで、Web API仕様が複雑になりがちである。そのため、カスタムヘッダは必要最小限の追加とする
581+ - 命名は「スタイル」章を参照
582+
566583# クエリパラメータ
567584
568585クエリーパラメータは以下のURLの ` key1=value1&key2=value2 ` にあたる要素を指す。
@@ -695,22 +712,11 @@ Web APIのクエリパラメータで `fields` を使って必要な項目だけ
695712- 開発工数が必要となるため、必要が無ければ導入しない
696713- 導入する場合も、必要最低限の機能のみに追加する
697714
698- # リクエストヘッダ
715+ # リクエストボディ
699716
700- 下表にてリクエストヘッダーについて推奨をまとめる。
717+ ## nullの扱い
701718
702- | 項目 | 推奨 |
703- | :-------------- | :---------------------------------------------------------------------------------------------------------------- |
704- | Authorization | 認証トークンなどは Authorizationヘッダ(またはCookie)に設定する。クエリパラメータやボディには設定しない |
705- | Content-Type | APIが対応しているメディアタイプを指定する(多くは ` application/json ` になる想定) |
706- | User-Agent | クライアントが対向システムである場合、利用実績の把握の把握のため ` User-Agent: SystemABC/1.0 ` などと指定しても良い |
707- | Accept-Language | 多言語対応しているWeb APIの場合は指定可能にする |
708-
709- カスタムヘッダーについて、本規約の推奨は以下の通り。
710-
711- - カスタムヘッダを追加する際は、その用途を明確化する
712- - カスタムヘッダが増えることで、Web API仕様が複雑になりがちである。そのため、カスタムヘッダは必要最小限の追加とする
713- - 命名は「スタイル」章を参照
719+ [ #値が存在しないという状態の表現] ( #値が存在しないという状態の表現 ) の内容に従う。PATCHメソッドの場合は、[ #PATCHによる部分更新] ( #PATCHによる部分更新 ) の内容に従う。
714720
715721# HTTPステータスコード
716722
@@ -791,7 +797,7 @@ HTTPステータスコードをできる限り細かく使い分けることに
791797
792798DBなどから取得したレコードをそのまま配列のままで返すのではなく、一律オブジェクトでラップして返すこととする。
793799
794- ` 推奨 : オブジェクトをトップレベルにする`
800+ ✅️推奨 : オブジェクトをトップレベルにする
795801
796802``` js
797803{
@@ -804,7 +810,7 @@ DBなどから取得したレコードをそのまま配列のままで返すの
804810}
805811```
806812
807- ` 非推奨 : 配列をトップレベルにする`
813+ ❌️非推奨 : 配列をトップレベルにする
808814
809815``` js
810816[
@@ -822,6 +828,30 @@ DBなどから取得したレコードをそのまま配列のままで返すの
822828| | クライアント側で items項目を取得すると言ったひと手間が必要だが、大した労力ではない |
823829| 性能 | データサイズが多少大きくなるが、レスポンスは通常gzip圧縮されることもあり誤差 |
824830
831+ ## 値が存在しないという状態の表現
832+
833+ 原則 ` null ` を用いず、パラメータのキー自体を含めないこと(` undefined ` )による表現を行う。理由は以下の通り。
834+
835+ - ペイロードサイズを小さくできるため
836+ - 必要なプロパティのみが含まれている方が視認性が良いため
837+ - 実装上の不具合が無く、OpenAPI定義としても ` null ` 許容する方が手間がかかるため
838+
839+ ✅️推奨: scoreがの値が存在しない場合、キー自体を含めない
840+
841+ ``` json
842+ { "id" : " 00001" , "name" : " Bob" }
843+ ```
844+
845+ ❌️非推奨: scoreの値が存在しない場合はnullを用いる
846+
847+ ``` json
848+ { "id" : " 00001" , "name" : " Bob" , "score" : null }
849+ ```
850+
851+ 参考:
852+
853+ - [ OpenAPIにおけるundefinedとnullの設計 | フューチャー技術ブログ] ( https://future-architect.github.io/articles/20211028b/ )
854+
825855## 日付フォーマット
826856
827857日付項目はUnix タイムスタンプを返すか、ISO8601で返すかの考慮がある。
@@ -1320,10 +1350,10 @@ sequenceDiagram
13201350
13211351それぞれのメリット/デメリットは以下のとおり。
13221352
1323- | | 同期API | 非同期API |
1324- | :--------- | :-------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- |
1325- | メリット | ・各言語でデファクトスタンダードとなる実装があり、比較的低コストで実装可能 | ・重量級の処理の場合、呼び出し側がブロックされず快適なUX提供につながる ・アプリケーションの機能とリソースが新しいリクエストの処理のために解放される |
1326- | デメリット | ・完了するまで呼び出し側処理がブロックされる ・応答時間が各サービスの応答時間の合算になるなど、ユーザーの待機時間が長くなる可能性がある | ・非同期タスクが失敗した場合の考慮など、設計/実装コストが高い |
1353+ | | 同期API | 非同期API |
1354+ | :--------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :---- -------------------------------------------------------------------------------------------------------------------------------------------------- |
1355+ | メリット | ・各言語でデファクトスタンダードとなる実装があり、比較的低コストで実装可能 | ・重量級の処理の場合、呼び出し側がブロックされず快適なUX提供につながる< br > ・アプリケーションの機能とリソースが新しいリクエストの処理のために解放される |
1356+ | デメリット | ・完了するまで呼び出し側処理がブロックされる< br > ・応答時間が各サービスの応答時間の合算になるなど、ユーザーの待機時間が長くなる可能性がある | ・非同期タスクが失敗した場合の考慮など、設計/実装コストが高い |
13271357
13281358同期APIと非同期APIの選択における本規約の推奨は以下。
13291359
0 commit comments