Web API: The Good Partsを読んだ
仕事でWeb APIを作ることが多くなったので読んだ。体系的にまとまっていてよかった。ヘッダ周りなど曖昧だった部分が明確に説明されていて助かった。
ちょっとAPIの例が古かったような気もするけれど、今でも特に変わっていないように思う。キャッシュ周りはISUCONとかで役に立ちそうだなと思いながら読んでいた。

- 作者: 水野貴明
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/11/21
- メディア: 大型本
- この商品を含むブログ (7件) を見る
メモ
APIの設計
- LSUDs(large set of unknown developers)
- SSKDs(small set of known developers)
URIの設計
- 開発者はドキュメントを読まない
- PUTとPATCH
- PUTは全部上書き
- PATCHは書き換えたい部分を送る
- 単語をつなげるのは-か_か
- アンダースコアは歴史的にタイプライターで河川をj引くためのものだから目的にそぐわない
- なるほど…。
ページネーション
- per_page/pageとlimit/offsetどちらがよいか
- limit/offsetの方が柔軟だけどper_page/pageのほうがキャッシュが効く
- 状況によりますね
- TwitterのAPIは
max_id
を定めていて、そこから手前というページングができる
ドメイン
api.example.net
とかにしたほうが良いのではないか
スクリーンとAPI
- 1スクリーン1APIコール、1セーブ1APIコール
REST
- アクセスしたデータがどんなデータなのかを知るためにメディアタイプがある
application/vnd.companyname.user.detail.v1+json
とかメディアタイプが有るとおしゃれ- GitHubはこんな感じのことをしている
- クライアントが微妙だとメディアタイプが
application/json
でないと動かないので、application/json
にしておきましょうと書いてあったけど、それでいいのか、という気持ちもした
レスポンスデータの設計
- ArrayでなくてObjectで返したほうが良い
- JSとして抜き取られた場合にArrayだとvalidなJSコードになってしまうけど、ObjectだとinvalidなJSコードになる(Blockとして判断される)
- タイムゾーンは
+00:00
がおすすめ- インターネットに提供しているサービスは全世界から使えるので、基本はタイムゾーンいじらない方が良い
- APIは内部で持っているDBのテーブル構造をむき出しにするものではない
- IDと返すだけではなくて、そのIDの情報を返してあげたほうが良いかもよ、など
エラー
- メンテナンス時には、メンテナンス用のエラーコードとメッセージを返すだけでなく、
Retry-After
ヘッダを付けてあげると親切 - エラーは配列で返して、できるだけ多くの情報を返してあげると親切
ステータスコード
- PUTやPATCHの場合は200と共に操作した後のデータを返したほうが良い
- わかる
キャッシュ
- キャッシュが使える状態: fresh, キャッシュが期限切れ: stale
Expires
とCache-Control
を同時に使うと、Cache-Control
が優先されるCache-Control
のmax-age
の計算にはDate
ヘッダを使っている- HTTPヘッダの日付にはRFC1123を使う
- 条件付きリクエスト
- レスポンス: 最終更新日付(
Last-Modified
)か、ETag(ETag
) - リクエスト:
If-Modified-Since
かIf-None-Match
- データを取ってくることがそれなりのコストじゃないとあまりメリットがない
- Hueristic Expiration(発見的期限切れ): クライアントがキャッシュの期限を判断する
- レスポンス: 最終更新日付(
Cache-Control
のno-cache
はキャッシュをしないのではなく、検証モデルを使って必ず検証してくれということ- 中継するプロキシサーバーとかにcacheしてほしくない場合は、
no-store
(機密情報があるとか)
- 中継するプロキシサーバーとかにcacheしてほしくない場合は、
Vary
でどのHTTPヘッダがCacheに影響するかを示すことができる- 例えば、
Accept-Language
で返す言語を変えているとか
- 例えば、
- RFC5861では、
stale-while-revalidate
とstate-if-error
というディレクティブがある- staleなデータをキャッシュサーバが持っていた場合に、どうするかを指定できる
stale-while-revalidate
:max-age
で指定された秒数後もcacheを返して良い秒数- しばらく古いのを返すけど、その間に新しいcacheを取ってくる
stale-if-error
: オリジンサーバーが死んだ場合に、どれくらいcacheを返していても良いか
メディアタイプ
text/xml
とapplication/xml
どちらを使うべきかtext/javascript
は廃止されている- GitHubのrawなコードは、
text/plain
で配信されているので<script src=
で読み込んでも使えない - 自分でメディアタイプをつくるときは、RFC 6838のRegistration treeにしたがう
application/vnd.companyname.awesomeformat
と言った感じ。- Excel:
application/vnd.ms-excel
- 実際は難しいので、
application/json
で返して、適当なヘッダに入れたい情報を詰め込む
Content-Type
はきちんと設定しないとセキュリティリスクになる
APIの運用
セキュリティ
- HTTPSを使う
Content-Type
をきちんと指定する。- Content Sniffering対策に
X-Content-Type-Options: nosniff
をつける
- Content Sniffering対策に
- XSRF
- JSONハイジャック
Content-Type
を指定する- ArrayではなくObjectで返す
- XMLHTTPRequestの場合はヘッダに
X-Request-With
を付けて、<script>
からは読み込めないようにする
- 支払いの偽装
- レシートをちゃんとチェックする
X-Frame-Options: deny
- iframeで読み込んでよいか
Content-Security-Policy
<img>
や<script>
、<link>
の読み込み先として何処を許可するのか
Strict-Transport-Security
- HSTSを実現するためのヘッダ
- HTTPでアクセスしようとしても、このヘッダを受け取った以降はHTTPSで訪れるようにする
Set-Cookie
- Secure(HTTPSのときのみやり取りする)
- HttpOnly(JSでは使わない)
レートリミット
- 429
- ヘッダに残りのリミットを入れてあげると親切