Hash a value from request and add to cache

corylprice
Participant I

Hi,

I have a task where someone sends a request to apigee with a key and a value for example Key: test, value:helloworld in the header and I need to hash the value and cache it before sending the request to the backend.

I've seen that this can be done using an AssignMessage policy but I havent a solution of how it can be done.

Any help on this would be much appreciated 🙂

Thanks in advance

1 3 721
3 REPLIES 3

How about this:?

<AssignMessage name='AM-HashValue'>
  <AssignVariable>
    <Name>hash_result</Name>
    <Template>{sha256Hex(request.header.something)}</Template>
  </AssignVariable>
</AssignMessage>

Notes:

  1. This uses a new "static function" available in message templates to compute the hash, and it also uses the new Template element under AssignVariable.
  2. This approach does not normalize the value of the header. If you need to do that, there's an extra step.

@Dino-at-Google Thanks for the quick response Dino, what is the extra step to normalize the value of the header?

By "normalize" maybe I should have said.... "canonicalize". And maybe you understand what I mean, but here's an illustration. Let's suppose the header is supposed to contain a JSON value. The client might pass this:

{ "key" : "value1" }

Notice there are spaces in there: between the open-curly and the first quote. before and after the colon. Before the close curly. The hex-encoded sha256 for that string, with all the spaces, according to this page, is

c870c19976aba77046667dc9b9986c73a8e4805c99186bc8ea6e7e56e5fe130b<br>

Now suppose the client eliminates spaces. The JSON is this:

{"key":"value1"}<br>

Semantically equal. This JSON represents the same information as the previous JSON. But the sha256 of the second string is

dfada72ccc2244e8c7aef8f0dbe7c026a6553bc5bda3f7654f3d0b94dd51a23b<br>

And obviously that's different. If you use the simple sha256 as the cache key, you will get two distinct cache entries for those inbound values. I think maybe you want a single cache entry, although it's possible you don't care either way.

if you want a single cache entry for each JSON that is semantically the same, you need to canonicalize the inbound json in order to get the same key.

"canonicalize": convert to a standard form, either with a standard amount of spaces, or with zero spaces... something like that. It doesn't matter, as long as you are consistent. For JSON it's pretty easy. Normalizing the value would require a JavaScript step, before the AssignMessage with code something like this:

var json = JSON.parse(context.getVariable('request.header.something'));
var canonicalized = JSON.stringify(json); // a canonicalized json string
context.setVariable('canonicalized'), canonicalized); 

(JSON.stringify removes all the extraneous whitespaces.)

And then the AssignMessage would be

<AssignMessage name='AM-HashValue'>
  <AssignVariable>
    <Name>hash_result</Name>
    <Template>{sha256Hex(canonicalized)}</Template>
  </AssignVariable>
</AssignMessage><br>