2
votes

I'm trying to transform a json response to xml if the request contains Accept=application/xml. Otherwise, the json response should be returned.

Here's my policy:

<policies>
  <inbound><base /></inbound>
  <backend><base /></backend>
  <outbound>
    <base />
    <json-to-xml apply="content-type-json" consider-accept-header="true" />
  </outbound>
  <on-error><base /></on-error>
</policies>

When I test this without an Accept header, all is well (200 OK and json is properly returned).

Adding the accept header, however, I get a 406 Not acceptable.

The trace (after adding the header Ocp-Apim-Trace:true), redacted is available at https://gist.github.com/jhgbrt/9df92cb0a140804ea01c. In that trace, you will see the following:

  • in the 'inbound' part confirm the request header 'Accept' with value 'application/xml' is present. The request-executor block contains a message saying "Request is being forwarded to the backend service."
  • in the 'outbound' block you already see the 406 not acceptable and the Accept header removed, after which the json-to-xml block fails because of this.

What am I missing?

1

1 Answers

2
votes

I suspect the problem is that your backend API doesn't support returning application/xml and has chosen to return 406 instead of ignoring the accept header and just returning JSON anyway.

One way to solve this might be (and I will try this also) is to store the accept header in a variable using <set-variable>, delete the Accept header from the inbound request using the <set-header> policy, and then on the outbound, use a <choose> policy to check the variable and only apply the transform if the accept header is application/xml

This policy should work, although I must admit I am having some issues getting my JSON to transform.

<policies>
    <inbound>

        <choose>
            <!-- Check for application/xml in the Accept Header -->
            <when condition='@(context.Request.Headers.GetValueOrDefault("Accept","").Contains("application/xml"))'>

                <!-- Update the accept header to ask for JSON -->
                <set-header name="Accept" exists-action="override">
                    <value>application/json</value>
                </set-header>

                <!-- Create flag to record that we switched accept header -->
                <set-variable name="ToXml" value="True" />
            </when>
            <otherwise>
                <set-variable name="ToXml" value="False" />
            </otherwise>
        </choose>

        <base/>
    </inbound>
    <backend>
        <base/>
    </backend>
    <outbound>
        <base/>
        <choose>
            <!-- If we switched the accept header, then apply conversion -->
            <when condition='@((string)context.Variables["ToXml"] == "True")'>
                <json-to-xml apply="always" consider-accept-header="false" />
            </when>
        </choose>
    </outbound>
</policies>