たいさブログ

taisa's engineer blog

JavaScript

Web API The Good Partsをじっくり読み返したら新しい気づきがあった

投稿日:2018年3月31日 更新日:

Pocket

Web API The Good Partsの読書会をする機会があって、2章と3章をじっくり読み返した。2014年の発売後にも読んでいたけど今あらためてじっくりと読み返したらその時は気づかなかった新しい気づきがあってとても参考になった。

以下は「3章 レスポンスデータの設計」の読書メモ

データフォーマット

  • JSONにするのが良い
  • ほとんどがJSONにしてるがAmazonだけがXMLだけになっている

データフォーマットの指定方法

  • クエリパラメータを使う方法
  • 拡張子を使う方法
  • リクエストヘッダでメディアタイプを使う方法

最もお行儀のよい方法はメディアタイプを指定する方法だが、ほとんどの大手サービスはクエリパラメータを使う方法を使っている

クエリパラメータを使う方法のメリット

  • 手軽で見た目にわかりやすい
  • 初心者にやさしい
  • 省略可能である

リクエストヘッダでメディアタイプを使う方法が良いと思っていたけど、クエリパラメータを使う方法の方が確かに分かりやすいしテストもしやすいなという感想をもった

JSONPの取り扱い

JSON with paddingの略で以下のようにJSONにそれをラップするJavaScriptを付け加えたものを指す

callbackという関数はJSONPを呼び出したscript要素の存在するページにあらかじめ用意しておく必要がある

なぜこの方法が考案されたか

  • XHTTPRequestは同一生成元ポリシーの制限によって、同じ生成元(ドメインなど)へのアクセスしか行うことができないから
  • でもscript要素は同一生成元ポリシーの規制の対象外のため、JSONをscript要素を使ってJavaScriptとして読み込めば、ドメインを超えたアクセスが可能

ただし、JSONPはGETしか使えずPOSTを利用できない、HTTPヘッダを独自に設定することができないなどの問題はある

JSONPをサポートする場合の作法

グローバル変数に格納する方法もある

コールバック関数の名前はクエリパラメータを指定できるようにするのが一般的

関数名を指定可能にすると良い理由は2つある

  • コールバック関数がグローバル空間に置かれるため、コールバック名を決め打ちにしてしまうと、その名前がページ内の他の関数と衝突する可能性がある
  • 同じAPIを複数買いアクセスする場合に、それぞれを異なるコールバック関数にすることで、返されたデータがどのリクエストによって得られたものか区別することができるようになる

JSONPを配信する際の注意点は、JSONPはJSONではなくJavaScriptなので、Content-Typeヘッダにセットするメディア・タイプがapplication/jsonではなくapplication/javascriptになる点

JSONPとエラー処理

大きな問題点として、サーバがエラーを返した際に正しく反応できないというものがあるので、エラーが発生しても200のステータスコードを返し、レスポンスボディでエラーの内容を表現することでこれに対応する

JSONP箇所については今使うケースがほとんどないので軽く読み飛ばした

データの内部構造の考え方

APIのアクセス回数がなるべく減るようにすることを考える必要がある

レスポンスの内容をユーザが選べるようにする

  • すべてのAPIでできるかぎり多くのデータを返す
  • 送受信されるデータのサイズはできるだけ小さい方が望ましい

上記の矛盾を解決する方法

  • 取得する項目を利用者がクエリパラメータなどで選択可能にするという方法
  • あらかじめいくつかの取得する項目の量の異なるセットを用意しておく

例) AmazonのProduct Advertising APIではレスポンスグループとして「Small」「Medium」「Large」を用意している

エンベローブは必要か

エンベロープ(封筒)例)

  • 冗長であるためやるべきではない
  • HTTPがエンベロープの役割を果たしている
  • JSONPを使う場合はHTTPヘッダにセットできないのでエンベロープを利用した方が便利

データはフラットにするべきか

  • なるべくフラットにしたほうがよいけど、階層構造を持ったほうがわかりやすい場合もある(GoogleのJSON Style Guide)

無駄に階層構造をもつとJSONのデータサイズが大きくなるから不要な階層化はするべきでない

配列とフォーマット

  • JSONオブジェクトは順序が考慮されない
  • JSONには配列の仕様があるからそれを利用する
  • 配列をそのまま返す方法とレスポンス全体をオブジェクトにしてその中に配列を入れる方法がある

返す方法はどちらでもさほど変わらないが筆者は以下の理由からオブジェクトで包む方法をすすめている

  • レスポンスデータが何を示しているものかがわかりやすくなる
  • レスポンスデータをオブジェクトに統一することができる
  • セキュリティ上のリスクを避けることができる

トップレベルが配列であるJSONは、JSONインジェクションという脆弱性に対するリスクが大きくなるという問題を抱えている

配列の件数、あるいは続きがあるかをどう返すべきか

取得するデータが全体で何件あるかという情報は処理が重くなりがちで工夫が必要になるので、本当に件数を返すことが必要かは見極める必要がある

‘続きがあるのか’を取得するために全体の件数を使わず、20件返すために最大21件取得してみて21件取得できれいれば’続きがある’と返す方法もある。そして、続きがあるかという情報を「hasNext」といった名前で結果に含める

‘続きがあるのか’を返すだけでなく、次のページのURIや次のページに必要なパラメータを返すパターンもある

各データのフォーマット

各データの名前

  • 多くのAPIで同じ意味に利用されている一般的な単語を用いる
  • なるべく少ない単語数で表現する
  • 複数の単語を連結する場合、その連結方法はAPI全体を通して統一する
  • 変な省略形は極力利用しない
  • 単数形/複数形に気をつける

適切な名前を選ぶのが大変な場合は ProgrammableWeb などを参考にする

キャメルケースかスネークケースかスパイナルケースか

  • JSONではキャメルケースがよいとされている
  • 命名規約を守っていないAPIでスネークケースを利用しているAPIはたくさんある

「スネークケースのほうがキャメルケースよりもずっと読みやすいという研究結果もある」ので一概には言えないが、統一されているのが大事

自分もスネークケースを使っていたしこれからもスネークケースを使うかなという感想をもった

性別のデータをどう表すか

文字列で返す方法と数値に置き換えて返す方法があるが文字列で返す方が圧倒的に多い

フィールド名の選択

生物学的な性別が必要な場合(医療系など)はsexを使い、そうでなければ(SNSやECなど)genderを使う

日付のフォーマット

  • RFC 3339を使うのが良い

インターネット上で用いる標準形式として決められたものだから

大きな整数とJSON

大きな整数はJavaScriptでは誤差がでてしまうので、文字列として返し問題を回避する

エラーの表現

ステータスコードでエラーを表現する

  • HTTPレスポンスの先頭行につける
  • 200や404など

  • 100番台:情報
  • 200番台:成功
  • 300番台:リダイレクト
  • 400番台:クライアントサイドに起因するエラー
  • 500番台:サーバサイドに起因するエラー

エラーの詳細をクライアントに返す

  • レスポンスヘッダに入れる方法とレスポンスボディに入れる方法があるがレスポンスボディに入れる方法で問題ない
  • レスポンスボディの内容はエラーを配列で返すと複数のエラーが同時に発生した場合に合理的な方法になる

エラー詳細情報には何を入れるべきか

  • 詳細エラーコードの付け方はAPIごとに勝手に決めて良い
  • ステータスコードと区別する為に4桁の数字にすると便利

エラーの際にHTMLが返ることを防ぐ

  • 500、503、404などのエラーでHTMLが返ることが多い

メンテナンスのステータスコード

  • メンテナンスする場合は503を返す
  • Retry-AfterというHTTPヘッダを使ってメンテナンスが終わるのを示す

意図的に不正確な情報を返したい場合

  • SNSやチャット系のサービスの場合はブロック機能などがあるので正確な情報を返さないパターンもある
Pocket

-JavaScript
-

執筆者:

関連記事

おれ的フロントエンド速習コース

3ヶ月でフロントエンド向上させるにあたって取り組んだことを書く。 フロントエンドって? どこからどこまで?何を指してる?と引っかかる人がいるかもしれないけどそこら辺はなんとなくお察しください。 3ヶ月 …

ECMAScript 6を触ってみる – モダンになった文法

WEB+DB PRESS Vol.87は、@t_wadaさんの言うとおりES6を速習するのにとても良い書籍だと思う。個人的には「JavaScript: The Good Parts ―「良いパーツ」に …

「はじめてのフロントエンド開発」という共著本を出版しました

『React,Angular,Vue.js,React Nativeを使って学ぶ はじめてのフロントエンド開発』という共著本を2018年5月9日に出版しました。 自分はこの中の第3章の環境構築を担当し …

「slideship Tech Dive vol.1 フロントエンド特集」でLTしてきた

connpassリンク slideship Tech Dive v1.0 #React / ReactVR / #VueJs Webフロントエンド特集 「slideship Tech Dive v1. …

node-nightlyを使ってwebpackをデバッグする

webpackに限らずだけどnode-nightlyを使うと簡単にデバッグすることができる Debugging When contributing to the core repo, writing …