English / 日本語
Amazon API Gateway (API Gateway)のREST APIとそのOpenAPI定義を@codemonger-io/cdk-rest-api-with-specで一度に記述。
AWS Cloud Development Kit (CDK)のパーツを使ってREST APIとそのOpenAPI定義を一度に書いてしまいたい方には役に立つかもしれません。 詳しくは「背景」をご覧ください。
Node.js v12かそれ以降をインストールしてください。 このライブラリはNode.js v22.xで開発しました。
このライブラリはCDKバージョン2 (CDK v2)向けに実装されており、CDKバージョン1には対応していません。
また、aws-cdk-libはv2.201.0以降が必要です。
このレポジトリを依存関係(dependencies)に追加してください。
npm install https://github.com/codemonger-io/cdk-rest-api-with-spec.git#v0.4.1このライブラリはCDK v2プロジェクトで使用することを想定しており、以下のモジュールはdependenciesではなくpeerDependenciesに含んでいます。
CDK v2プロジェクトで使っている限り、これらを別途インストールする必要はないはずです。
mainブランチにコミットがプッシュされるたびに、開発者用パッケージがGitHub Packagesの管理するnpmレジストリにパブリッシュされます。
開発者用パッケージのバージョンは次のリリースバージョンとハイフン(-)と短いコミットハッシュををつなげたもので表現されます。例、0.4.1-abc1234 (abc1234はパッケージをビルドするのに使ったコミット(スナップショット)のコミットハッシュ)。
開発者用パッケージはこちらにあります。
開発者用パッケージをインストールするには、最低限read:packagesスコープのクラッシックGitHubパーソナルアクセストークン(PAT)を設定する必要があります。
以下、簡単にPATの設定方法を説明します。
より詳しくはGitHubのドキュメントをご参照ください。
PATが手に入ったら以下の内容の.npmrcファイルをホームディレクトリに作成してください。
//npm.pkg.github.com/:_authToken=$YOUR_GITHUB_PAT
$YOUR_GITHUB_PATはご自身のPATに置き換えてください。
プロジェクトのルートディレクトリに以下の内容の.npmrcファイルを作成してください。
@codemonger-io:registry=https://npm.pkg.github.com
これで以下のコマンドで開発者パッケージをインストールできます。
npm install @codemonger-io/cdk-rest-api-with-spec@0.4.1-abc1234abc1234はインストールしたいスナップショットの短いコミットハッシュに置き換えてください。
aws_apigateway.RestApiの代わりにRestApiWithSpecをインスタンス化してください。
const api = new RestApiWithSpec(this, 'example-api', {
description: 'Example of RestApiWithSpec',
openApiInfo: {
version: '0.0.1',
},
openApiOutputPath: 'openapi.json',
// ... other options
});CDKスタックを合成すると、OpenAPI定義を含むopenapi.jsonファイルが作成されます。
より詳しくは「使用例」と「APIドキュメンテーション」をご参照ください。
実際に動くサンプルもexampleフォルダにあります。
最近、API Gatewayで作成したREST APIのOpenAPI定義を書くべきだなぁという思いが強くなっていました。 私の知る限り、API Gatewayで作ったREST APIのOpenAPI定義を得るには2つの選択肢があります。
追加のドキュメンテーションなしでは、API GatewayからエクスポートされたOpenAPI定義には制約が全然かかっておらず使い物になりません。 REST APIのすべての構成要素に個別にドキュメンテーションリソースを追加しなければなりません。 REST APIの構成要素を作るのと同時にドキュメント作成もできるとよい気がします。
私はCDKのパーツを使ってAPI GatewayのREST APIを記述するのに慣れています。 以前、素のCloudFormationテンプレートでREST APIを書いていましたが繰り返しが多すぎて嫌気がさしました。 CDKはその苦痛を取り除いてくれました。 素のOpenAPI定義を書くとその苦痛が戻ってくることになるのではないかと思います(試していませんが・・・)。
ということで、CDKのパーツを使いつつREST APIとそのOpenAPI定義を一度に書くことのできる3番目の選択肢を求めています。 そしてこのライブラリが解決策になることを願っています。
CDKはaws_apigateway.SpecRestApiという似たような名前を持つConstructを提供しています。
aws_apigateway.SpecRestApiの目的は既存のOpenAPI定義をインポートしてREST APIを作成することである一方、このライブラリの目的はその逆、REST APIを構築することでOpenAPI定義を作成することです。
IResourceWithSpec.addMethodメソッドの3番目の引数のsummaryとdescriptionプロパティを指定することができます。
api.root.addMethod(
'GET',
new apigateway.MockIntegration({
// ... integration settings
}),
{
operationName: 'getRoot',
summary: 'Get root', // NEW!
description: 'Returns the root object', // NEW!
methodResponses: [
{
statusCode: '200',
description: 'successful operation',
},
],
}
);operationName, summary, descriptionプロパティはそれぞれOpenAPI定義におけるOperation ObjectのoperationId, summary, descriptionプロパティに対応しています。
methodResponsesプロパティの各要素にはdescriptionプロパティを設定することができ、これはOpenAPI定義におけるResponse Objectのdescriptionプロパティに対応しています。
IResourceWithSpec.addMethodメソッドの3番目の引数のrequestParameterSchemasプロパティでリクエストパラメータを記述することできます。
findByStatus.addMethod(
'GET',
new apigateway.MockIntegration({
// ... integration settings
}),
{
operationName: 'findPetsByStatus',
requestParameterSchemas: { // NEW!
'method.request.querystring.status': {
description: 'Status values that need to be considered for filter',
required: false,
explode: true,
schema: {
type: 'string',
enum: ['available', 'pending', 'sold'],
default: 'available',
},
},
},
},
);requestParameterSchemasプロパティはKey-ValueペアのマップでrequestParametersプロパティと同じキーを受け付けますが、キーをboolean値ではなくOpenAPI定義におけるParameter Objectを表すオブジェクト(nameとinプロパティを除く)にマップします。
Parameter Objectのnameとinプロパティはキーから導出されます。
ということで上記のrequestParameterSchemasは以下のParameter Objectになります。
[
{
name: 'status',
in: 'query',
description: 'Status values that need to be considered for filter',
required: false,
explode: true,
schema: {
type: 'string',
enum: ['available', 'pending', 'sold'],
default: 'available',
},
},
]requestParameterSchemasプロパティを指定した場合、requestParametersプロパティを指定する必要はありません。
ベースとなるaws_apigateway.IResource.addMethodに渡されるrequestParametersプロパティはrequestParameterSchemasプロパティからrequestParameters[key] = requestParameterSchemas[key].requiredとなるように生成されます。
requestParameterSchemasプロパティを省略しrequestParametersプロパティを指定した場合、requestParametersプロパティから最低限のParameter Objectを作成します。
以下のオブジェクトをrequestParametersプロパティに指定したとすると、
{
'method.request.querystring.status': false,
}以下のようになります。
[
{
name: 'status',
in: 'query',
required: false,
schema: {
type: 'string',
},
},
]requestParametersとrequestParameterSchemasプロパティの両方を指定した場合、requestParameterSchemasプロパティが優先されます。
IRestApiWithSpec.addModelメソッドはOpenAPI定義におけるComponents ObjectのschemasプロパティにSchema Objectを追加します。
以下は例です。
const petModel = api.addModel('PetModel', {
description: 'A pet',
contentType: 'application/json',
schema: {
schema: apigateway.JsonSchemaVersion.DRAFT4,
title: 'pet',
description: 'A pet',
type: apigateway.JsonSchemaType.OBJECT,
properties: {
id: {
description: 'ID of the pet',
type: apigateway.JsonSchemaType.INTEGER,
format: 'int64',
example: 123,
},
name: {
description: 'Name of the pet',
type: apigateway.JsonSchemaType.STRING,
example: 'Monaka',
},
},
},
});IRestApiWithSpec.addModelメソッドの2番目の引数のschemaプロパティ(JsonSchemaEx)はOpenAPI定義において等価なSchema Objectに翻訳されます。
IResourceWithSpec.addMethodメソッドの3番目の引数のmethodResponsesプロパティにおけるresponseModelsプロパティから参照したaws_apigateway.IModelはOpenAPI定義でそのaws_apigateway.IModelに対応するスキーマへの参照に置き換えられます。
以下の例におけるmethodResponsesプロパティは、
petId.addMethod(
'GET',
new apigateway.MockIntegration({
// ... integration settings
}),
{
operationName: 'getPetById',
methodResponses: [
{
statusCode: '200',
description: 'successful operation',
responseModels: {
'application/json': petModel,
},
},
],
},
);OpenAPI定義において以下のようなResponses Objectになります。
{
'200': {
description: 'successful operation',
content: {
'application/json': {
schema: {
'$ref': '#/components/schemas/exampleapiPetModel43E308F7'
},
},
},
},
}aws_apigateway.IModelに付与されるCloudFormationのリソースIDがaws_apigateway.IModelの参照パスを表現するのに使われます。
aws_apigateway.JsonSchemaの拡張であるJsonSchemaExにはmodelRefという追加のプロパティがあります。
modelRefプロパティを使うとスキーマから別のaws_apigateway.IModelを参照することができます。
以下は配列要素の型を指定するのに別のaws_apigateway.IModelを参照する例です。
const petArrayModel = api.addModel('PetArrayModel', {
description: 'An array of pets',
contentType: 'application/json',
schema: {
schema: apigateway.JsonSchemaVersion.DRAFT4,
title: 'petArray',
description: 'An array of pets',
type: apigateway.JsonSchemaType.ARRAY,
items: {
modelRef: petModel,
},
},
});augmentAuthorizer関数を使って既存のaws_apigateway.IAuthorizerをOpenAPI定義のためのプロパティで拡張することができます。
const authorizer = augmentAuthorizer(
new apigateway.TokenAuthorizer(
this,
'ExampleAuthorizer',
{
handler: new nodejs.NodejsFunction(this, 'authorizer', {
description: 'Example authorizer',
runtime: lambda.Runtime.NODEJS_18_X,
}),
},
),
{
type: 'apiKey',
in: 'header',
name: 'Authorization',
},
);augmentAuthorizer関数の2番目の引数はOpenAPI定義においてAuthorizerを記述するSecurity Scheme Objectです。
最新のAPIドキュメンテーションはapi-docs/markdown/index.mdにあります(日本語版はありません)。
pnpm installpnpm builddistフォルダ内で以下のファイルが作成または更新されます。
index.jsindex.js.mapindex.d.ts
distフォルダは存在しなければ作成されます。
このライブラリのAPIに変更があるとapi-docs/cdk-rest-api-with-spec.api.mdファイルも更新されます。
pnpm docapi-docs/markdownフォルダのコンテンツを置き換えます。