OpenAPIを最初に展開せずにCDKスタックから
18866 ワード
最後の投稿How to Automatically Generate Request Models from TypeScript Interfaces , 私はAWS APIゲートウェイ(CDKで)の要求と応答モデルを自動的に定義する方法を歩きました.より良いエンドポイントセキュリティのようないくつかの利点があり、あなたはOpenAPI / Swagger spec like this AWS CLIかAWS APIゲートウェイコンソールから.
この問題はAPIを展開した後にOpenAPI仕様をエクスポートする唯一の方法です.APIをワイルドにする前にspecを持ちたいかもしれない理由がたくさんあります(より多くのセキュリティチェック、クライアントライブラリ生成、ドキュメンテーションなど).
それで、私は何をしましたか?私は私の最後の投稿から私のコードを改善し、Aを作成CDK Construct これは、パラメータ、要求、および応答モデル(検証付き)でRESTAPIを作成し、それらを定義しているため、OpenAPI仕様を生成するために同じ情報を使用します.
このプロジェクトのコードはここにあります.https://github.com/martzcodes/blog-cdk-openapi そして、これは結果(左から配備されたAPIからAPIスペックを生成しました、右は展開の前にCDKコード生成された仕様です).
始める
応答モデルは 無効にする 許可を加える ランムダスを更新して文字列の代わりに文字列オブジェクトを返す サードパーティライブラリを使用して、TypeScriptインターフェイスhttps://github.com/vega/ts-json-schema-generator ) それらの改善で、それは走ることの単純な問題でした
ラフマッピングは以下の通りです. すべてのモデル(要求と応答は、問題ではない)に入る Authorizer関数は 他のすべては かなり簡単.
The API Gateway Module それは我々が使用される残りのAPIを生成しますが、少し迷惑です.v 2 apigatewayモジュールのhttppiと異なります.RESTAPIは次のようにリソースを介してエンドポイントを定義します.
私は何を終了しましたか?
addEndpoint - 多分、私はこの「addroute」と名付けなければなりませんでしたが、これは重要なものです.これは、リクエストと応答モデルとルートを追加します
addValidator - 使用するルートのバリデータを追加する
addModel - 以前に取得したスキーマからモデルをRESTAPIモデルに追加する
addResourcesForPath - パスに必要なすべてのリソースを作成する
generateOpenApiSpec - OpenAPI specをクリーンアップし、ファイルシステムに保存します これらのaddEndpoint が最も重要です.残りは本当に“内部”/プライベートメソッドです.我々のスタックで行う必要があるすべての効果的に行われます
比較のために.
...最後のポストのコード(左側)を使用する前に、我々がエンドポイント(右側)を作成するためにスタック内で何をする必要があるかを示します.したがって、その構造は、その多くを遠ざけます.
舞台裏では、このメソッドは、パスのリソースを作成します(もし存在しない場合は、バリデータが存在しない場合はバリデータを作成します(必要に応じて)、モデルを参照してパスを追加します.
最後の「トリック」は、生成されたAPIをディスクに保存し、残りのコードでコミットすることができます.テストは簡単にできます.
まず、Specを生成するかどうかスタックにプロップを追加しました
以下のようになります.https://editor.swagger.io/?url=https://raw.githubusercontent.com/martzcodes/blog-cdk-openapi/main/openapigenerated.json
次は何ですか。
いくつかのフロントエンドコードを含むスタックを持っているし、したいauto-generate client libraries ライブラリを使用してライブラリを展開します OpenAPI specファイルを解析できるセキュリティ解析ツールを持っていて、あなたのCIパイプラインで repoに住んでいるAPIドキュメントを生成し、同じコミットに展開したものを反映したい 自動的にAPIスペックを使用していくつかのPostmanテストを生成する これを図書館に変えることを考えています.あなたはどう思いますか.
そして、もしあなたが私のコードのいずれかに深く行くか、改善のための提案をしたいです.私に知らせて!
あなたがdevブログを始めることに興味があるならば..HashNodeに参加し、私の紹介を使用します.https://hashnode.com/@martzcodes/joinme (私はいくつかの特典を得ます.
この問題はAPIを展開した後にOpenAPI仕様をエクスポートする唯一の方法です.APIをワイルドにする前にspecを持ちたいかもしれない理由がたくさんあります(より多くのセキュリティチェック、クライアントライブラリ生成、ドキュメンテーションなど).
それで、私は何をしましたか?私は私の最後の投稿から私のコードを改善し、Aを作成CDK Construct これは、パラメータ、要求、および応答モデル(検証付き)でRESTAPIを作成し、それらを定義しているため、OpenAPI仕様を生成するために同じ情報を使用します.
このプロジェクトのコードはここにあります.https://github.com/martzcodes/blog-cdk-openapi そして、これは結果(左から配備されたAPIからAPIスペックを生成しました、右は展開の前にCDKコード生成された仕様です).
始める
私は最後のポストに使用したコードにいくつかの改善を行った.すなわち
aws apigateway get-export --parameters extensions='postman' --rest-api-id c638jrlvt0 --stage-name prod --export-type oas30 openapideployed.json
openAPI specファイルを生成し、ベースラインを取得します.ファイルを読みます.そこにはAPIゲートウェイ特有のものがたくさんありません.私たちのAPIがとにかくこの時点で展開されていないので、私たちが本当に気にしないサーバがあります.また、Authorizer機能の論理的なIDがありますblogcdkopenapiblogAuthorizer0C135D8A
それは本当に重要ではない.キー名は、上記の参照と一致する必要があります.他のすべてはファイル内の内部参照です.ラフマッピングは以下の通りです.
components.schemas
モデル名components.securitySchemas
名前によってpaths[<relative path>][<method>]
それからパスの設定The API Gateway Module それは我々が使用される残りのAPIを生成しますが、少し迷惑です.v 2 apigatewayモジュールのhttppiと異なります.RESTAPIは次のようにリソースを介してエンドポイントを定義します.
const validatedResource = restApi.root.addResource('validated');
const validatedHelloResource = validatedResource.addResource('{hello}');
const validatedHelloBasicResource = validatedHelloResource.addResource(
'basic',
);
validatedHelloBasicResource.addMethod('POST', ...);
の代わりにhttpApi.addRoutes({ path: '/validated/{hello}', methods: [ HttpMethod.POST ], integration: ... });
OpenAPIスペックがフルパスとIMOを使用しているということを考えると、私は、ルートによってエンドポイントを追加できるような方法で構築を行うつもりです.私は何を終了しましたか?
注意を払う2つの重要なファイルはhttps://github.com/martzcodes/blog-cdk-openapi/blob/main/src/main.ts and https://github.com/martzcodes/blog-cdk-openapi/blob/main/src/api.ts api.ts
CDK構成を含みます.入力としてtsconfigへのパスを取ります.JSONファイル(サードパーティのTS -> JSONスキーマライブラリで使用されます)、リクエスト/レスポンスモデルがどこに住んでいるか、およびAPIコンストラクタにあるrestapipropsの場所.
const api = new OpenApiConstruct(this, 'OpenApi', {
tsconfigPath: `${join(__dirname, '..', 'tsconfig.json')}`,
apiProps: {
defaultMethodOptions: {
authorizer: auth,
},
},
models: `${__dirname}/interfaces`,
});
Constructorのコンストラクターは、RESTAPIを作成し、JSONスキーマを取得しますが、何もしません.また、OpenAPI仕様を初期化します.
this.openApiSpec = {
openapi: '3.0.1',
info: {
title: `${id}`,
version: new Date().toISOString(),
},
paths: {},
components: {
schemas: {},
securitySchemes: {},
},
};
if (props.apiProps.defaultMethodOptions && props.apiProps.defaultMethodOptions.authorizer) {
this.openApiSpec.components.securitySchemes.authorizer = {
'type': 'apiKey',
'name': 'Authorization',
'in': 'header',
'x-amazon-apigateway-authtype': 'custom',
};
}
}
この構文には、次の5つのメソッドがあります.
const api = new OpenApiConstruct(this, 'OpenApi', {
tsconfigPath: `${join(__dirname, '..', 'tsconfig.json')}`,
apiProps: {
defaultMethodOptions: {
authorizer: auth,
},
},
models: `${__dirname}/interfaces`,
});
this.openApiSpec = {
openapi: '3.0.1',
info: {
title: `${id}`,
version: new Date().toISOString(),
},
paths: {},
components: {
schemas: {},
securitySchemes: {},
},
};
if (props.apiProps.defaultMethodOptions && props.apiProps.defaultMethodOptions.authorizer) {
this.openApiSpec.components.securitySchemes.authorizer = {
'type': 'apiKey',
'name': 'Authorization',
'in': 'header',
'x-amazon-apigateway-authtype': 'custom',
};
}
}
addEndpoint - 多分、私はこの「addroute」と名付けなければなりませんでしたが、これは重要なものです.これは、リクエストと応答モデルとルートを追加します
addValidator - 使用するルートのバリデータを追加する
addModel - 以前に取得したスキーマからモデルをRESTAPIモデルに追加する
addResourcesForPath - パスに必要なすべてのリソースを作成する
generateOpenApiSpec - OpenAPI specをクリーンアップし、ファイルシステムに保存します
addEndpoint
メソッド.比較のために.
...最後のポストのコード(左側)を使用する前に、我々がエンドポイント(右側)を作成するためにスタック内で何をする必要があるかを示します.したがって、その構造は、その多くを遠ざけます.
舞台裏では、このメソッドは、パスのリソースを作成します(もし存在しない場合は、バリデータが存在しない場合はバリデータを作成します(必要に応じて)、モデルを参照してパスを追加します.
最後の「トリック」は、生成されたAPIをディスクに保存し、残りのコードでコミットすることができます.テストは簡単にできます.
まず、Specを生成するかどうかスタックにプロップを追加しました
interface MyStackProps extends StackProps {
generateApiSpec: boolean;
}
export class MyStack extends Stack {
public apiSpec?: OpenApiSpec;
constructor(scope: Construct, id: string, props: MyStackProps = { generateApiSpec: false }) {
...
if (props.generateApiSpec) {
this.apiSpec = api.generateOpenApiSpec(join(`${__dirname}`, '..', 'openapigenerated.json'));
}
}
}
...テストの使用test('Api Spec', () => {
const app = new App();
const stack = new MyStack(app, 'test', { generateApiSpec: true });
console.log(`Stack: ${JSON.stringify(stack.apiSpec)}`);
console.log(`deployed: ${JSON.stringify(deployedApiSpec)}`);
expect(stack.apiSpec).toMatchSnapshot({
info: {
version: expect.any(String),
},
});
});
これを生成するには:https://github.com/martzcodes/blog-cdk-openapi/blob/main/openapigenerated.json 以下のようになります.https://editor.swagger.io/?url=https://raw.githubusercontent.com/martzcodes/blog-cdk-openapi/main/openapigenerated.json
次は何ですか。
世界はあなたの牡蠣です!
たぶんあなた.
そして、もしあなたが私のコードのいずれかに深く行くか、改善のための提案をしたいです.私に知らせて!
あなたがdevブログを始めることに興味があるならば..HashNodeに参加し、私の紹介を使用します.https://hashnode.com/@martzcodes/joinme (私はいくつかの特典を得ます.
Reference
この問題について(OpenAPIを最初に展開せずにCDKスタックから), 我々は、より多くの情報をここで見つけました https://dev.to/aws-builders/openapi-specs-from-cdk-stack-without-deploying-first-4g83テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol