0
votes

I am working on a change to a working API Management endpoint. I needed to send the request body to a backend service for some authentication / validation before calling the backend service.

I used context.Request.Body.As<string>(preserveContent: true) to get a copy of the original request body.

However, now my <set-body template="liquid"> template fails with the message "Stream was not readable".

The template is responsible for converting the request body, which is XML, to a JSON format, which the backend accepts.

It was my understanding that using preserveContent: true will allow the liquid template to access the body but it doesn't appear to be the case.

What other options do I have? Can I store the body on a variable and pass it to liquid explicitly? Is it better to just revert to LINQ to XML, where I at least got control of the data?

Edit:

I have since then abandoned using this feature of liquid for a more manual, but reliable approach.

1
That does not seem right, couldn't reproduce it right now. Could you show whole policy you're using, and possible trace of a failing request? Just make sure to remove all secrets that are there.Vitaliy Kurokhtin

1 Answers

0
votes

Via the following inbound API Management policies, using a Liquid template, it gets converted into a valid SOAP request.

<inbound>
   <base />

   <!--Change for GET to POST-->
   <set-method>POST</set-method>

   <!--Set mandatory SOAPAction HTTP header-->
   <set-header name="SOAPAction" exists-action="override">
      <value>GetOrderDetails</value>
   </set-header>

   <!--Create SOAP Request via liquid template-->
   <set-body template="liquid">
      <GetOrderDetails xmlns="tvh.blogs">
         <OrderId>{{context.Request.MatchedParameters["orderId"]}}</OrderId>
      </GetOrderDetails>
   </set-body>

</inbound>

The xml-to-json policy is not sufficient for this scenario, because some fields require renaming, the order needs to be controlled and dates need to be formatted.

<outbound>
   <base />

   <!--Create JSON Response via liquid template-->
   <set-body template="liquid">
   {
   "orderId" : "{{body.GetOrderDetailsResponse.OrderId}}",
   }
   </set-body>

   <!--Set correct content type-->
   <set-header name="Content-Type" exists-action="override">
      <value>application/json</value>
   </set-header>
</outbound>

For more details, you could refer to this article.