FORCIA CUBEフォルシアの情報を多面的に発信するブログ

OpenAPI + Express.js + TypeScriptでAPI開発するTips

2020.12.14

アドベントカレンダー2020 テクノロジー

FORCIAアドベントカレンダー2020 14日目の記事です。

事業開発部の龍島です。皆さんschema firstな開発してますか?

フォルシアではwebアプリケーション開発にサーバサイドはExpress.js + TypeScript、クライアントサイドはNext.js(React.js) + TypeScriptを用いており、間をつなぐAPIインターフェースの定義にOpenAPI Specification(swagger)を用いてschema firstな開発を行っています。

ここ2年ほどschema firstな開発を行ってきましたがAPIのインターフェース定義を初めに設計することでサーバサイドとクライアントサイドの開発を複数人で同時に進めることができ、近年のフォルシアでも大規模化してきているwebアプリケーション開発に適した手法だと感じています。

web上にはschema firstで開発していこう!という記事は多くありますが、実際にOpenAPIの仕様を満たすAPIを実装する方法を解説した記事は少ないです。
社内でもOpenAPI周りの仕組みは約2年前に情報のない中手探りで整備したものですが、苦労した部分もありつつ、ある程度上手くワークしていると思うので、これから導入を検討している方に向けて紹介したいと思います。
schema first開発が世の中に浸透してきた今ではライブラリも充実してきているため、現状の仕組みに加えて新しいライブラリの導入で今ならこうしたほうが良さそうという点も補足していきます。

advent_calendar_20201214_1.png

今回紹介する内容の全体像を図にしてみました。①~③の箇所で利用している内容について、詳細をみていきましょう。

1. リクエスト、レスポンスのTypeScriptの型を自動生成

一番メリットを享受しやすいのはTypeScriptの型生成の部分かと思います。
フォルシアではsw2dts を用いてOpenAPIの定義からリクエスト、レスポンスの型定義を自動生成しています。sw2dtsはOpenAPI定義のJSONからdtsファイルを出力するdtsgeneratorのラッパーですが、dtsgeneratorでできなかったGETのクエリパラメータも型定義として出力できるようになっています。/post/:idなどのようにpathにパラメータが含まれる場合は定義が出力できないので注意が必要です。
現在ではopenapi-typescriptというライブラリが出てきており、クエリパラメータもOpenAPI3系であれば上手く出力できるようなので、置き換えが可能そうです。

2. リクエストパラメータのバリデーション機能を自動生成

型定義を生成しても、リクエストパラメータに関しては定義通りに叩いてもらえるとは限らず、パラメータをバリデーションする必要があります。バリデーションを手作業で実装すると、定義と乖離してしまう可能性があります。二重管理を防ぐためOpenAPIの定義からバリデーションを生成したいです。
整備当時はこの要求を満たす良いライブラリを見つけられず、expressの標準的なバリデーションライブラリのexpress-validatorを利用して実現しました。OpenAPI定義のJSONからexpress-validatorのschema validation機能の形式のオブジェクトを生成するスクリプトを内製しています。基本的なバリデーションは成功し、内製のため自由度もあり、ある程度上手く運用できているとは言えますが、default値の設定など対応できていない部分もあり、可能なら外部のライブラリで巻き取ってしまいたいとも感じています。

現在では express-openapi-validatorという目的に完全合致したライブラリがあり、Express.jsのmiddlewareとして導入することで定義通りにバリデーションをしてくれるようです。現在の内製スクリプトの仕組みを置き換えるものとしてフォルシアでも導入を検討しています。

3. 実際のレスポンスが定義通りかチェックするテストを自動生成

前述のsw2dtsを用いてレスポンスの型定義は作れているものの、DBから取得してきた値などでTypeScriptの型定義が100%信用できない場面もあり、実際のレスポンスが定義通りであることを保証するテストも導入しています。openapi-response-validatorはオブジェクトがOpenAPIの定義を満たしているかチェックすることができるので、frisby.jsで実際にAPIを叩き、レスポンスが仕様を満たしているかをテストしています。

番外 OpenAPIの定義をいい感じに書く

API開発とは少しずれますが、以前OpenAPI(Swagger)の定義をいい感じに書くTipsを記事にしています。よろしければご覧ください。

まとめ

以上がフォルシアでのOpenAPIの定義に準拠するAPI開発で導入している仕組みです。まとめると下記のようになります。

  1. リクエスト、レスポンスのTypeScriptの型をopenapi-typescriptなどを用いて自動生成
  2. 実際のリクエストパラメータの値をexpress-openapi-validatorなどを用いてバリデーション
  3. 実際のレスポンスの値をopenapi-response-validatorなどを用いてテスト


TypeScriptの世界と実際のリクエスト、レスポンスの両方がOpenAPIの定義と一致していることを保証する仕組みを作ることで、定義と実装の乖離を防げます。

OpenAPIを用いた開発は一度環境を整備してしまえば、特にクライアント側とサーバ側を同時に開発するようなプロジェクトでかなり有効です。今回改めて周辺ライブラリを調査することで改善できそうな点も見えてきたので、フォルシアのschema first開発環境もUPGRADEしていきたいと思います。

この記事を書いた人

龍島 広人

事業開発部所属。
2016年新卒入社 最近健康診断でコレステロール値で引っかかったため魚や大豆、野菜を中心とした食生活に改善中。