Help us understand the problem. What is going on with this article?

今さらだけど「Web API: The Good Parts」 を読んだので自分なりにまとめてみる

More than 3 years have passed since last update.

今さらですが、「Web API: The Good Parts」を読みました。
せっかくなので自分なりにまとめてみます。

1. URLについて

  • 短く入力しやすいURL
      ×:http://sample.com/search-api/service/api/search
      ○:http://sample.com/api/search
  • 人間が読んで理解できるURL
     ×:http://sample.com/api/u
     ○:http://sample.com/api/user
      略すのもだめ products -> prod
  • 大文字小文字が混在していないURL
      ×:http://sample.com/api/getUserInfo
      ○:http://sample.com/api/user
      基本はすべて小文字
  • 改造しやすい(Hackable)なURL
      ×:http://sample.com/api/item/a/12345
      ×:http://sample.com/api/item/b/67890
      ○:http://sample.com/api/item/12345
      ○:http://sample.com/api/item/67890 
  • サーバ側のアーキテクチャが反映されていないURL
      ×:http://sample.com/cgi-bin/get_user.php?user=100
      ○:http://sample.com/api/user?id=100
  • ルールが統一されたURL
      userはidを指定するのに、itemはクエリを使うなどの不統一はだめ

2. HTTPメソッドについて

  • GET
    リソースの取得
  • POST
    リソースの新規登録
  • PUT
    既存リソースの更新
  • DELETE
    リソースの削除
  • PATCH
    リソースの一部変更
  • HEAD
    リソースのメタ情報の取得

    ※ 基本的には、GET/POST/PUT/DELETEの4つをサポートする
    GET,POSTしか使えない場合
    リクエストヘッダX-HTTP-Method-Overrideを使う

    POST /X/XX HTTP/1.1
    Host XXX.com  
    X-HTTP-Method-Override: DELETE
    

3. ネーミング選定指針について

  • 複数形の名詞を利用する
      複数だとわかりにくい単語は単数形にしてもよい
  • 極力動詞は使用しない
  • 利用する単語に気を付ける
      迷ったらProgrammableWebというサイトなどで探す
  • スペースやエンコーディングを必要とする文字を使わない
  • 単語をつなげる必要がある場合はハイフンを利用する
      URIのドメイン名のルールと合っているため

4. エンドポイント設計について

  • ひとつの画面を表示するためにコールするのが1つのAPIで済むようにする
  • なんらかのデータをサーバに保存する場合にも1回のコールで済むようにAPIを用意する

5. レスポンスデータの設計について

  • データフォーマットはJSONをデフォルトとし、必要がある場合のみXMLに対応する
  • 様々なユースケースを考慮し、一度に返すデータはなるべく詳細にする
    例)ユーザ情報を返す
    ID、名前、写真、住所など
  • ただし、データが大きすぎる場合、クライアント側で選択できるようにする
    例えば、パラメータにsmall, medium, largeをつけると取得する項目を変えるようにする
  • 不要な階層化はせず、なるべくフラットにする
  • もちろん階層化したほうが良い場合もある
    例えば、メッセージの送信者と受信者があり、その下にユーザデータをつける場合など

    sender_id:12345,
    sender_name:aaaaa,
    receiver_id:67890,
    receiver_name:bbbbb                 
    
        ↓
    
    sender: {
        id:12345,
        name:aaaaa
    },
    receiver:{
        id:67890,
        name:bbbbb
    }                   
    
  • JSONのトップレベルを配列にしない
    JSONインジェクションという脆弱性に対するリスクが大きくなる
    ※ JSONインジェクション
    → ScriptタグでJSONを読み込む手法。トップレベルが配列だと、JavaScript構文エラーにならずに、データが取得できてしまう。
  • 日付のフォーマット
    RFC3339を推奨
    → インターネット上で用いる標準形式として決められたもののため
    例)2015-10-12T11:30:22+09:00
  • 巨大な数字は文字列にして返す
    18桁などの整数は、JavaScriptが64bit浮動小数として扱うため誤差がでる
  • エラーの表現
    • 適切なステータスコードを返すこと
      エラーメッセージを返していてもステータスコードが200だとクライアント側に負担をかけることになる
    • エラーの際にHTMLが返らないようにする
    • メンテナンスなどでサービスを止める場合
      • ステータスコードは503を返す
      • HTTPヘッダのRetry-Afterを使って、メンテナンスが終わる時刻を返す

6. HTTPの仕様について

  • ステータスコード
    • 100番台
      情報
    • 200番台
      成功
    • 300番台
      リダイレクト
    • 400番台
      クライアントサイドに起因するエラー
    • 500番台
      サーバサイドに起因するエラー
  • データ更新時のベストプラクティス
    • PUTやPATCHは200(OK)とともに操作したデータを返却
    • DELETEは204(No Contents)を返す
  • クライアントエラーについて
    • 401(Unauthorized)は認証エラー
    • 403(Forbidden)は認可エラー
      認証とは、「アクセスしてきたのが誰であるのかを識別すること」
      認可とは、「特定のユーザに対してある操作の権限を許可すること」
      → つまり、401は「あなたが誰だかわからないよ」、403は「あなたが誰だかはわかったけど、この操作はあなたには許可されていないよ」
  • サーバエラーについて
    500(Internal Server Error)はログをきちんと監視して、管理者に通知が行くように設定しておくこと
  • クロスドメイン問題について
    CORSの利用
  • 独自HTTPヘッダの定義について
    • 「X-」という接頭辞をつける
    • その後はサービス・アプリ名や組織名、そしてハイフンを挟んでIDを付ける
      例)X-abc-original-id

7. バージョンについて

  • APIのバージョン
    URIにバージョン情報を含める方法が最もよく利用されている
    例)http://api.abc.co.jp/v2/users/
  • モバイルアプリのアップデートについて
    アプリ起動時に、現在のバージョンとサーバ側で配信するサポートバージョンを比較し、利用者にアップデートを案内する仕組みを仕込んでおく

8. セキュリティについて

  • セッションハイジャック対策
    • HTTPSにする
  • XSS(クロスサイトスクリプティング)対策

    • 以下のレスポンスヘッダを使用する(JSONインジェクション対策にも有効)

      X-Content-Type-Options: nosniff     
      
    • JSON文字列のエスケープを行う(SCRIPTタグを無効にする)

  • XSRF(クロスサイトリクエストフォージェリ)対策
    • サーバのデータ更新を行うようなアクセスに関しては、GETメソッドを利用せずPOST, PUT, DELETEを用いること
    • 正規のフォームにワンタイムトークン(少なくともセッションごとにユニークなトークン)を埋め込んでおき、そのトークンのないアクセスは拒否する
  • JSONインジェクション対策

    • メディアタイプをクライアントに返す

      Content-Type: application/json
      
    • JSONデータのトップレベルを配列にしない。必ずオブジェクトにする

9. 大量アクセス対策

  • ユーザごとにアクセス制限する
    • 何を使ってユーザを識別するか
    • リミット値をいくつにするか
    • どういう単位でリミット値を設定するか
    • リミットのリセットをどういうタイミングで行うか
      • たとえば1分間に60回をアクセスの上限とした場合、1分間の間に61回アクセスがあった場合はエラーを返し、また1分が経過したらアクセスができるようになる、といった具合
      • 一般的には1時間が多い
  • 制限値を超えた場合の対応
    • 429 Too Many Requests を返すべき
    • エラーの詳細をレスポンスに含めるべき
    • Retry-Afterヘッダを使って次のリクエストまでの待ち時間を指定してもよい
  • レスポンスにレートリミットを含める場合
    以下はヘッダに格納する場合のデファクトスタンダード
    • X-RateLimit-Limit
      単位時間あたりのアクセス上限
    • X-RateLimit-Remaining
      アクセスできる残り回数
    • X-RateLimit-Reset
      アクセス数がリセットされるタイミング
naoki_koreeda
PHPerになりました。最近Google Cloud Platform/Golang/Node.js。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away