GithubHelp home page GithubHelp logo

arcanereinz / cdk-rest-api-with-spec Goto Github PK

View Code? Open in Web Editor NEW

This project forked from codemonger-io/cdk-rest-api-with-spec

0.0 0.0 0.0 253 KB

Describe a REST API and the OpenAPI definition side by side with CDK

License: MIT License

JavaScript 2.16% TypeScript 97.84%

cdk-rest-api-with-spec's Introduction

English / 日本語

cdk-rest-api-with-spec

Describe an Amazon API Gateway (API Gateway) REST API and the OpenAPI definition at once with cdk-rest-api-with-spec.

What's new

  • OpenAPI 3.1 support for type as an array
    type: [string, integer];
  • add build options that affects openapi json output
    const api = new RestApiWithSpec(this, 'example-api', {
      buildOptions: {
        // 1. Use modelName instead of generated name for models
        usePhysicalName: true,
        // 2. Do not include OPTIONS in openAPI output file
        noIncludeOptionsMethod: true,
      },
      // ... other options
    });
  • add servers parameter to list servers
    const api = new RestApiWithSpec(this, 'example-api', {
      servers: [
        {
          description: 'qa-stg-internal',
          url: 'https://example.com/qa-stg',
        },
        {
          description: 'prod-stg-internal',
          url: 'https://example.com/prod-stg',
        },
      ],
      // ... other options
    });
  • add tags support for openAPI 2/3
    api.root.addMethod(
      'GET',
      new apigateway.MockIntegration({
        // ... integration settings
      }),
      {
        tags: ['examples'],
        // ... options settings
      },
    );

For whom is this library?

This library could help you if you would like to write a REST API and the OpenAPI definition at once using the AWS Cloud Development Kit (CDK) building blocks. See "Background" for more details.

Prerequisites

You have to install Node.js v12 or later. I have developed this library with Node.js v16.x.

This library is implemented for the CDK version 2 (CDK v2) and does not work with the CDK version 1.

How to install

Please add this repository to your dependencies.

npm install https://github.com/codemonger-io/cdk-rest-api-with-spec.git#v0.2.1

This library is supposed to be used in a CDK v2 project, so it does not include the following modules in the dependencies but does in the peerDependencies.

As long as you are working on a CDK v2 project, you should not have to separately install them.

Getting started

Please instantiate RestApiWithSpec instead of aws_apigateway.RestApi.

const api = new RestApiWithSpec(this, 'example-api', {
  description: 'Example of RestApiWithSpec',
  openApiInfo: {
    version: '0.0.1',
  },
  openApiOutputPath: 'openapi.json',
  // ... other options
});

After synthesizing the CDK stack, you will find a file openapi.json containing the OpenAPI definition created.

Please refer to the sections "Use cases" and "API documentation" for more details. You can also find a working example in the example folder.

Background

Recently, I have been urged to write the OpenAPI definition of my REST API on API Gateway. As far as I know, there are two options to have the OpenAPI definition of a REST API on API Gateway.

  1. Export the OpenAPI definition from an existing REST API
  2. Create a REST API by importing the OpenAPI definition

1. Exporting the OpenAPI definition

Without any additional documentation, the OpenAPI definition exported from API Gateway is poorly constrained and useless. I have to add a separate documentation resource to every component of a REST API. It would be nice if I could construct REST API components and document them at once.

2. Importing the OpenAPI definition

I am familiar with the CDK building blocks to describe a REST API on API Gateway. I used to write a REST API with a plain CloudFormation template and got tired of a lot of repetition. CDK has relieved me of that pain. I think writing a plain OpenAPI definition could bring the pain back to me, though I have not tried.

Third option

Thus, I want a third option that enables me to write a REST API and the OpenAPI definition at once using the CDK building blocks. And I hope this library would be the solution.

Difference between SpecRestApi

CDK provides a construct with a similar name aws_apigateway.SpecRestApi. The goal of aws_apigateway.SpecRestApi is to create a REST API by importing an existing OpenAPI definition, whereas the goal of this library is, the opposite, to create an OpenAPI definition by constructing a REST API.

Use cases

Describing a method

You can specify summary and description properties to the third argument of the IResourceWithSpec.addMethod method.

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',
      },
    ],
  },
);

The operationName, summary, and description properties correspond to the operationId, summary, and description properties of the Operation Object in the OpenAPI definition respectively.

Elements in the methodResponses property can have the description property which corresponds to the description property of the Response Object in the OpenAPI definition.

Describing request parameters

You can describe request parameters in the requestParameterSchemas property of the third argument of the IResourceWithSpec.addMethod method.

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',
        },
      },
    },
  },
);

The requestParameterSchemas property is a collection of key-value pairs and takes the same key as the requestParameters property, but it maps a key to an object which represents a Parameter Object, except for the name and in properties, in the OpenAPI definition rather than a boolean value. The name and in properties of the Parameter Object are derived from the key. So the above requestParameterSchemas will become the following 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',
    },
  },
];

If you specify the requestParameterSchemas property, you do not have to specify the requestParameters property. The requestParameters property given to the underlying aws_apigateway.IResource.addMethod will be generated from the requestParameterSchemas property such that requestParameters[key] = requestParameterSchemas[key].required.

If you omit the requestParameterSchemas property but specify the requestParameters property, minimal Parameter Objects will be created from the requestParameters property. Suppose you specify the following object to the requestParameters property,

{
  'method.request.querystring.status': false,
}

then you will get

[
  {
    name: 'status',
    in: 'query',
    required: false,
    schema: {
      type: 'string',
    },
  },
];

If the requestParameters and requestParameterSchemas properties are both specified, the requestParameterSchemas property precedes.

Defining a model (schema)

The IRestApiWithSpec.addModel method will add a Schema Object to the schemas property of the Components Object in the OpenAPI definition. Here is an example,

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',
      },
    },
  },
});

The schema property, JsonSchemaEx, of the second argument of the IRestApiWithSpec.addModel method will be translated into an equivalent Schema Object in the OpenAPI definition.

The aws_apigateway.IModel referenced in the responseModels property in the methodResponses property of the third argument of the IResourceWithSpec.addMethod method will be replaced with a reference to the schema corresponding to the aws_apigateway.IModel in the OpenAPI definition.

The methodResponses property in the following example,

petId.addMethod(
  'GET',
  new apigateway.MockIntegration({
    // ... integration settings
  }),
  {
    operationName: 'getPetById',
    methodResponses: [
      {
        statusCode: '200',
        description: 'successful operation',
        responseModels: {
          'application/json': petModel,
        },
      },
    ],
  },
);

will become a Responses Object similar to the following in the OpenAPI definition.

{
  '200': {
    description: 'successful operation',
    content: {
      'application/json': {
        schema: {
          '$ref': '#/components/schemas/exampleapiPetModel43E308F7'
        },
      },
    },
  },
}

The CloudFormation resource ID given to an aws_apigateway.IModel is used to represent the reference path to the aws_apigateway.IModel.

JsonSchemaEx which extends aws_apigateway.JsonSchema has an additional property modelRef. You can reference another aws_apigateway.IModel in a schema by using the modelRef property. The following is an example of referencing another aws_apigateway.IModel to specify the type of array items,

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,
    },
  },
});

Describing an Authorizer

You can augment an existing aws_apigateway.IAuthorizer with the properties for the OpenAPI definition with the augmentAuthorizer function.

const authorizer = augmentAuthorizer(
  new apigateway.TokenAuthorizer(this, 'ExampleAuthorizer', {
    handler: new nodejs.NodejsFunction(this, 'authorizer', {
      description: 'Example authorizer',
      runtime: lambda.Runtime.NODEJS_16_X,
    }),
  }),
  {
    type: 'apiKey',
    in: 'header',
    name: 'Authorization',
  },
);

The second argument of the augmentAuthorizer function is a Security Scheme Object to describe the authorizer in the OpenAPI definition.

API documentation

The latest API documentation is available on api-docs/markdown/index.md.

Development

Resolving dependencies

npm install

Building the library

npm run build

You will find the following files created or updated in the dist folder,

  • index.js
  • index.js.map
  • index.d.ts

The dist folder will be created if it does not exist.

You will also find the file api-docs/cdk-rest-api-with-spec.api.md updated if there are any changes in the API of this library.

Generating the documentation

npm run doc

This will replace the contents of the api-docs/markdown folder.

cdk-rest-api-with-spec's People

Contributors

kikuomax avatar nangchan avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.