private static String buildCacheID(ApiRequest request, IPolicyContext context) {
        StringBuilder cacheId = new StringBuilder();
        if (request.getContract() != null) {
            cacheId.append(request.getApiKey());
        } else {
            cacheId.append(request.getApiOrgId()).append(KEY_SEPARATOR).append(request.getApiId())
                    .append(KEY_SEPARATOR).append(request.getApiVersion());
        }
        cacheId.append(KEY_SEPARATOR).append(request.getType()).append(KEY_SEPARATOR)
                .append(request.getDestination());

        // According to RFC7234 (https://tools.ietf.org/html/rfc7234#section-2),
        // 'The primary cache key consists of the request method and target URI.'
        if (!request.getQueryParams().isEmpty()) {
            cacheId.append("?").append(request.getQueryParams().toQueryString());
        }

        //use hashed payload to ensure right caching of request with different bodies.
        IPayloadIO requestPayloadIO = context.getAttribute(PolicyContextKeys.REQUEST_PAYLOAD_IO, null);
        Object requestPayload = context.getAttribute(PolicyContextKeys.REQUEST_PAYLOAD, null);
        if (requestPayloadIO != null && requestPayload != null) {
            try {
                byte[] payloadBytes = requestPayloadIO.marshall(requestPayload);
                cacheId.append('_').append(DigestUtils.sha256Hex(payloadBytes));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        return cacheId.toString();
    }
Builds a cached request id composed by the API key followed by the HTTP
verb and the destination. In the case where there's no API key the ID
will contain ApiOrgId + ApiId + ApiVersion
gateway/engine/policies/src/main/java/io/apiman/gateway/engine/policies/CachingResourcesPolicy.java