RFC 9205読んでみた

## はじめに
API設計にはRESTの原則は避けて通れないものです．そのベストプラクティスについて「RFC 9205」を参考にまとめました．間違っている考え方や記述等ありましたらコメントいただけると助かります．

## REST API

> REST API（Representational State Transfer API）とは，REST（Representational State Transfer）というアーキテクチャスタイルに基づいて設計されたWeb APIのことを指します．REST APIは，Webサービスやアプリケーションがリソースを管理・操作するために，クライアントとサーバー間で通信する際に使用されます．

引用：ChatGPT

### 人気の理由
- 実装者，仕様，管理者，開発者，およびユーザーによる親しみやすさ
- さまざまなクライアント，サーバー，およびプロキシの実装の可用性
- 使いやすさ
- Webブラウザの可用性
- 認証や暗号化などの既存のメカニズムの再利用
- ターゲットの展開におけるHTTPサーバーとクライアントの存在
- ファイアウォールを通過する能力


### 注意
複数のサーバーが独自に運用されるような状況では，APIが使いにくくなるリスクがある．何も気にせず開発してしまうと，異なる機能やバージョンを持つデプロイメントが同時に存在することになってしまう．APIはクライアントがどのサーバーにアクセスしても問題なく動作するようにしなければならない．そこでサービスを拡張する際には特に注意して設計する必要がある．


### 開発上のポイント
1. httpsを使用する
1. 標準のHTTPメソッドとステータスコードを使用する
1. HTTPキャッシュ，認証，ステータスコード，ヘッダーなどを適切に活用する
1. Webブラウジングと共存させるには，API専用のサブドメイン`api.example.com`を使用する
1. APIのバージョン管理や後方互換性(新しいやつでも使える)を保つ

HTTPのプロトコル要素（メソッドやステータスコード）を変更・追加することで詳細な挙動を指定できる．しかし意図しない動作の原因へ繋がるためそのまま使うようにすべき．それによって，アプリ固有の知識がなくてもHTTPセマンティクスの知識を活用することもできる．

## HTTPを使うためのベストプラクティス

### HTTPの指定
HTTPを使用する際の仕様では，特定のバージョンに固執せず，APIプロトコルの進化を妨げないようにすることが重要である．また，例を示す際には完全なリクエストとレスポンスをHTTP/1.1形式で記載することが推奨されている．これにより，他の実装者が仕様を理解しやすくなる．


### サーバ動作の指定
- メディアタイプ(JSON等)の指定
- HTTPヘッダの指定
- リソースのリンク動作とメソッドを定義
- URIテンプレートを使用して，クライアントが動的にURLを生成できるようにすることも推奨

### クライアントの動作の指定
- Webブラウザーとの互換性
- リダイレクト処理やCookieの使用などを，明確に指定することで互換性の問題を防止


### ★ URLの指定（API設計の肝） ★
- クライアントはAPIドキュメントから他のリンクに対して，容易にアクセスできるようにしなければいけない．
- リソース名は名詞，メソッド名は動詞
- `/users/3/orders`など，コレクション・要素・コレクション程度の階層にとどめる
    - ×`/users/3/orders/10/products`→○`/orders/10/products`
- リソースと操作を切り分けて考える
    - `GET /users`  → ユーザ一覧取得
    - `POST /users` → ユーザ作成


## HTTPメソッド
| メソッド  | 意味 |
|-----------|------|
| GET       | リソースの取得|
| POST      | 新規リソースの作成等|
| PUT       | 既存リソースの更新・作成|
| DELETE    | リソースの削除|
| PATCH     | リソースの一部更新 |
| HEAD      | リソースのヘッダの取得|
| OPTIONS   | リソースがサポートしているメソッドの取得|


※GETは冪等でなければならない

- 悪い例：
    - データの書き込みや更新：**サーバの状態やリソースに変化を加えてしまうからダメ**
    - トランザクションの処理：支払い等の複数回実行してはいけないもの
    - メールの送信：メールを複数回送信してしまう


## HTTPステータスコード

1. ステータスコードよりもレスポンスやヘッダ情報で細かい情報を伝える
1. 全てのステータスコードに対応できるようにすべき
1. ステータスコードのセマンティクスを再定義しない


| ステータスコード | 名前         | 説明|
|------------------|--------------|-----------|
| 200              | OK                       | リクエストが正常に処理され，リクエストに対する応答が返されます．                         |
| 201              | Created                  | リクエストが成功し，新しいリソースが作成されました．                                    |
| 204              | No Content               | リクエストが成功しましたが，返すべきコンテンツがありません．                              |
| 301              | Moved Permanently        | リソースが恒久的に移動されたことを示します．新しいURLが返されます．                      |
| 302              | Found                    | リソースが一時的に移動されたことを示します．新しいURLが返されます．                      |
| 304              | Not Modified             | リソースは変更されておらず，キャッシュされたバージョンを使用できます．                   |
| 400              | Bad Request              | クライアントのリクエストが不正であるため，サーバーがリクエストを理解できません．           |
| 401              | Unauthorized             | 認証が必要ですが，クライアントが提供していないか，失敗しています．                       |
| 403              | Forbidden                | サーバーがリクエストを拒否しています．権限がありません．                                 |
| 404              | Not Found                | リクエストされたリソースがサーバーに見つかりません．                                     |
| 405              | Method Not Allowed       | リクエストのHTTPメソッドが許可されていません．                                           |
| 409              | Conflict                 | リクエストが現在のサーバーの状態と競合しているため処理できません．                         |
| 429              | Too Many Requests        | クライアントが短時間でリクエストを送信しすぎたため，制限がかかっています．                 |
| 500              | Internal Server Error    | サーバーで予期しないエラーが発生し，リクエストを処理できません．                          |
| 502              | Bad Gateway              | サーバーがゲートウェイやプロキシとして動作している際に，不正な応答を受け取りました．        |
| 503              | Service Unavailable      | サーバーが一時的に過負荷状態にあるか，メンテナンス中のため，リクエストを処理できません．    |
| 504              | Gateway Timeout          | ゲートウェイやプロキシとして動作しているサーバーが，上流サーバーからの応答を待つ際にタイムアウトしました． |


## HTTPヘッダーフィールドの指定
1. ヘッダーフィールド名の短縮化
1. キャッシュされた応答の選択に使用されるリクエストヘッダーフィールドの考慮


## 複数リクエスト
1. HTTP/1.1
1. HTTP/2およびHTTP/3
1. リクエストは独立して行われ，順序に依存しない
1. 単一の接続上でのリクエスト間に関係があると仮定しない

## クライアント認証
1. HTTP認証:
    - クライアントの識別に使用可能
    - ダイジェスト認証は安全なチャネル上でのみ使用する必要有
1. HTTPSを使用した認証:
    - 証明書を用いたクライアント認証が可能
    - 認証の範囲は基本的にトランスポート接続に限定される
    - 認証されたステータスが応答に影響したかどうかを知る方法がない
1. 認証のスコーピング:
    - 認証の範囲と使用方法を慎重に指定する必要がある
    - クライアントの意図を確保するために，リクエスト固有のトークンを使用することが推奨される．(OAuth2.0)


## Webブラウジング
1. Webブラウザとの互換性:
    - Webブラウザでの使用を意図していなくても，リソースはブラウザで利用可能
    - POSTリクエストで状態を変更できる場合，CSRF攻撃のリスクがある
1. XSS攻撃:
    - 攻撃者がコンテンツを制御できると，XSS攻撃のリスクが生じる．
    - 一般的なセキュリティ対策を講じることが推奨される．
1. セキュリティ対策:
    - アプリケーション固有のメディアタイプを指定し，正しく使用されていない場合はエラーを返す
    - X-Content-Type-Options: nosniff を使用して，コンテンツが誤って解釈されることを防ぐ
    - Content-Security-Policy を使用して，アクティブコンテンツの機能を制限する
    - Referrer-Policy を設定し，URL内の機密データが漏れないようにする
    - Cookieには 'HttpOnly' フラグを設定し，ブラウザのスクリプトからのアクセスを防ぐ
    - 機密情報には圧縮を使用しないことで，圧縮攻撃のリスクを回避する



## セキュリティ上の考慮
1. HTTPSの推奨
    - データの暗号化や通信安全性保障．全ての機密情報や認証情報を含む通信は必ず使用
1. ステータスコードを正確に使用する
    - 特にエラー情報の伝え方を明確にすることで，動作を予測可能に
1. HTTPキャッシュとの不一致
    - 古いデータが返されないようにすべき
    - 特にログイン情報をキャッシュすると違うユーザが返されることもあるため注意
1. 同一オリジン上のアプリケーションの問題
    - 複数アプリケーションが同一オリジンにホストされている場合はXSSやCSRF対策が必要

### プライバシーに関する考慮事項
1. セッション情報の管理
    - ユーザを識別するセッション情報が漏洩するとリソースにアクセスできてしまう
    - セッション情報は最小限に留め，暗号化やセキュアな通信路でのやり取りが必要
1. フィンガープリントによるクライアント追跡のリスク
    - クライアントの特定のブラウジングパターンや設定情報を利用してユーザの追跡が可能に
    - 識別情報の集めすぎに注意
1. コード実行のリスク
    - クライアント側でコード実行できる場合，XSSなどの攻撃への対策が必要


## 参考
https://tex2e.github.io/rfc-translater/html/rfc9205.html

https://developer.mozilla.org/ja/docs/Web/HTTP/Status