0

I'm trying to connect an API endpoint in Azure (api management) to a backend service. However, the set-body policy isn't recognizing my JSON body and thus isn't transforming it for the backend call.

I've tried all iterations i can think of for the "Liquid" and "None" templates. The microsoft documentation is useless as even the "liquid" template is capitalized in the doc while it NEEDS to be lowercase. Even the Deep Dive article that everyone points to is misleading and/or out of date.

i was once able to get the {{context.Request.OriginalUrl}} reference to work using liquid template, but i can't seem to get the {{body.json}} reference to work

Here's the policy i have in the section (purely to test - this has no use for what i'm doing):

<set-body template="liquid">
    Calling User Agent: {{context.Request.OriginalUrl}}
</set-body>

And here's an example of what i have to try to read the json body (passing through via POST):

<set-body template="liquid">{{body}}</set-body>

I've tried several iterations and inputs like below:

<set-body template="liquid">{{body.json}}</set-body>

while passing through a body like this:

{"json":"this is an example body"}

No matter what I do, this is what I see in the trace after testing the call:

set-body (0.069 ms)
{
    "input": null,
    "output": ""
} 

i'm obviously open to using the "none" template, but i run into the same problems. The documentation is wrong - if i copy/paste the example:

<set-body>@(context.Body.As<String>())</set-body>

I get errors like:

One or more fields contain incorrect values:
Error in element 'set-body' on line 32, column 10: 'IProxyRequestContext' does not contain a definition for 'Body' and no extension method 'Body' accepting a first argument of type 'IProxyRequestContext' could be found (are you missing a using directive or an assembly reference?)

and when i do get it to not error, it returns the same "output":"" output.

HoosierDaddy
  • 3
  • 1
  • 4

1 Answers1

2

For being able to access the body as an object in the liquid template, you will have to set the Content-Type header to application/json as mentioned in the docs.
If your requests are already sending this header, then it should work without setting it too.

A policy like this in the inbound section will guarantee it works as expected

<set-header name="Content-Type" exists-action="override">
    <value>application/json</value>
</set-header>
<set-body template="liquid">{{body.json}}"}</set-body>

As for accessing it via the context variable, you have to access it as context.Request.Body.As<string>() as mentioned in the docs, so something like this

<set-body>@(context.Request.Body.As<string>())</set-body>

The official reference for set-body doesn't seem to have the problems you've mentioned.
Was there any other doc you are referring to? If its on learn.microsoft.com, you could open an issue at the end of each doc.

PramodValavala
  • 6,026
  • 1
  • 11
  • 30
  • i am trying to use @(context.Request.Body.As()) but it is not working for myself. I keep getting a 500 and on the trace i see an error. Before the set body I have a couple of other policies 'Set backend service', 'log to event hub', and then set body. can this have an impact? – markblue777 Apr 02 '19 at 15:19
  • "source": "set-body", "timestamp": "2019-04-02T15:17:24.1314885Z", "elapsed": "00:00:00.0012055", "data": { "messages": [ { "message": "Expression evaluation failed.", "expression": "context.Request.Body.As()", "details": "Object reference not set to an instance of an object." }, "Expression evaluation failed. Object reference not set to an instance of an object.", "Object reference not set to an instance of an object." ] – markblue777 Apr 02 '19 at 15:19
  • Are you trying to access `context.Request.Body` in your other policies? If so, make sure to use the `preserveContent` parameter to true - `context.Request.Body.As(preserveContent: true)`. This is documented in the same official doc as well. – PramodValavala Apr 02 '19 at 16:54
  • thank you PramodValavala. The content-type seemed to work although it is not clear in the documentation when to set this. I had to find it on the "deep Dive" article and even then it was toward the top. The One item i'm coming across now is that when I send in any "special characters" in the policy, it errors. i'm trying to pass through a simple json object that contains a URL with parameters.set-body doesn't like the "=", "&" or "^" characters, but they are necessary... any ideas on how to pass that through? – HoosierDaddy Apr 02 '19 at 19:46
  • The error is a bit misleading the problem seems to because of the `&` which is an escape character in XML. Since you need it to be a valid URL, replace it with `%26` – PramodValavala Apr 03 '19 at 07:10