Can I restrict Azure API Management cache storage by response content?

316 Views Asked by At

I have an OLTP API where a client can check for the status of a transaction.

Often, clients make multiple status requests for a transactions which are in a final state e.g. cancelled. I'd like to leverage Azure API Management response caching but ONLY for responses where the transaction status was final.

The API response body message is simply URL encoded e.g. reference=ABC123&status=Cancelled&amount=123.45 so determining if the transaction status is final should be simple

UPDATE

Thanks to @MohamadHaidar answer, I was able to construct a policy to achieve the caching, however the response body is now blank! I suspect this is because its being read by the condition and its only able to be read once?

<policies>
    <inbound>
        <base />
        <cache-lookup vary-by-developer="false" vary-by-developer-groups="false" downstream-caching-type="none" />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
        <choose>
            <when condition="@(Regex.IsMatch(context.Response.Body.As<string>(), @"status=(Cancelled|Paid)"))">
                <cache-store duration="3600" />
            </when>
        </choose>
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>
2

There are 2 best solutions below

0
Jimbo On BEST ANSWER

SOLUTION

Thanks to @MohamadHaidar answer, I was able to construct my solution which I have shared below.

NOTE: One needs to set preserveContent: true when reading the request/response body (unless you're going to set your own body after having read the existing one) otherwise it will no longer be available in the pipeline. More on that here

So, the final solution was per below:

<policies>
    <inbound>
        <base />
        <cache-lookup vary-by-developer="false" vary-by-developer-groups="false" downstream-caching-type="none" />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
        <choose>
            <when condition="@(Regex.IsMatch(context.Response.Body.As<string>(preserveContent: true), @"status=(Cancelled|Paid)"))">
                <cache-store duration="3600" />
            </when>
        </choose>
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>
3
Mo Haidar On

You can conditionally cache values using control flow policies https://learn.microsoft.com/en-us/azure/api-management/api-management-advanced-policies#choose

All you need to do is to put the cache store inside the choose/When policy https://learn.microsoft.com/en-us/azure/api-management/api-management-caching-policies#policy-statement-1