ServiceCallout does not expose full cache-control headers

I want to cache result from ServiceCallout. And want to derive information from the cache-control header in response of the ServiceCallout. I want to cache the data within Apigee based on the information returned by the server.

Service returns e.g. public, max-age=16544. I want to access the value of max-age. Unfortunately, Apigee only makes available the value "public".

With snippet of Javascript code, can dump all the header values. Only the value "public" is returned for the header cache-control. Can't get hold of that max-age value.

I experience this problem both with cloud and on-premise version (4.17.09). Suggestions very welcome!

1 3 357
3 REPLIES 3

Yes, I understand. The problem is the Apigee runtime is trying to be helpful in splitting the text of the header value by commas, and then returning the array.

When you refer to request.header.cache-control , you get the FIRST value in that array.

If you want to get the various values of a header that includes a comma, you can use these "variable names" :

variable name value
message.header.{header_name} the value of the header, or the first value of the header if the header text includes one or more commas
message.header.{header_name}.{N}
The Nth value of the header if the header text includes one or more commas. N starts at 1.
message.header.{header_name}.values The array of header values, if the header text includes one or more commas.

The variable reference documentation didn't say so a few minutes ago, but I've now modified it.

I think what you need to do is use something like this in your JS code.

  var a = context.getVariable('response.header.cache-control.values'); // java.util.ArrayList
  // Sorry! An Apigee Edge JS Callout cannot access a java.util.ArrayList
  a = a + ''; // coerce ArrayList to string
  // a = "[public, maxage=16544]"
  var parts = a.slice(1, -1).split(',').map(function(x){return x.trim();});
  context.setVariable('extracted_value', parts[1]); // "maxage=16544"


Thanks for the quick and very helpful feedback! Below my final implementation. Was using the Curity article as a source of inspiration, but their xtract-cache-duriation.js doesn't seem to correct.

// idpkeysResponse contains response message of service callout
var cacheDuration = null;
var cacheHeader = context.getVariable('idpkeysResponse.header.cache-control.values');
cacheHeader = cacheHeader + '';
var headerParts = cacheHeader.slice(1, -1).split(',').map(function(x){return x.trim();});
for (var i = 0; i < headerParts.length; i++) {
    headerPart = headerParts[i].trim();
    if (headerPart.startsWith("max-age=")) {
        valueParts = headerPart.split("=");
        if (valueParts.length == 2) {
            cacheDuration = valueElse(valueParts[1], "").trim();
            break;
        }
    }
}
if (isInt(cacheDuration)) {
    cacheDuration = cacheDuration;
} else {
    cacheDuration = 300;
}

After reading the docs more thoroughly, better/cleaner/nicer solution below.

var cacheDuration = null;
var cacheValCnt = context.getVariable('idpkeysResponse.header.cache-control.values.count');
print("cache-control.length ", cacheValCnt);
for (var i = 1; i <= cacheValCnt; i++) {
    var hdrStr = 'idpkeysResponse.header.cache-control.' + i;
    var headerPart = context.getVariable(hdrStr);
    if (headerPart !== null) {
        if (headerPart.startsWith("max-age=")) {
            valueParts = headerPart.split("=");
            if (valueParts.length == 2) {
                cacheDuration = valueElse(valueParts[1], "").trim();
                print("cacheDuration "+ cacheDuration);
                break;
            }
        }
    }
}