技術

REST APIを作るときに考える7つのこと

副業的な案件で、REST APIを0から作ることが多いのですが、その際に気をつけていることをまとめてみます。

メソッド

リクエストメソッドはちゃんと使い分けるようにしています。

一度、すべてPOSTで作成されている案件にジョインしたことがあるのですが、閉口しました。更新はおろかGETするだけのものも何もかもPOSTでやっていました。もちろん、それでも動作自体をするのですが、やっていて頭が痛かったです。

メソッドはGETやPOSTはもちろん、PUTやDELETEも使い分けるようにしています。

そうしたほうが構築中や修正しているときにすべきこと、してはいけないことが明確になりますし、ビジネスロジックにも落とし込みやすいです。それにAPIドキュメントも見やすくなります。

POSTとPUTの使い分けは難しく、今でもたまに混乱することがあります。ソースの新規作成はPOST、更新はPUTと一般的に言われているのが混乱の元かと思います。これは間違いではないのですが、POSTは新規作成以外にもいろいろと使うケースが出てきます。

私は、既存リソースの単純な更新はPUTで、それ以外はPOSTとしてしまっています。

なのでステータスコードはPOSTでも、201と200の時が混ざっています。

エンドポイント

エンドポイント、URLはそれほ気を付けていることはありません。

ただ必要以上に長くならないようにシンプルにしています。ただ略語は使いません。一度、やたら長ったらしいエンドポイントのAPIを見たことがあります。URLでどんなAPIかを分かるようにしたかった見たいです。

URLでそんなことをする必要はありません。全体でユニークになれる程度の長さ、複雑さで十分です。

また命名規則はスネークでもキャメルでも、どちらでもいいかと思います。全体で統一されていればですが。特に決まりはないと思います。私はキャメルにすることが多い気がします。

バージョン情報を含めるとか含めないとかのベストプラクティスははっきりしていないので、どちらでも良いかと思います。私は指定がなければ、含めないことが多いです。

リクエストパラメーターの使い分け

リクエストに渡すパラメーターはクエリーパラメータ、パスパラメータ、ボディの3種がありますが、ちゃんと使い分けるようにします。

使い分けの方法は、このページの通りです。
https://qiita.com/Shokorep/items/b7697a146cbb1c3e9f0b

要点だけまとめめると

  • クエリパラメータはGETの対象をフィルタしたりソートしたりする情報
  • パラメーターは特定リソースの識別子(要はID系)
  • それ以外はリクエストボディ、主な用途は新規or更新するリソースの属性情報

という感じになります。

レスポンス

ボディ

レスポンスは特に指定がなければ、基本的にはリクエストメソッドにかかわらずオブジェクトのすべての情報を返すようにしています。が、GETでフィルターなどが設定されている場合は、その限りではありません。またDELETEは、ステータス204を返してボディには何も含めていません。

オブジェクトは1個であろうと、resultsという配列に入れて返しています。GETでプライマリキーが指定されて必ず1つのオブジェクトになる場合も、配列で返しています。

これは意見が分かれるところだと思いますが、実装時にどっちだったっけと悩みたくないので、こうしています。

その他のステータスコードやメッセージは、フレームワークによって入れたり入れなかったりしています。(この辺は、あまり重要でないので、割と適当です。後から修正を求められても影響はほとんどないので、どうとでもなります。)

ステータスコード

ステータスコードは、以下のページがまとまっていて、しょっちゅう見ています。
https://qiita.com/NagaokaKenichi/items/eb85b5fbb719d60c6627

私はステータスコードは、できるだけ少ない種類になるようにしています。

200系は200と201、DELETEのときは204も。POSTやPUTで204を返すことは基本していないです。エラーを返してしまうことが多いです。

400系は400, 401, 404あたりは使います。

500系は500を独自の例外でよく使っています。それ以外は、フレームワークやインフラが返すので、実装時は解くに意識しません。

独自のエラーコードを返すAPIをよく見ますが、指定がない限りはエラーコードなどは設定しません。例外名やエラーメッセージだけで、障害時の原因調査などは事足ります。

エラーコード対応表がないと何のことなのかわからないコードを、何でREST APIで使うのか私は理解できないです。デジタルパネルで表示可能文字数が限られるとかならわかるのですが。

ドキュメント

昔はAPIドキュメントツールがいくつか乱立していた気がしますが、今はOpenAPI(Swagger)で統一された感があります。

なので当然、ドキュメントはOpen APIで作成します。ExcelやPowerPointの表で作ることはありません。たたき台的にさっと作ってもいいと思いますが、オフィスツールのドキュメントを正とすることはありません。

Open APIはオンラインのSwagger Editorを使っています。ローカルでEditor環境を構築する方法もありますが、めんどくさいので基本やりません。セキュリティ的にどうしてもダメというときだけ構築します。

できればOpen APIのyaml作成は、JetbrainsやVSCodeでやってしまいたいですが、今の所、実用的に使えるプラグインやエクステンションはないように思います。

Open APIのyamlは、Redocでhtmlに変換します。個人的にはSwaggerのhtmlでも別にいいと思うのですが、Redocを使う現場が多かったので、それに習っています。このhtmlは、S3+CloudFrontに載せることが多いです。その場合は、変換からdeployまで、CIでやってしまいます。

Open APIのyamlからコードを生成する、もしくはコードからドキュメントを生成する方法があるみたいですが、私は使ったことありません。何かはまりポイントがありそうですし、その後の修正でコードやドキュメントを個別に修正したいことはあると思うので、逆に管理コストがかかる気がします。使っている現場も見たことありません。

セキュリティ

内部で使うAPIでも、最低限のセキュリティはかけるようにしています。

https化は可能なかぎり設定します。認証機能がない場合は、x-api-keyは設定するようにしています。

認証かkeyを設定するので、要望がない限り、IP制限はかけません。IP制限を入れると、管理コストがかかるので、できる限りやりたくありません。

APIクライアント

開発中は必須のAPIクライアント。私はPostmanを使っています。というか、APIクライアントはこれしか知りません。

前述のPOSTしかなかった現場で、curlコマンドだけでひたすらやっている人がいました。正気の沙汰とは思えませんでした。周囲の人はPostmanでやっているので、APIクライアントを知っているにもかかわらずです。まあその人は、バックエンドの専任じゃなかったので、それでも何とかなったかもしれませんが、Postmanぐらい入れたらって白い目で見てました。

Postmanは、Environmentsを駆使して、同じCollectionsを各環境ごとで使えるようにしてます。また、私一人でAPIを作っている場合でも、他の人と共有できたら便利なシーンがだいたい来るので、Collectionsはチームで作っています。(フリープランだと3人までしか共有できないのですが・・・)

まとめ

以上、REST APIを作り始めるときに考えることでした。他にも細々あると思いますが、以下の7つになりました。少しでも参考になれば幸いです。

  • リクエストメソッド
  • エンドポイント
  • リクエストパラメータ
  • レスポンス
  • ドキュメント
  • セキュリティ
  • APIクライアント