0
votes

Goal: Use API Management cache-policy to cache a json response that never changes.

Original (no cache)
This policy is backed by an azure function that returns a never-changing json response.

<policies>
    <inbound>
        <base />
        <set-backend-service id="apim-generated-policy" backend-id="azfunc-fluffyoauth2" />
        <rewrite-uri template="/WellKnownOpenidConfiguration" />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Thinking that this might be a good thing to cache, I introduce the cache-lookup policy.

<policies>
    <inbound>
        <base />
        <set-backend-service id="apim-generated-policy" backend-id="azfunc-fluffyoauth2" />
        <rewrite-uri template="/WellKnownOpenidConfiguration" />
        <cache-lookup vary-by-developer="false" vary-by-developer-groups="false" downstream-caching-type="none" />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
        <cache-store duration="36000" />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

What I am seeing is that the cached version returns a binary that I believe is gzipped. This causes downstream code that expects it to be raw json to break. This reponse is an openid connect discovery document, and ironically if I point API Management's jwt-policy to this it breaks as well.

i.e.

var auth0Domain = "https://apim-mycompany.azure-api.net/oauth2";
string responseString = null;
try
{
    var url = $"{auth0Domain}/.well-known/openid-configuration-cached";
    Console.WriteLine($"-------------------");
    Console.WriteLine($"{url}");
    var httpClient = new HttpClient();
    var response = await httpClient.GetAsync(new Uri($"{auth0Domain}/.well-known/openid-configuration-cached"));
    responseString = await response.Content.ReadAsStringAsync();
    Console.WriteLine($"-------------------");
    Console.WriteLine($"{responseString}");
    Console.WriteLine($"-------------------");
    JsonConvert.DeserializeObject<OpenIdConnectConfiguration>(responseString);
}
catch (Exception ex)
{
    Console.WriteLine($"Error:{ex.Message}");
    Console.WriteLine($"-------------------");
    return;
}



curl -I --location --request GET 'https://apim-fluffyoauth2.azure-api.net/oauth2/.well-known/openid-configuration-cached'
HTTP/1.1 200 OK
Cache-Control: no-store, must-revalidate, no-cache
Pragma: no-cache
Content-Length: 558
Content-Type: application/json; charset=utf-8
Content-Encoding: gzip
Expires: Tue, 14 Apr 2020 18:50:53 GMT
Vary: Accept-Encoding
Request-Context: appId=cid-v1:dfeba42c-e636-42bc-b501-7c77563c3e7b,appId=cid-v1:dfeba42c-e636-42bc-b501-7c77563c3e7b
Date: Tue, 14 Apr 2020 18:50:53 GMT

Question(s):

What is the cache-policy doing?
How can I change it to still cache but respond with what the NON-CACHED version does?

1
Response being gzipped by itself should not be a problem as long as all content headers are in place. Could you add a sample cached response with all headers that you get from APIM?Vitaliy Kurokhtin
APIM will out of the blue not do gzip, all I have to do is modify the cache policy TTL and save it. That triggers it to start sending gzip. apim-fluffyoauth2.azure-api.net/oauth2/.well-known/… HTTP/1.1 200 OK Cache-Control: no-store, must-revalidate, no-cache Pragma: no-cache Content-Length: 558 Content-Type: application/json; charset=utf-8 Content-Encoding: gzip Expires: Tue, 14 Apr 2020 18:50:53 GMT Vary: Accept-Encoding Date: Tue, 14 Apr 2020 18:50:53 GMTHerb Stahl
APIM always sends all client headers to backend, did you send accept-encoding? You may want to add vary="accept-encoding" into your cache-lookup policy, that would prevent APIM from replying with cached gzipped content if client didn't ask for it.Vitaliy Kurokhtin
I added the <vary-by-header> Accept and Accept-Charset. This seems to have fixed it. You get what you ask for. <cache-lookup vary-by-developer="false" vary-by-developer-groups="false" downstream-caching-type="none"> <vary-by-header>Accept</vary-by-header> <vary-by-header>Accept-Charset</vary-by-header> </cache-lookup>Herb Stahl

1 Answers

1
votes

Adding the following;

<cache-lookup vary-by-developer="false" vary-by-developer-groups="false" downstream-caching-type="none">
  <vary-by-header>Accept</vary-by-header>
  <vary-by-header>Accept-Charset</vary-by-header>
</cache-lookup>

Which produces the final policy.

<policies>
<inbound>
    <base />
    <set-backend-service id="apim-generated-policy" backend-id="azfunc-fluffyoauth2" />
    <rewrite-uri template="/WellKnownOpenidConfiguration" />
    <cache-lookup vary-by-developer="false" vary-by-developer-groups="false" downstream-caching-type="none">
        <vary-by-header>Accept</vary-by-header>
        <vary-by-header>Accept-Charset</vary-by-header>
    </cache-lookup>
</inbound>
<backend>
    <base />
</backend>
<outbound>
    <base />
    <cache-store duration="3600" />
</outbound>
<on-error>
    <base />
</on-error>

Now results in API Management not doing a gzip encoding when it wasn't asked for.

I am still wondering why API Management will suddenly stop doing gzip encoding on the original problem. Sometimes it did it, then stop, which lead to some confusion as to what was going on.