OpenAPIを最初に展開せずにCDKスタックから


最後の投稿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 )
  • それらの改善で、それは走ることの単純な問題でした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 モデル名
  • Authorizer関数は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つのメソッドがあります.

  • addEndpoint - 多分、私はこの「addroute」と名付けなければなりませんでしたが、これは重要なものです.これは、リクエストと応答モデルとルートを追加します

  • addValidator - 使用するルートのバリデータを追加する

  • addModel - 以前に取得したスキーマからモデルをRESTAPIモデルに追加する

  • addResourcesForPath - パスに必要なすべてのリソースを作成する

  • generateOpenApiSpec - OpenAPI specをクリーンアップし、ファイルシステムに保存します
  • これらのaddEndpoint が最も重要です.残りは本当に“内部”/プライベートメソッドです.我々のスタックで行う必要があるすべての効果的に行われます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

    次は何ですか。


    世界はあなたの牡蠣です!
    たぶんあなた.
  • いくつかのフロントエンドコードを含むスタックを持っているし、したいauto-generate client libraries ライブラリを使用してライブラリを展開します
  • OpenAPI specファイルを解析できるセキュリティ解析ツールを持っていて、あなたのCIパイプラインで
  • repoに住んでいるAPIドキュメントを生成し、同じコミットに展開したものを反映したい
  • 自動的にAPIスペックを使用していくつかのPostmanテストを生成する
  • これを図書館に変えることを考えています.あなたはどう思いますか.
    そして、もしあなたが私のコードのいずれかに深く行くか、改善のための提案をしたいです.私に知らせて!

    あなたがdevブログを始めることに興味があるならば..HashNodeに参加し、私の紹介を使用します.https://hashnode.com/@martzcodes/joinme (私はいくつかの特典を得ます.