Reference to a external swagger api definition

api-gateway
aws
#1

Hello,
I would like to reference inside the serverless.yml to an external swagger api definition.

Swagger is a widely spread way to define an api and it’s also supported from the api gateway to import external swagger definitions.

With a swagger api definition there can also be added aws features like api validation and custom api resonses to the api gateway, which will replace a lot of small serverless plugins with official aws features. Also, it gives a developer the possibility to use his api definition from other projects directly with the serverless framework and convert the project easier to serverless.

My current approach is to overwrite the serverless api with the aws put-rest-api command, but it’s not the optimal way to use my own api definition.

A similar feature was also requested in this post " Swagger and Serverless in parallel - bad idea?" but there was no solution and the there mentioned plugin looks like, that it will not be developed further.

It would be nice if I can define an api-definition path directly to the serverless resources, which would be used than to create the api-gateway.

0 Likes

#2
  1. The Serverless Framework uses CloudFormation to handle deployments.
  2. CloudFormation supports Swagger (see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html)
  3. You can override the default CloudFormation template generated by the Serverless Framework (see https://serverless.com/framework/docs/providers/aws/guide/resources#override-aws-cloudformation-resource)

I would start by trying something like:

resources:
  Resources:
    ApiGatewayRestApi:
      Properties:
        Body:
          # Your swagger definition in YAML format goes here
1 Like

#3

Your solution seems to be exactly that I was looking for.
I also have successfully tested your approach with this:

resources:
    Resources:
      ApiGatewayRestApi:
        Type: 'AWS::ApiGateway::RestApi'
        Properties:
          Name: ${self:provider.apiName}-${self:provider.stage}
          Body:
            ${file(api-model/api.yml)}
      ApiGatewayDeployment:
        Type: AWS::ApiGateway::Deployment
        Properties:
          RestApiId:
            Ref: ApiGatewayRestApi
          StageName: ${self:provider.stage}

This import my api.yml like expected but it also removes a lot of advantages, the serverless framework gives me.
If I replace the whole API template with my API definition, I also have to define all other API ressources like the API keys, the API deployment and the trigger for the lambda functions by my self.

For me, an better solution would be, if I could use something like the put-rest-api command in cloudformation to overwrite only the Methods and Models from the serverless API template and keep the API Keys and lambda trigger.

aws apigateway put-rest-api --rest-api-id {AWS::ApiGateway::RestApi}
–region {self:provider.stage}
–mode overwrite
–body file://api-model/api.yml

1 Like

#4

Thanks for moving this discussion forward.
My organisation is API therefore Swagger first, rather than Function therefore Serverless first.
If we can achieve the successful marriage of the two (Swagger and Serverless) then I will win them over with Serverless, without it reluctantly I’m likely destined for Swagger/SAM.
The Swagger use case the organisation likes is the ability to forward engineer the consumer/client.

0 Likes

#6

You don’t need to replace the whole template. The Serverless Framework will merge your resources section with the one it generates. My example adds the Body property to the CloudFormation generated by the Serverless Framework.

0 Likes

#7

Hi,

I’m testing your trick by including the following swagger definition in the resource section:

openapi: 3.0.0
info:
  title: Sample API
  description: Description
  version: 0.1.9
paths:
  /users:
    get:
      summary: Returns a list of users.
      description: Optional description
      responses:
        '200':
          description: A JSON array of user names
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string

However, when I serverless deploy my API, I get the following error message:

 An error occurred: ApiGatewayDeployment1554726393541 - No integration defined for method (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: ...).

Should I add x-amazon-apigateway-integration ?
Is there a way that serverless still handles the integration layer for us ?

My second question is:
Using swagger, how does serverless map the routes from the swagger definition, to the JS methods ?
I mean the swagger equivalent to the handler key-value pair:

functions:
  todo:
    handler: handler.todo

Thanks

0 Likes