概要
API Gatewayの設定にOpenAPIを連携できないか検討した。
OpenAPIのJSONから型情報を読み込む形で実装してみたメモを残す。
検討
cdk - openapi-definitionを読むと、定義はすべてOpenAPIのほうに書く必要があるもよう。また、OpenAPIは3.1は使えず3.0か2.0を使う必要がある。
すべてのリソースとメソッドは OpenAPI 仕様ファイルの一部として定義する必要があり、CDK を介して追加することはできません。これは、これらのプロパティの重複や潜在的な混乱を防ぐためです。
こちらの記事で「OpenAPI定義にAWS用の設定値を記載するのが嫌だ」と言っているように、OpenAPIとAWSの設定は分けて管理したい。
記事中ではopenapixを使用しているが、1年更新がないのが不安。
型定義をOpenAPIから取り込む方法を考える。
構造
OpenAPIのフォルダとcdkのフォルダを分けて作成する。
以下はイメージ。
- openAPI
- openapi.yaml # ... OpenAPIの定義ファイル
- cdk
- data
- openapi.json # ... OpenAPIの定義ファイルをJSONとしてエクスポートした生成ファイル
- lib
- stack.ts
StackファイルにOpenAPIの定義を適用する
OpenAPIから、Stackで使いたい情報をピックアップして記載する。
openapi: 3.1.0
paths:
/tags:
put:
summary: タグ情報永続化
/scenario/{scenarioId}/tags:
get:
summary: シナリオタグサマリー取得
/scenario:
get:
summary: シナリオ一覧取得
これをもとに、下記のように補完が効くようにする。
yamlからjsonへの変換は、package.jsonでスクリプトにしている。(openapi-init)。
Stackを書く前に実行し、OpenAPIの情報を反映する必要がある。
// 省略
import openApi from '../data/openapi.json';
type OpenAPI = typeof openApi;
type Paths = OpenAPI['paths'];
export class KartaGraphRESTAPIStack extends core.Stack {
private apiRoot: apigateway.Resource;
// 省略
private createAPILambdaResource<T extends keyof Paths>(path: T, method: keyof Paths[T], props: Partial<NodejsFunctionProps>) {
const methodStr = method as string; // 型が合わない(string | number | Symbol とみなされる)ので本来の型であるstringキャスト
const lambda = this.createLambda(
{
...props,
// summary は 必ず入力するものとして、 any で逃げる
description: (openApi as any).paths[path][method].summary,
},
`${methodStr}-${path}`,
);
const methodOptions = this.createMethodOptions({
'method.request.header.Content-Type': true,
});
this.getResource(path).addMethod(methodStr.toUpperCase(), new LambdaIntegration(lambda), methodOptions);
}
// 省略
上記のようにジェネリックを使って、補完をできるようにした。
ただ、メソッドの中ではas string
やas any
を使っているのが分かるように、うまく型予測することはできなかった。
パスからリソースを作る部分については、パスを分割し、マップでキャッシュするヘルパー関数を作っている。(同じリソースは2回作ろうとするとエラーとなるため、すでにあるリソースは再利用する必要がある)
これでデプロイした結果が下記。
OpenAPIの情報をStackに反映することができた。
参考
cdk - openapi-definition
cdk - SpecRestApi
openapi-down-convert
OpenAPI を使用した REST API の設定
OpenAPI × AWS CDK × APIGateway でRest APIを管理する
AWS CDKで作ったAPI Gateway + LambdaからOpenAPIドキュメントを生成してみた
AWS CDKを使ってAPI Gateway(HTTPAPI)+LambdaをOpenAPIで定義してデプロイする
APIGatewayをCDKで構築するコツ
【TypeScript】Utility Typesをまとめて理解する
【TypeScript】Yaml を読み込んで(無理やり)型付けする