4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

API仕様書に求めるものについての考察

Last updated at Posted at 2020-12-24

この記事は ただの集団 Advent Calendar 2020 の25日目の記事です。

目次

  • 概要
  • 背景
  • 今回想定するユースケース
  • API仕様書での記述
  • テスティングツール
  • まとめと所感
  • 参考資料

概要

サーバーサイドエンジニアとしてWeb APIの開発を行うにあたって、API仕様書をもとに開発を進めています。
仕様書と実装コードを書きながらふと、以下のようなことを考えていました:thinking:

  1. リクエストによってレスポンスが微妙に違うパターンを表現したい
  2. 実装したAPIアプリケーションが仕様通りに動作しているかを検証したい (具体的にはレスポンスのJSON Schema Validationをしたい)

2.については「OpenAPIからソースコードを自動生成して開発する」というルールに則っていれば、理論上両者のschemaがずれることは無いのですが、実挙動を手軽に確認・保証する手段があれば安心感が増すよなぁと思った次第です。

背景

昔の勉強会で Apiドキュメンテーションツールを使いこなす【api blueprint編】 を発表したのですが、当時はまだSwagger2だったこともあり、API Blueprintをメインで使っていました。
現在はOpenAPI3がデファクトになりつつあると感じており、実開発での仕様書もOpenAPIで記述しています。

そういった環境の変化の過程で取り巻くツール群もガラリと変わったため、キャッチアップも兼ねて調べてみることにしました。

(余談)
今でも個人的にはAPI Blueprintを評価しているのですが、OpenAPI周りのツールが強力なため (特にOpenAPI Generator)、 なかなか太刀打ちできないかなぁ...といったところです:cry:

今回想定するユースケース

「URLパラメータにxxxが含まれている場合のみ、レスポンスのこのフィールドは必ず存在する」といったケースです。
以下のような例を考えてみます。

  • ユーザー情報を取得するAPIがある (ex: GET /user/{id})
  • レスポンスのフィールドにgenderageが存在するが、デフォルトでは返さないフィールドである
  • これらはURLパラメータに明示的に指定された場合のみ、返すフィールドである (ex: GET /user/1?attr=gender,age)

API仕様書での記述

API Blueprintの場合

API Blueprintでは、リクエスト × ステータスコード × レスポンスの3つの組み合わせを複数記述できるため、柔軟性があります。

# Resource [/resource]
## Create Resource [POST]

+ request A
        ...

+ response 200
        ...

+ request B
        ...

+ response 200
        ...

+ response 500
        ...

+ request C
        ...

+ request D
        ...

+ response 200
        ...

しかし、記述量も多くなり複数のブロックに跨ってしまうため、柔軟過ぎると感じることもしばしば。

OpenAPIの場合

OpenAPIではリクエストの複数パターン記述ができないため、こういったユースケースを実現することは難しそうです。
descriptionexamplesに記載することで情報量はカバーできますが、実際の挙動との関連性を示すには少し弱いと感じます。

レスポンスについては、discriminatorを使えば複数記述はできるようです。しかし、

Adds support for polymorphism

とあるようにその概念に沿った使い方かというと、ちょっと違うかもしれません。

テスティングツール

dredd

https://dredd.org/en/latest/
API Blueprint向けメインとして用意されています。各言語でのhook操作も記述できたりと、フルスタックなツールです。
実はこのdredd、OpenAPIもサポートしているのですが、version3はexperimentalであるため現段階では実用的であるとは言えません...残念:sob:

karate

同Adventカレンダー18日目の記事 APIのE2Eは カラテ を使うべし。古事記にもそう書いてある。 でも紹介されているツールです。
ドキュメントにあるように、一応Schema Validationが可能ではあるようです。

* def oddSchema = { price: '#string', status: '#? _ < 3', ck: '##number', name: '#regex[0-9X]' }
* def isValidTime = read('time-validator.js')
When method get
Then match response ==
  """
  { 
    id: '#regex[0-9]+',
    count: '#number',
    odd: '#(oddSchema)',
    data: { 
      countryId: '#number', 
      countryName: '#string', 
      leagueName: '##string', 
      status: '#number? _ >= 0', 
      sportName: '#string',
      time: '#? isValidTime(_)'
    },
    odds: '#[] oddSchema'  
  }
  """

しかし、既にOpenAPIのyamlがあるのだから、そのファイルを使って検証したくはあります。
karateは細かなSchema Validation向けのツールではないと思うので、色々混ぜ込まないほうが良いのかもしれません。

その他のツール

いくつか探してみましたが、OpenAPIのversion3に対応していて使いやすそうなツールは見つかりませんでした。ご存じの方居ましたら、ご教授願いたいです:bow:

目的は違いましたが、prismのValidation Proxyは使えそうだなと感じました。

まとめと所感

API仕様書にどこまで書くのが良いかについては現在も試行錯誤中ですが、あまり細かすぎることは書かないほうが良いかなと考えています。
ツール側の都合で仕様書のほうが変な制約を受ける、というのも正しくないでしょうし。
場合によっては、externalDocs等を使って棲み分けるほうが開発者にとっても理解しやすいのかもしれません。

API仕様書周りは久しぶりに時間を使って調べましたが、OpenAPIも機能が豊富で奥が深いですね。
個人的にdreddには愛着があるので応援...もとい、contributeしていけるように努力したいと思いました:muscle:

参考資料

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?