Cache using Vary header

My REST API returns `Vary` headers depending on the called endpoint.

I'm trying to use these headers for `ResponseCache`

I've created these 2 policies

 

 

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="am-vary-header">
    <DisplayName>am-vary-header</DisplayName>
    <Properties/>
    <AssignVariable>
        <Name>vary-header</Name>
        <Ref>response.header.vary</Ref>
    </AssignVariable>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>

 

and

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ResponseCache async="false" continueOnError="false" enabled="true" name="response-cache-on-vary">
    <DisplayName>response-cache-on-vary</DisplayName>
    <Properties/>
    <CacheKey>
        <Prefix/>
        <KeyFragment ref="vary-header" />
    </CacheKey>
    <ExpirySettings>
        <TimeoutInSeconds>60</TimeoutInSeconds>
    </ExpirySettings>
</ResponseCache>

 

and added like this

 

 

    <PreFlow name="PreFlow">
        <Request/>
        <Response>
            <Step>
                <Name>am-vary-header</Name>
            </Step>
            <Step>
                <Name>response-cache-on-vary</Name>
            </Step>
        </Response>
    </PreFlow>

 

But it does not work. When I check the value using "Trace" functionality `responsecache.cachesource ` is always `MISS`

Any idea ?

--

Simone
 

Solved Solved
1 1 375
1 ACCEPTED SOLUTION

Any idea ?

Yes. There are a couple problems.

The ResponseCache policy is somewhat unique in that it has to be attached in two places in the api proxy. First, it's attached the ProxyEndpoint's Preflow. Like this::

<PreFlow>
    <Request>
      <Step>
        <Name>RC-1</Name>
      </Step>
    </Request>
</PreFlow>
...

(Full example ProxyEndpoint).

Then, the policy is attached to the TargetEndpoint's PostFlow Response flow. Like so:

<TargetEndpoint name="default">
    <PostFlow name="PostFlow">
        <Request/>
        <Response>
            <Step>
                <Name>RC-1</Name>
            </Step>
        </Response>
    </PostFlow>
...

(Full example TargetEndpoint).

So, one policy, attached twice, in two different places. I looked in the documentation for the ResponseCache policy and could not find a clear statement about this attachment. I'm sorry, I'll get that updated.

OK, the second issue - you are trying to cache based on the response vary header. That makes sense to me, except,

  1. you also need to cache based on the URI.  I mean, probably. Right?  The URI is not implicitly used in the cache key. You need to specify it in the CacheKey element if you want to cache based on URI.  You might also want to explicitly specify the method/verb.  The Apigee ResponseCache policy will execute with POST/PUT/DELETE, which may or may not be what you want.  So take care.  (See this old article for caching only GET/HEAD requests)
  2. When you attach the policy to the request flow, the response vary header does not exist. There is no response header. Referring to it will not work. But you can sort of get what you want if the value of the response Vary header is predictable. The Vary response header will contain a list of one or more named request headers, typically "Accept". Those are the things you need to include in the cache key, in ResponseCache policy that you attach in the request flow.

As a result, your policy should look something like this:

 

 

<ResponseCache name="RC-1">
    <CacheKey>
        <KeyFragment ref="request.header.accept" />   <!-- not response.header.VARY -->
        <KeyFragment ref="request.uri" />
    </CacheKey>
    <ExpirySettings>
        <TimeoutInSeconds>60</TimeoutInSeconds>
    </ExpirySettings>
</ResponseCache>

 

Because of the ordering of execution, you cannot directly use the value of the Vary header as part of the key.  I mean you could try, but it won't work. 

Oh, the last thing: you don't need the AssignMessage policy. 

 

 

 

View solution in original post

1 REPLY 1

Any idea ?

Yes. There are a couple problems.

The ResponseCache policy is somewhat unique in that it has to be attached in two places in the api proxy. First, it's attached the ProxyEndpoint's Preflow. Like this::

<PreFlow>
    <Request>
      <Step>
        <Name>RC-1</Name>
      </Step>
    </Request>
</PreFlow>
...

(Full example ProxyEndpoint).

Then, the policy is attached to the TargetEndpoint's PostFlow Response flow. Like so:

<TargetEndpoint name="default">
    <PostFlow name="PostFlow">
        <Request/>
        <Response>
            <Step>
                <Name>RC-1</Name>
            </Step>
        </Response>
    </PostFlow>
...

(Full example TargetEndpoint).

So, one policy, attached twice, in two different places. I looked in the documentation for the ResponseCache policy and could not find a clear statement about this attachment. I'm sorry, I'll get that updated.

OK, the second issue - you are trying to cache based on the response vary header. That makes sense to me, except,

  1. you also need to cache based on the URI.  I mean, probably. Right?  The URI is not implicitly used in the cache key. You need to specify it in the CacheKey element if you want to cache based on URI.  You might also want to explicitly specify the method/verb.  The Apigee ResponseCache policy will execute with POST/PUT/DELETE, which may or may not be what you want.  So take care.  (See this old article for caching only GET/HEAD requests)
  2. When you attach the policy to the request flow, the response vary header does not exist. There is no response header. Referring to it will not work. But you can sort of get what you want if the value of the response Vary header is predictable. The Vary response header will contain a list of one or more named request headers, typically "Accept". Those are the things you need to include in the cache key, in ResponseCache policy that you attach in the request flow.

As a result, your policy should look something like this:

 

 

<ResponseCache name="RC-1">
    <CacheKey>
        <KeyFragment ref="request.header.accept" />   <!-- not response.header.VARY -->
        <KeyFragment ref="request.uri" />
    </CacheKey>
    <ExpirySettings>
        <TimeoutInSeconds>60</TimeoutInSeconds>
    </ExpirySettings>
</ResponseCache>

 

Because of the ordering of execution, you cannot directly use the value of the Vary header as part of the key.  I mean you could try, but it won't work. 

Oh, the last thing: you don't need the AssignMessage policy.