Using the ResponseCache policy responsibly! (or, Don't cache POST requests)

Today, I want to discuss the ResponseCache policy.

The ResponseCache policy allows API publishers to add caching to any backend system. This simple capability is really powerful and can help you offload over-burdened backend systems, or more importantly improve response times for snappier front-end performance.

But it's important to use this tool in the right way. The HTTP Spec says that caches in HTTP servers should be used to satisfy only GET or HEAD verbs. This means a system should never return a cached result for a POST or a PUT or a DELETE, for example. But out of the box, the ResponseCache in Apigee Edge allows you to cache *anything*.

What if you don't want to return cached responses for POSTs or PUTs?

It's a simple matter of configuration.

Let's have a look at the policy. In the Administrative Portal for Apigee Edge, if you drag-and-drop a ResponseCache policy into an API Proxy, currently you get a configuration that looks like this:

<ResponseCache name="Response-Cache-1">
    <DisplayName>Response Cache-1</DisplayName>
    <Properties/>
    <CacheKey>
        <Prefix/>
        <KeyFragment ref="request.uri" type="string"/>
    </CacheKey>
    <Scope>Exclusive</Scope>
    <ExpirySettings>
        <ExpiryDate/>
        <TimeOfDay/>
        <TimeoutInSec ref="">3600</TimeoutInSec>
    </ExpirySettings>
    <SkipCacheLookup/>
    <SkipCachePopulation/>
</ResponseCache>

Notice that the SkipCacheLookup and SkipCachePopulate elements are present but empty. What this means is that the cache gets populated and served, for any request, with any verb.

To make sure the cache gets populated and served only for GET or HEAD, you can make a simple change to the configuration, like this:

<ResponseCache name="Response-Cache-1">
    <DisplayName>Response Cache-1</DisplayName>
    <Properties/>
    <CacheKey>
        <Prefix/>
        <KeyFragment ref="request.uri" type="string"/>
    </CacheKey>
    <Scope>Exclusive</Scope>
    <ExpirySettings>
        <ExpiryDate/>
        <TimeOfDay/>
        <TimeoutInSec ref="">3600</TimeoutInSec>
    </ExpirySettings>
  <SkipCacheLookup>NOT (request.verb ~~ \"(GET|HEAD)\")</SkipCacheLookup>
  <SkipCachePopulation>NOT (request.verb ~~ \"(GET|HEAD)\")</SkipCachePopulation>
</ResponseCache>

You can make other changes to this configuration, to set the cache key to include query parameters, or to respect the Accept headers. Read the doc to find out more.

And, here's a video explaining and showing what I just wrote above.

Comments
Not applicable

@Dino How to clear the cache which was created by response cache policy whenever there is an update in the backend data, so that the next time GET requests will hit a cache miss and get the latest value?

DChiesa
Staff

I can think of two ways

  • allow the cache entry to expire "naturally" according to the ExpirySeconds (eg TimeoutInSec ) that you had configured when populating the cache.
  • Rather than using ResponseCache policy, use the primitive policies PopulateCache and LookupCache. Invoke a PopulateCache policy with an expiry of 1s, and it will overwrite the cache entry and ensure that the cache entry expires within 1 second.
mohdilyas
Participant IV

@Dino-at-Google

@Dino

In #2, are you suggesting running the Populate Cache policy for this specific case? If yes, then on what req.uri or cache-key, it should run? Can we use a combo of Response Cache and Invalidate Cache policy to achieve this?

joshuacarino
Participant V

i have the same exact question, haha. As I need to clear the response cache from the backend if there was an update on the data. And the only thing policies I know where I could do this is via Populate Cache, Lookup Cache, Invalidate Cache and Assign Message Policy which is a hassle. I am trying to find a way clear the response cache too, hehe.

joshuacarino
Participant V

Oh, found it, turns out we could really use Invalidate Cache to manually

10707-screenshot-1199.png

Clear the cache of Response Cache

mohdilyas
Participant IV

thanks for your reply. WIll try this out.

jamilmuhammad
Community Visitor

I am posting this just to document a link to a solution provided 4Mv4D in youtube.

HYG: https://www.youtube.com/watch?v=XS93EZYYbTU&list=PLsWqc60hQz4cP2SOZkMM9Gwri25uICZzj&index=7

 

Version history
Last update:
‎03-10-2016 07:27 AM
Updated by: