serverless-application-model icon indicating copy to clipboard operation
serverless-application-model copied to clipboard

HttpApi circular dependency between RouteSettings and Route

Open brcarp opened this issue 3 years ago • 7 comments

Description:

When creating HTTP API and Stage resources for the first time using AWS::Serverless::HttpApi, adding RouteSettings will fail for routes that you may be creating at the same time. (You cannot create the Route resource ahead of time because it needs to belong to the API that you are creating.) The circular dependency can be resolved by first creating the HttpApi along with a defined Route resource, and then doing a subsequent update to add RouteSettings that will match it to existing routes, but this is inefficient and not a golden path.

Steps to reproduce:

Example template snippet:

Resources:

  TestHttpApi:
    Type: AWS::Serverless::HttpApi
    Properties:
      FailOnWarnings: true
      StageName: 'test'
      RouteSettings:
        'GET /path':
          ThrottlingBurstLimit: 100
          ThrottlingRateLimit: 100

  TestRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
      ApiId: !Ref TestHttpApi
      RouteKey: 'GET /path'
      Target: !Join
        - /
        - - integrations
          - !Ref TestIntegration

  TestIntegration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref TestHttpApi
      # [...]

Observed result:

The AWS::ApiGatewayV2::Stage resource results in a CREATE_FAILED in CloudFormation with the following error:

Unable to find Route by key GET /path within the provided RouteSettings (Service: AmazonApiGatewayV2; Status Code: 404; Error Code: NotFoundException; Request ID: x-x-x-x-x; Proxy: null))

Expected result:

The expectation is that the SAM deploy can create the API, Stage and Route together in a single deployment, resolving the circular dependency of the Route needing to exist before the Stage's RouteSettings can be applied.

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

  1. OS: Amazon Linux
  2. If using SAM CLI, sam --version: FROM public.ecr.aws/sam/build-nodejs14.x:latest (should be 1.55.0)
  3. AWS region: us-east-1

brcarp avatar Aug 26 '22 14:08 brcarp

Some additional thoughts regarding the desired behavior here:

  1. It would be nice if all the Route settings (like Target) could be included in the RouteSettings property, so that it didn't need to be specified as a separate resource
  2. Barring (1.) above, I had the thought of whether the RouteKey in the RouteSettings could be retrieved by Fn::GetAtt (with arguments TestRoute, RouteKey), but as far as I can tell, you cannot use intrinsic functions for the name in a name-value pairing (inside RouteSettingsMap or anywhere else for that matter). It seemed like it would be a nice little trick to not have to write out the route key in multiple places, and to be able to use the route's property by reference, but at the end of the day that is all a workaround for (1.) above anyway.

If all of the route's properties could be provided in the RouteSettings of the HttpApi, then you'd only need to specify the route key in one place. In such an enhancement to the SAM specification, the included settings would need to be divided up into the route creation and the stage creation, but it would be much cleaner for the template. As it stands, there needs to be multiple deploys and careful coordination, both among the resources and between the deployments, to get the route settings applied properly.

brcarp avatar Aug 26 '22 14:08 brcarp

@brcarp AWS::Serverless::Api and AWS::Serverless::HttpApi should not be used with the "raw" ApiGateway resources. Api Gateway will accept this but can lead to unexpected behavior.

What happens if you switch to specifying this through OpenApi? This should fix the circular dependencies and the nondeterministic behavior of ApiGateway.

jfuss avatar Aug 26 '22 15:08 jfuss

@brcarp AWS::Serverless::Api and AWS::Serverless::HttpApi should not be used with the "raw" ApiGateway resources. Api Gateway will accept this but can lead to unexpected behavior.

@jfuss is that documented anywhere? I didn't know that was considered unsupported behavior.

What happens if you switch to specifying this through OpenApi? This should fix the circular dependencies and the nondeterministic behavior of ApiGateway.

I actually had a LOT of difficulty trying to set up an HTTP proxy integration with a VPC Link using OpenApi. If you have any working examples of that to share, I'd be interested to see them. In my experimentation, I could not get this to work with VPC Links and a proxy path variable (/{proxy+} => "overwrite:path": "/base-path/${request.path.proxy}").

brcarp avatar Aug 26 '22 15:08 brcarp

is that documented anywhere? I didn't know that was considered unsupported behavior.

@brcarp This has come up before in the repo. Here is a previous response: https://github.com/aws/serverless-application-model/issues/1971#issuecomment-880136629 I would have to check/search if Api Gateway updated their docs. At the very least, we should have it on our docs as well. I either can't find it or needs to be added. Will take that up internally.

If you have any working examples of that to share,

I do not off hand. I would have to create one myself. Have you looked at https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-using-swagger.html? Seems like what you are looking for but not totally sure.

jfuss avatar Aug 26 '22 16:08 jfuss

If you have any working examples of that to share,

I do not off hand. I would have to create one myself. Have you looked at https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-api-with-vpclink-using-swagger.html? Seems like what you are looking for but not totally sure.

@jfuss Yeah that's useful for the VPC Link, but I think my actual issue was with using {proxy+} as a path parameter for creating a proxy with path overwrite. I couldn't find any documentation on that at all. It's not clear to me whether that's part of the OpenAPI spec or whether transforming API requests and responses with a proxy integration was specific to AWS and not configurable with OpenAPI.

I was unable to get that aspect of it to work properly, but it may be because I was experimenting in the dark without any relevant documentation.

brcarp avatar Aug 26 '22 16:08 brcarp

For what it's worth, I recall trying to follow the model in the article Set up a proxy resource with Lambda proxy integration and Set up HTTP integrations in API Gateway, but finding that it did not work correctly for HTTP_PROXY type (vs. AWS_PROXY type for a Lambda) in an HTTP API (vs. a REST API).

brcarp avatar Aug 26 '22 16:08 brcarp

It's possible that I just didn't iterate on it enough, but my recollection is that I just wasn't able to get it to work. If it has been proven out, it would be nice to add an OpenAPI example to Working with HTTP proxy integrations for HTTP APIs.

brcarp avatar Aug 26 '22 17:08 brcarp