AWS APIGateway × OpenAPI (2. Proxy編)
2022-07-26
OpenAPI定義をCDKのREST API定義に統合するライブラリを開発しています。 これはライブラリの開発過程を紹介するシリーズのブログ投稿第2弾です。
背景
本シリーズの最初のブログ投稿で、以下の課題を残しました。
RestApi
との互換性はどうやって実現するか?
RestApi
を再利用しないのは大変すぎるので、サブクラスを書くことにします。
インターフェイスの定義
AWS Cloud Development Kit (CDK)のAPIを拡張する前に、最低限のインターフェイスを定義しましょう。 以下のセクションに現れるインターフェイスやコードはシンプルにするために私のライブラリから部分的に抽出し改変したものなのでご注意ください。 完全な定義はGitHubレポジトリにあります。
IRestApiWithSpec
IRestApiWithSpec
はIRestApi
の拡張です。
IResourceWithSpec
IResourceWithSpec
はResource
の拡張*です。
* IResource.addResource
を正しく拡張するには、IResourceWithSpec
はIResource
ではなくResource
を実装していなくてはなりません。
一方で、IRestApiWithSpec.root
はResource
ではなくIResource
を実装しなければならないので、IRestApiWithSpec
のroot: IResourceWithSpec
定義は限定的すぎます。
しかし、Resource
の公開インターフェイスとIResource
は私の知る限り同じなので問題にはならないはずです。
ResourceOptionsWithSpec
ResourceOptionsWithSpec
はResourceOptions
の拡張です。
MethodOptionsWithSpec
MethodOptionsWithSpec
はMethodOptions
の拡張です。
BasePrameterObject
は外部ライブラリOpenApi3-TS[1]から借りてきました。
当初はMethodOptions.requestParameters
の定義を以下のようにオーバーライドするつもりだったのですが(前のブログ投稿の例参照)・・・
requestParameters?:;
MethodOptionsWithSpec
をMethodOptions
に代入できなくしてしまうのでこの試みは失敗しました。
ということで回避策としてrequestParameterSchemas
という新しいプロパティを導入しました。
RestApiを拡張する
RestApi
を拡張するのは単純です。
言語機能(extends
)を使いRestApi
のプロパティをオーバーライドするだけです。
単純化のためRestApiWithSpecProps
の詳細は省きます。
ご興味がありましたらGitHubレポジトリをご参照ください。
ここで、疑問はどのようにroot
を実装するかです。
親クラス(RestApi
)のroot
をラップするのが良さそうです。
ではどうやってラップしましょうか?
ほとんどのリクエストをRestApi
のroot
に転送するだけのラッパークラスを書きましょうか?
大量のBoilerplate(定型的なコード)が発生しそうです。
それならProxy
がニーズにもっとマッチしそうです。
rootにProxyをかませる
root
用のProxy
を書くのはとても簡単です。
ハンドラオブジェクトのget
関数を実装するだけです。
// root: IResource
;
残念ながら、TypeScriptは上記コードでProxyをかませたオブジェクトをIResourceWithSpec
だと認識せずエラーになります。
Proxy
コンストラクタのデフォルトのTypeScript定義が以下のようになっているからです。
declare global
この問題に対処するため、Proxy
コンストラクタがtarget
とは違う型を生成することができるように定義を拡張できます。
StackOverflowのこちらの投稿[2]がまさに答えです。
ということで以下の宣言を追加するとTypeScriptエラーが解決します。
declare global
Resourceを拡張する
Resource
を生成するたびに、節「rootにProxyをかませる」で記述したようにProxy
でラップする必要があります。
ということで既存のどんなIResource
でもIResourceWithSpec
の機能でラップできるファクトリーメソッドaugmentResource
を導入しました。
このファクトリーメソッドはroot
にも適用可能です。
上記のコードはシンプルにしてあり、実際の定義はGitHubレポジトリにあります。
まとめ
このブログ投稿では、CDK APIの拡張を簡単にするためにProxy
を導入しました。
Proxy
に関するTypeScriptのエラーを回避するトリックも紹介しました。
次のブログ投稿では、いつOpenAPI定義ファイルを出力するかという課題に挑む予定です。
Reference
-
OpenAPI 3の仕様そのものに対するTypeScriptバインディング。
-
How to use Proxy
with a different type than T as argument? - Answer