こんにちは。ランドネット広報の山崎です。
ランドネットのエンジニアをもっと知って頂くために、エンジニアブログを始めました。
今回は、前回に引き続きランドネット期待の若手エンジニア「アジキング」が書いてくれました。
今回の記事は1万文字レベルの大型記事だけど、個人的には全て理解していれば、WebAPIの基礎知識はOKだと思っていいぞ!
ー目次ー
WebAPIって何!?
-WebAPIを公開する意味
-REST APIについて
WebAPI設計
-WebAPIエンドポイント
-HTTPメソッド
・GETメソッド
・POSTメソッド
・PUTメソッド
・DELETEメソッド
・PATCHメソッド
-検索とクエリパラメータ
・ページネ―ション
・絞り込み検索
レスポンスの設計
-データ構造
-必要な分をレスポンスできるようにする
-ステータスコード
・200番台 成功
・300番台 追加で処理が必要
・400番台 クライアントのリクエストが原因
・500番台 サーバ原因
-エラーの内容をレスポンスに含める
バージョン管理
※登場する人物は、超人気アニメ「ドラ◯ンボール」とは一切関係ありません。
WebAPIって何!?
APIっていうのはApplication Programming Interfaceの略で、簡単にいうと『中身の動作までは知らないけど、どんな機能かを知ってれば外部からでも使える仕様』のこと
それのWeb版がWebAPIってことか
まあそうね。もう少しいうと『HTTPプロトコルを使ってネットワーク越しに呼び出すAPI』
とかになるけど、簡単にいうとURIにアクセスしてデータを取得したり、作成することができるの。
最近おらが使ってるサービスでTwitterと連携したら、Twitterのタイムラインが見れたけど、それもWebAPIになるのか?
そう!TwitterはWebAPIでURIを公開してるから、そのサービスではURIから情報を取得して、あなたにデータを表示しているの。
WebAPIを公開する意味
さっき例に出たTwitterがそうだけど、2006年からほとんどの機能をAPIで公開してたの。だからTwitterに関連するサービスがたくさん出たんだけど出ることで、Twitterに付加価値が生まれるの。
確かに、botとかツイート分析とかたくさんあったぞ!Mr.タサンはツイートから性格分析するために、Twitter始めたって言ってたぞ?
そういうサービスが出れば出るほど、Twitterは付加価値になるからお得なのよ。
他にも、自分たちでは手が回らなかったり、思いつかなかった機能を作ってくれる時があるの。
実際に、関連するサービスで作られた機能を、大元のサービスが取り入れる事もあるわ。
REST APIについて
少し寄り道だけど、REST APIって聞いたことある?
RESTの言葉は、2000年のRoy Fieldingさんの博士論文が始まりなの。
だけどRESTの意味は、『論文のRESTアーキテクチャの意味』と、『HTTPでアクセスできて、データ形式をJSONかXMLで返すAPIの意味』の2種類で使われるの。
じゃあ早速Web APIの設計について話してくわね!
WebAPI設計
WebAPIエンドポイント
それじゃあ、WebAPIを作る時に注意しなきゃいけないことを説明するわね。
まずAPIのURI、つまりエンドポイントを分かりやすくする必要があるの!
例えば、友達一覧を取得するAPIだったら、どれがいいと思う?
1.https://api.example.com/friends
2.https://api.example.com/service/api/friends
3.https://api.example.com/f
4.https://api.example.com/Friends/list
これは1番が使いたくなるぞ!
そうよね!2番はapiが2回入って長いし、3番はエンドポイントだけ見ても理解できない、4番はパッと見いいけどFが大文字なのが気になるわよね。
そうか!使う立場になって考えることが大事ってことなんだな!
さすがそういうこと!それじゃあ次はHTTPメソッドにいくわね。
HTTPメソッド
それじゃあ次はHTTPメソッドについてね。HTMLのformでmethod属性に指定するのは知ってるかしら?
<form action="http://example.com" method="get">
HTTPメソッドはHTTPリクエストヘッダの先頭行の最初につけられてサーバに送信されるの。
GET /v1/friends HTTP/1.1
Host: api.example.com
前にHTMLやった時にgetとかpostって付けたぞ!
それならよかったわ。そのHTTPメソッドには意味があってURIでHTTPって捉えるといいわ。
https://api.example.com/friends でGETだと友達っていうリソースを取得するってことだな!
そうよ。getやpost以外にもHTTPメソッドはあるの。
一応まだ他にもあるけど、この辺が主要かしら。それじゃあ一つずつ簡単に話すわ
GETメソッド
URIで指定された『リソースの取得』を表すわ。
もちろんAPIにもよるけどhttps://api.example.com/friendsが友達の一覧取得で、https://api.example.com/friends/123でIDが123の友達の詳細取得なんてパターンもあるわ。
一覧の取得と詳細の取得ていうのがあるのか。IDっていうのは、リソースを指定するってことでいいんだよな?
そうよ。あと、GETメソッドでデータを更新するのは、絶対にダメだからね。
PUTメソッド
PUTメソッドは、URIでリソースを指定して更新するわ。
URIは例えばこんな風にhttps://api.example.com/friends/123って123でリソースを指定して更新をするわ。
DELETEメソッド
DELETEメソッドは、URIでリソースを指定して削除するわ。
PATCHメソッド
PATCHメソッドは、URIでリソースを指定して一部更新するわ。
PUTメソッドとの違いはなんだ?
PUTメソッドは指定したリソースを一気に更新するんだけど、PATCHメソッドは、差異がある部分だけど更新するから、リソース自体が10MBとかサイズが大きいとPUTメソッドより、PATCHメソッドで差異だけ更新する方が効率がいいのよ。
検索とクエリパラメータ
それじゃあ中盤に入るわよ。検索とクエリパラメータについてよ!
さっきやったけどGETメソッドで一覧取得をやったけど、友達の数が2万人いて、それを全て取得しようとしたら大変じゃない?
そんなにたくさん取得してもほとんど使わないぞ!
そうよね、そんな時にリソースの絞り込みをするんだけどそこで条件を指定する時に、クエリパラメータを使うの。
例えば、https://api.example.com/friends?limit=20&offset=10で、limit=20とoffset=10に指定してるの。
見たことあるぞ!でもどういう意味だ?
APIによって意味は様々だけど、まずはページネーションからね。
ページネ―ション
ページネーションっていうのは、データの取得数と取得位置を指定するの。
例えば、さっきのだと『limit=20とoffset=10でデータ一覧の10番目から20個を取得する』みたいな意味になるの。
そういうことか。確かにそれなら友達が2万人いても平気だぞ!limitとoffsetっていうの名前は決まっているのか?
それはAPIによって様々だわ。よく使われるのは、
取得数にlimitと取得位置にoffset,
取得数にcountと取得位置にcursor,
取得数にper_pageと取得位置にpage,とかになるかしら。
どれを使おうか迷うぞ、、、
ちなみにoffsetとpageの意味が違うから注意ね。
offsetはアイテム数だけど、pageはper_page単位で1ページ、2ページなるからね。
例えば11アイテム目からを指定する場合はこんな感じになるの。
per_page=5&page=3
limit=5&offset=10
per_pageの指定が1ページあたり5件ってことでpageで3ページ目からっていうことと、limitが5件取得ってことで、offsetが10件目からってことか?
そう!offsetが10件目?って思ったかもしれないけど、offsetは0からスタートするから問題ないの。
好みもあるけど、私はlimitとoffsetの方が使いやすくて好きだわ。
絞り込み検索
それじゃあ、次は絞り込み検索の話に移るわね。
ページネーションだけじゃなくて、色んなパターンで絞り込みたい時があると思うの。
確かに、名前とかメールアドレスとか複数の想定があるぞ!
そういう時は大体。クエリパラメータの名前には要素名、値には絞りこむ値を指定するの。
例えば、こんな感じになるわ。
https://api.example.com/friends?first-name=sita&last-name=Be
そうか!苗字と名前で検索してるっちゅーことか!
そう。ただ条件が1つだったり、全文検索の場合はqが使われることが多いわ。
https://api.example.com/friends?q=Besita
qっていうのはqueryの略よ!
レスポンスの設計
それじゃあ、リクエストについてやったから今度はレスポンスについてね。
レスポンスだけどまずデータフォーマットは基本的にはJSONにするって考えて問題ないわ。
そうなのか?おらXMLとか聞いたことあるぞ!
前はXMLが主流だったんだけど、今ではJSONがデファクトスタンダードになってるから、必要があればXMLにも対応するって感じになるわね。
じゃあ、おらはとりあえずJSONで作るぞ!
データ構造
エンドポイントの時もそうだったけど、レスポンスも使いやすいように返さないといけないの。
例えば、この例でどっちが使いやすいと思う?
例1
例2
①番はIDなんだろうけど、またリクエストしないといけなくなりそうだから ②番の方が良さそうだぞ!
そう!友達一覧取得する時は普通に名前とかも当然欲しいよね。
だから①だとIDからまた取得することになって、ユーザも大変だしサーバの負荷も上がるから、いいことないの。
でもどこまでレスポンスすればいいのか、難しいぞ?
そうね、そういう時はユーザが選べるようにすれば問題ないわ!
必要な分をレスポンスできるようにする
一度にたくさんのデータをレスポンスすれば楽だけど、、ユーザは必要じゃないデータをレスポンスされても、ダウンロードにも時間がかかって不便よね。
だからユーザ自身で選べるようにクエリパラメータで指定することができるようにするの。
https://api.example/friends/123?fields=name,age
なるほど!fieldsで必要なデータだけになるのか!
そう!fieldsを指定しなかったら、全てを返すとかにしておけばユーザにも使いやすくなるわよね。
ステータスコード
それじゃあ、HTTPに関わってくるところだけど、ステータスコードもやっちゃうわ!
ステータスコードなら少しわかるぞ!404とか500とかのやつで合ってるか?
そう!リクエストがサーバによってきちんと処理されたのかを表すステータスのこと。
他にも種類がたくさんあるから、表にするわ。
こんなにあるのか!おら覚えらんねーぞ!
覚えなくても都度調べれば大丈夫よ!まだ他にもあるから、簡単に補足するわね。
【200番台 成功】
200は、一般的よね。
201は、POSTメソッドが成功してリソースが新規作成されたら返されるもの。
202は、リクエストが非同期で実行されて、処理は受け付けたけど完了はしていないの時に使われるわ。
204は、DELETEメソッドでリソースが削除された時に使われるの。
【300番台 追加で処理が必要】
300番台は、リダイレクトが一般的よね。
URIのアクセスに対して、目的のアクセスは別のURIに変わっていることを伝えるために使用するステータスコード。
ただ、これはWebAPIで使うことはおすすめしないわ。
ユーザがリダイレクトの対応をしてないと、クライアントが動かなくなったりするからね。
リダイレクトは本当に必要な時にだけって覚えておくぞ!
【400番台 クライアントのリクエストが原因】
これは、クライアントのリクエストに原因がある番号ね。
401は、認証エラーでリクエストした人を認識できない時だわ。
403は、認可エラーでリクエストした人にはアクセス許可されていない時。
あとは、なんとなく理解できるかしら。
ちなみに400は、他の400番台で表せない時に使う『その他』になるの。
クエリパラメータに問題がある時なんかに使うわよ。
【500番台 サーバに原因】
これは、開発者はよく見るかしら。
サーバ側のバグが原因でエラーが発生して処理が止まっているから、きちんと監視することが大切ね。
503は、システムメンテナンスだったり、サーバが過負荷でサーバが止まっている状態のことよ。
500がでた時は、通知がいくようにしてるぞ!
エラー内容をレスポンスに含める
ステータスコードをやって、400番台でユーザにクライアントの原因を伝えることができることがわかったわね。でも、404のNot Foundをレスポンスする時に『何がNot Foundなのか』も伝えるべきなの。
確かに、おらだったら404だけ返されても何がNot Foundなのか分からないぞ。
そう!だから、内容を教えてあげる必要があるの。今回は例にTwitterとGithubを使うわ。
Github
ちなみに、Twitterは配列になっていてエラーが複数合った場合は、複数レスポンスしてくれるの。
開発者に取ってはありがたいわよね。
バーション管理
APIを公開していると、そのAPIをいきなり変更するとユーザは困るでしょ。
でもAPIを、改善していきたいっていう時には、新しい改善したAPIは別のエンドポイントをするの!
それなら元々使ってるユーザは困らないそうだぞ!
そう!こうやってやるの!
https://api.example.com/v1/friends
APIのパスの先頭にv1っていうバージョン1っていうのを示しておくのよ。
そうか!それじゃあ更新したらv2に上げていけばいいのか!
そうよ!ただ後方互換性を保てる時は、できる限りバージョンを上げずにしない方が
APIの管理が増えないから、互換性を保てない時にあげるべきだわ。
確かに、増えすぎると後で大変な気がするぞ!
でもAPIのバージョンを上げた時は、古い方はいつまでサポートすればいいんだ?ずっとサポートしてるのもおら大変だぞ。。。
いい質問ね!ただそれは明確な決まりはないわ。
だけど古いほうのAPIを使っている人に移行する期間を設ける必要があるわ。いきなり終了するとユーザは困るからね。
Twitterの場合だと6ヶ月以内に終了するってアナウンスをしてから停止してるわ。最低でも6ヶ月は、設けると安心だと思うわ。
半年か!時と精神の部屋だったら、半日だ!
そうなのね笑
あとは、事前にAPIのサポート期間をドキュメントとかに記載しておくっていうのもありね。
事前に伝えておけば、伝わってないっていうことは減りそうだぞ。
APIの提供が終了したら、エラーメッセージで提供は終了した旨を伝えると、さらに親切よ。
シノブルマ、説明ありがとな!
参考までに、この本はすっげー分かりやすいから、おすすめだぞ!
https://www.amazon.co.jp/Web-API-Parts-%E6%B0%B4%E9%87%8E-%E8%B2%B4%E6%98%8E/dp/4873116864
気軽な情報交換や相互理解に活用できます