API Management - Convert SOAP POST to GET

Markus MeyerMarkus Meyer
2 min read

API Management is receiving a SOAP POST request with XML in the request body. Data from the request body has to be forwarded to a GET operation

Import SOAP Service

The public soap service https://www.dataaccess.com/webservicesserver/numberconversion.wso?op=NumberToDollars is imported in API Management.

image.png

The imported SOAP service in API management: image.png

Request-Body for SOAP service:

<?xml version="1.0" encoding="utf-8"?>
<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope">
  <Body>
    <NumberToDollars xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.dataaccess.com/webservicesserver/">
      <dNum>1</dNum>
    </NumberToDollars>
  </Body>
</Envelope>

The target API

An additional operation in the Echo API returns the mocked status 200.

image.png

<policies>
    <inbound>
        <base />
        <mock-response status-code="200" content-type="application/json" />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

This target API has to be replaced with a real-world API.

Transform POST to GET

The incoming request body is escaped and also has additional double quotes which has to be removed:

string xml = context.Request.Body.As<string>(preserveContent: true);
xml = Regex.Unescape(xml);

// Remove the double quotes
xml = xml.Remove(0,1);
xml = xml.Remove(xml.Length-1,1);

Transform the XML string into a JSON object:

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

var json = JsonConvert.SerializeObject(doc);
var data = JObject.Parse(json );

The transformed JSON string:

{
  "?xml": {
    "@version": "1.0",
    "@encoding": "utf-8"
  },
  "Envelope": {
    "@xmlns": "http://www.w3.org/2003/05/soap-envelope",
    "Body": {
      "NumberToDollars": {
        "@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
        "@xmlns": "http://www.dataaccess.com/webservicesserver/",
        "dNum": "1"
      }
    }
  }
}

Finally, the wanted data has to be returned from the JSON Object:

JObject envelope = data["Envelope"] as JObject;
JObject body = envelope["Body"] as JObject;
JObject numberToDollars = body["NumberToDollars"] as JObject;

return numberToDollars["dNum"].Value<string>();

The data has to be forwarded to the mocked API with a GET request:

<set-method>GET</set-method>
<set-backend-service base-url="https://rfqapiservicey27itmeb4cf7q.azure-api.net/echo/200/" />
<rewrite-uri template="@("/test?q=" + context.Variables.GetValueOrDefault<string>("num"))" copy-unmatched-params="false" />

Result

The complete policy:

<policies>
    <inbound>
        <base />
        <set-variable name="num" value="@{
            string xml = context.Request.Body.As<string>(preserveContent: true);
            xml = Regex.Unescape(xml);

            // Remove the double quotes
            xml = xml.Remove(0,1);
            xml = xml.Remove(xml.Length-1,1);

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            var data = JObject.Parse(JsonConvert.SerializeObject(doc));
            JObject envelope = data["Envelope"] as JObject;
            JObject body = envelope["Body"] as JObject;
            JObject numberToDollars = body["NumberToDollars"] as JObject;

            return numberToDollars["dNum"].Value<string>();
            }" />
        <set-method>GET</set-method>
        <set-backend-service base-url="https://rfqapiservicey27itmeb4cf7q.azure-api.net/echo/200/" />
        <rewrite-uri template="@("/test?q=" + context.Variables.GetValueOrDefault<string>("num"))" copy-unmatched-params="false" />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Testing it in API management:

image.png

The trace log:

image.png

GitHub answer

0
Subscribe to my newsletter

Read articles from Markus Meyer directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Markus Meyer
Markus Meyer

I am a developer and architect from Bavaria. I'm focused on Azure technologies. And I love coding in C#.