1

I have a CloudFront distribution configured with multiple Origins, including an API Gateway deployment.

I'm trying to create a Behavior on CloudFront so that any requests received to a /api/* path will be redirected to the API Gateway and what I did was to simply create a new Behavior with the path pattern as /api/* and Origin as the API Gateway deployment I mentioned. This works, however any requests containing a query string in it, such as /api/data?since=2020-01-01, will result in a request to API Gateway without the query string, i.e, what will reach API GW is simply /api/data.

To solve this problem, I tried to set a Cache Policy of Managed-CachingOptimized (or even Managed-CachingDisabled) and an Origin Request Policy of Managed-AllViewer, but then CloudFront started ignoring completely that Behavior and processing the next one in line, which happens to be a S3 bucket. Once the request is sent to the S3 bucket, I get a 404 back as there's no such key in there.

I also tried to use the "Legacy Cache settings", but the same problem is happening.

Is it possible at all to have this "proxy" implemented with CloudFront and API GW? If yes, how would I do that?

Thanks

2 Answers2

2

This caught me out too, with both the query string and headers such as Authorization.

However, the docs state that to pass the Authorization header to the origin it must be used as a cache key:

Cache key settings specify the values in viewer requests that CloudFront includes in the cache key. The values can include URL query strings, HTTP headers, and cookies. The values that you include in the cache key are automatically included in requests that CloudFront sends to the origin, known as origin requests.

and

Note: You can't use an origin request policy to forward the Authorization header. The header must be a part of the cache key to prevent the cache from satisfying unauthorized requests. CloudFront returns an HTTP 400 error if you try to create an origin request policy that forwards the Authorization header.

Additionally, note that in relation to the Origin Request Policy Managed-AllViewer, the issue looks to be the forwarding of the Host header to API Gateway; see https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/571#issuecomment-792051286 i.e. we can't use the Managed-AllViewer for API Gateway origins.

See

  1. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-the-cache-key.html
  2. https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-authorization-header/

As part of a CDK cloudfront.Distribution() construct:

const apiCachePolicy = new cloudfront.CachePolicy(this, 'ApiCachePolicy', {
        headerBehavior: cloudfront.CacheHeaderBehavior.allowList('authorization'),
        queryStringBehavior: cloudfront.CacheQueryStringBehavior.all(),
        cookieBehavior: cloudfront.CacheCookieBehavior.none(),
        minTtl: Duration.minutes(0),
        maxTtl: Duration.minutes(1),
        defaultTtl: Duration.minutes(0),
        enableAcceptEncodingGzip: true,
        enableAcceptEncodingBrotli: true,
    });
Michael Hampton
  • 237,123
  • 42
  • 477
  • 940
Daniel
  • 141
  • 5
0

I have a similar requirement to access couple of API's on AWS GW via cloudfront.

  1. First I created couple of API's with path variable for eg /users/{users-id} for PUT and GET methods
  2. Created custom domain (used subdomain and SSL cert) in API GW and created mapping of API's ( one API is mapped to asset1 and another API is mapped to asset2)
  3. Created the custom origin as api custom domain like api.xyz.com and created the behaviour for custom map path asset1 to redirect to that API
  4. backend API was running on ecs container which i mapped as target in the API GW
  5. Then was able to proxy that API via root domain from cloudfront and invoke the API using the mapped name with resource paths like "http:///asset1/users/{user-id} by substituting the user-id with required values.

But unfortunately i could not acheive /api/* mapping from cloudfront as it expects that api path must be present on API GW and API GW does not support multilevel mapping like api/asset1 using custom domain.

Andrew Schulman
  • 8,561
  • 21
  • 31
  • 47