13

I'm a bit confused by how API Gateway and CloudFront work together. Ultimately, I want to be able to have a custom header and value be considered part of my cache key. I know this can be done by whitelisting (if I'm using CloudFront).

So when I make the following request:

GET /pagesRead/4
Some-Header: fizz

This returns, for instance, '29 pages'

Then there's a post that updates id 4 to '45 pages'

If I make this request

GET /pagesRead/4
Some-Header: buzz

It will now return '45 pages'

But I'm using API Gateway, which obviously has it's own CloudFront behind the scenes. Is there a way I can configure API Gateway to use its 'behind-the-scenes' CloudFront to whitelist my custom header? Does this even need to be done?

According to this documentation: AWS-API-Gatway, It seems like I can just enable API caching in API Gateway, and it will consider my headers as part of the cache key.

Am I understanding this correctly? If all I want is for my headers to be a part of the cache key, what's the difference between 'Enabling API Caching' in API Gateway and adding a CloudFront instance on top of API Gateway and white-listing in CloudFront?

UPDATE:

I've added a header like this in API Gateway: enter image description here

But on GET, I am getting stale data from the cache.

GET /pagesRead/4 test-header: buzz
Akshay barahate
  • 649
  • 8
  • 23
JAck28
  • 899
  • 4
  • 15
  • 40

2 Answers2

16

The difference is that API Gateway doesn't actually use the CloudFront cache. CloudFront does provide some front-end services for all API Gateway APIs edge-optimized API endpoints¹, but caching does not appear to be one of them, based on the following:

API Gateway enables caching by creating a dedicated cache instance.

...and...

You should not use the X-Cache header from the CloudFront response to determine if your API is being served from your API Gateway cache instance.

https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-caching.html

It is possible to cascade an Edge Optimized API Gateway endpoint behind a CloudFront distribution that you create, but it's not without certain inconveniences. Latency increases somewhat, since you're passing through more systems. Given that configuration, the CloudFront-Is-*-Viewer and CloudFront-Viewer-Country headers, and probably any notion of the client IP will be invalid, because the API Gateway deployment will see attributes of the additional CloudFront distribution that is in front of it, rather than of the real client. X-Forwarded-For will still be right, but will have to be handled with care, because it will contain one extra hop that will have to be correctly handled.

For an application where you want to put API Gateway behind your own CloudFront distribution, use one of the new Regional endpoints to deploy your API stage.

it will consider my headers as part of the cache key.

You do have to configure the cache key explicitly, based on the document you cited, but yes, the API Gateway cache will then cache responses based on the value of that header, and other attributes in the cache key.


¹ edge optimized endpoints. API Gateway now has two different kinds of endpoints. The original design is now called edge-optimized, and the new option is called regional. Regional endpoints do not use front-end services from CloudFront, and may offer lower latency when accessed from EC2 within the same AWS region. All existing endpoints were categorized as edge-optimized when the new regional capability was rolled out. With a regional endpoint, the CloudFront-* headers are not present in the request, unless you use your own CloudFront distribution and whitelist those headers for forwarding to the origin.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • I've edited my post with what I've added to APIG. However, it doesn't seem to be adding the headed to my cache key, as I keep getting stale data. – JAck28 Sep 29 '17 at 20:29
  • With each request, you need to change the value accompanying the header, in order to get a fresh answer. – Michael - sqlbot Sep 30 '17 at 04:13
  • I did try that in postman, and it didn't work. Let me try again. I was playing around with it a lot, so maybe I repeated a value in postman. I'll let you know if it works out. Thanks. – JAck28 Sep 30 '17 at 10:48
  • Worked out nicely. I also forgot to deploy earlier :-/. Thanks for your help. – JAck28 Oct 03 '17 at 19:49
  • @Michael - sqlbot, You mention `CloudFront does provide some front-end services for all API Gateway APIs edge-optimized API endpoints¹, but caching does not appear to be one of them`, What is the `front-end services`, for instance? Could you explain in more detail? – SangminKim Jun 16 '18 at 16:10
  • 1
    @SangminKim when you connect to an edge optimized endpoint, the IP addresses in the DNS response depend on your location, taking you to a nearby CloudFront edge, where the TLS session with the client is terminated. CloudFront parses the request to identify the internal target, then finds an available (idle/reusable, kept-alive) connection or creates a new one, back to API Gateway in the region where the API is deployed, and sends the request. These connections are over networks managed by AWS rather than the public Internet, optimizing their latency and performance. – Michael - sqlbot Jun 16 '18 at 17:04
  • 1
    CloudFront provides similar capabilities to S3 for the [S3 Transfer Acceleration](https://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html) feature, which also consistently shows `X-Cache: Miss from CloudFront` just like API Gateway, because CloudFront is providing services that do not include caching. In both cases, the customer does not configure anything in CloudFront and is not billed by CloudFront for the accompanying use of the CloudFront infrastructure. – Michael - sqlbot Jun 16 '18 at 17:09
1

When you enable caching in API Gateway,

You can also optionally add,

RequestPath
QueryStringParameters
Http Headers

E.g.,

http://example.com/api/{feature}/?queryparam=queryanswer [ with header customheader=value1 ]

Above url gives you option to cache based on,

Just the URL without PathParameters: http://example.com/api/

Optionally include PathParameter: http://example.com/api/{feature}/

Optionally include QueryStrings: http://example.com/api/{feature}/?queryparam=queryanswer

Optionally include Http Headers: You can either include regular header like User-Agent or Custom headers

Whatever the caching mode you have in API-Gateway, you can also have it under CloudFront as well.

Also to clear up the cache, in your http response send Cache-Control: max-age=0

Hope it helps.

CloudFront cache image

Kannaiyan
  • 12,554
  • 3
  • 44
  • 83
  • Can you help me navigate to the page where the you can put in Request Paths and URL Query String Parameters? I need this badly but don't see those settings anywhere. I would expect to see them in Management Console -> Amazon API Gateway -> APIs -> {my api} -> Stages -> Settings where the cache settings are, but they are not. – steve-o Apr 13 '18 at 15:39
  • @kannaiyan How do we invalidate cache based on the query parameters/path parameters ? – systemdebt May 28 '21 at 17:57
  • You can invalidate cache per api. No option to invalidate cache based on query / path parameters. aws apigateway flush-stage-cache --rest-api-id 1234123412 --stage-name dev . You can invalidate by path if you your api gateway with cloud front. – Kannaiyan May 29 '21 at 05:02