SOAP Service : Fault Responses in JSON? How to change it...

Not applicable

Hi,

I have SOAP Pass-through service proxy on edge. Now problem is any fault messages are coming as JSON. so how do i change it to a valid soap xml reponse against default behavior of Apigee.

For example : Invalid API Key

{
  "fault": {
    "faultstring": "Invalid ApiKey",
    "detail": {
      "errorcode": "oauth.v2.InvalidApiKey"
    }
  }
}

I have attempted to add DefaultFaultRule to convert json to xml, not sure am doing it right...i's not working.

<DefaultFaultRule name="Default-Fault-rule">
        <Step>
            <Name>JSON-to-XML</Name>
        </Step>
</DefaultFaultRule>

Solved Solved
2 8 3,295
1 ACCEPTED SOLUTION

I think you want to use FaultRules . We say the request processing within Apigee Edge enters "fault status" when a fault occurs; this would happen in various situations, including but not limited to when a VerifyApiKey policy fails because

  • no api key was presented
  • the api key presented was invalid
  • the api key presented was expired

Each fault generates its default response message, including a status code and a payload. With FaultRules , you can replace those response messages with your own. You would like a SOAP message, no problem.

Here's some code I use regularly in my API Proxies:

<ProxyEndpoint name='whatever'>
  <Description>...</Description>
  <HTTPProxyConnection>...</HTTPProxyConnection>
  <FaultRules>
    <FaultRule name="invalid-key">
      <Step>
        <Name>AM-SoapFault-InvalidApiKey</Name>
      </Step>
      <Condition>(fault.name = "InvalidApiKeyForGivenResource" OR fault.name = "InvalidApiKey" OR fault.name = "DeveloperStatusNotActive" OR fault.name = "invalid_client-app_not_approved")</Condition>
    </FaultRule>
    <FaultRule name="expired-key">
      <Step>
        <Name>AM-SoapFault-ExpiredApiKey</Name>
      </Step>
      <Condition>fault.name = "consumer_key_expired"</Condition>
    </FaultRule>
  </FaultRules>
  ...

OK, what's going on there?

There are two fault rules. one is named "invalid-key" and one is named "expired-key". The names aren't significant. Each FaultRule includes a Condition. When the Condition evaluates to true, then the FaultRule applies; the rules appearing later in the list take precedence. In my case, each FaultRule does just one thing: invokes a single policy, which is an AssignMessage policy. The AssignMEssage policy (not shown yet) just replaces the default response message with something of my choice. in your case you want it to be a SOAP message.

ok, let's look at the conditions. The "invalid-key" Condition handles all cases in which the apikey was invalid. The key is bogus, or it is valid, but not for the request API proxy, or the developer account has been disabled, or the app has not been approved... You get the picture. I want to handle all those cases with the same response message.

The second FaultRule applies when the key has expired. That causes a different message to be sent to the requesting app.

Now, what do you want your AssignMessage policies to look like? How about something like this:

<AssignMessage name="AM-SoapFault-InvalidApiKey">
  <DisplayName>AM-SoapFault-InvalidKey</DisplayName>
  <AssignTo createNew="false" transport="http" type="response"/>
  <Set>
    <Payload contentType='text/xml' variablePrefix='{' variableSuffix='}'>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode>109239839</faultcode>
         <faultstring>InvalidApiKey</faultstring>
         <detail>The key you presented was invalid</detail>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>
    </Payload>
    <StatusCode>400</StatusCode>
    <ReasonPhrase>Bad Request</ReasonPhrase>
  </Set>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</AssignMessage>

View solution in original post

8 REPLIES 8

Hi @Pravin,

Are you getting an error in JSON-to-XML policy? You can check in trace if this policy is failing for some reason. Also if possible let me know how you have configured this policy.

Please check the Source and OutputVariable values in JSON-to-XML policy . For more details please refer here.

@GargiTalukdar

No error because Json-To-XML is not getting called. Please refer my post, i have added json-to-xml policy under "DefaultFaultRule" expecting all fault response to get transform to XML instead of json.

Json-to-Xml Policy content :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JSONToXML async="false" continueOnError="false" enabled="true" name="JSON-to-XML">
    <DisplayName>JSON to XML Error Message</DisplayName>
    <Properties/>
    <Options>
        <NullValue>NULL</NullValue>
        <NamespaceBlockName>#namespaces</NamespaceBlockName>
        <DefaultNamespaceNodeName>$default</DefaultNamespaceNodeName>
        <NamespaceSeparator>:</NamespaceSeparator>
        <TextNodeName>#text</TextNodeName>
        <AttributeBlockName>#attrs</AttributeBlockName>
        <AttributePrefix>@</AttributePrefix>
        <InvalidCharsReplacement>_</InvalidCharsReplacement>
        <ObjectRootElementName>Root</ObjectRootElementName>
        <ArrayRootElementName>Array</ArrayRootElementName>
        <ArrayItemElementName>Item</ArrayItemElementName>
    </Options>
    <OutputVariable>response</OutputVariable>
    <Source>response</Source>
</JSONToXML>

In case an exception is raised , DefaultFaultRule should execute unless a fault rule with raise fault policy in it executes first. I am not sure why this is not happening and cannot comment without looking at the proxy bundle. If possible please share the bundle.

@Pravin : if your policy is not getting called then reason is that its not getting into the error flow.By default, Edge treats HTTP response codes in the 1xx-3xx range as 'success', and HTTP response codes in the range 4xx-5xx as 'failure'. That means any response from the backend service with an HTTP response code 4xx-5xx automatically invokes the Error flow, which then returns an error message directly to the requesting client.

I am getting error code 401, but still it is a json response expecting a valid soap xml.... not sure how to achieve it..

3185-error401.png

Hi @Pravin, I have attached a dummy proxy bundle with JSON-to-XML policy added in the DefaultFaultRule and a Verify API Key policy which will fail in case an invalid apikey is passed in the queryparameter and I am able to generate the response in XML. faulthandling-rev2-2016-07-15.zip Kindly check if this helps.

hi @GargiTalukdar

could you please post your request and response of this proxy. when i tested i was still getting a json response.

{
  "fault": {
    "faultstring": "Invalid ApiKey",
    "detail": {
      "errorcode": "oauth.v2.InvalidApiKey"
    }
  }
}

I think you want to use FaultRules . We say the request processing within Apigee Edge enters "fault status" when a fault occurs; this would happen in various situations, including but not limited to when a VerifyApiKey policy fails because

  • no api key was presented
  • the api key presented was invalid
  • the api key presented was expired

Each fault generates its default response message, including a status code and a payload. With FaultRules , you can replace those response messages with your own. You would like a SOAP message, no problem.

Here's some code I use regularly in my API Proxies:

<ProxyEndpoint name='whatever'>
  <Description>...</Description>
  <HTTPProxyConnection>...</HTTPProxyConnection>
  <FaultRules>
    <FaultRule name="invalid-key">
      <Step>
        <Name>AM-SoapFault-InvalidApiKey</Name>
      </Step>
      <Condition>(fault.name = "InvalidApiKeyForGivenResource" OR fault.name = "InvalidApiKey" OR fault.name = "DeveloperStatusNotActive" OR fault.name = "invalid_client-app_not_approved")</Condition>
    </FaultRule>
    <FaultRule name="expired-key">
      <Step>
        <Name>AM-SoapFault-ExpiredApiKey</Name>
      </Step>
      <Condition>fault.name = "consumer_key_expired"</Condition>
    </FaultRule>
  </FaultRules>
  ...

OK, what's going on there?

There are two fault rules. one is named "invalid-key" and one is named "expired-key". The names aren't significant. Each FaultRule includes a Condition. When the Condition evaluates to true, then the FaultRule applies; the rules appearing later in the list take precedence. In my case, each FaultRule does just one thing: invokes a single policy, which is an AssignMessage policy. The AssignMEssage policy (not shown yet) just replaces the default response message with something of my choice. in your case you want it to be a SOAP message.

ok, let's look at the conditions. The "invalid-key" Condition handles all cases in which the apikey was invalid. The key is bogus, or it is valid, but not for the request API proxy, or the developer account has been disabled, or the app has not been approved... You get the picture. I want to handle all those cases with the same response message.

The second FaultRule applies when the key has expired. That causes a different message to be sent to the requesting app.

Now, what do you want your AssignMessage policies to look like? How about something like this:

<AssignMessage name="AM-SoapFault-InvalidApiKey">
  <DisplayName>AM-SoapFault-InvalidKey</DisplayName>
  <AssignTo createNew="false" transport="http" type="response"/>
  <Set>
    <Payload contentType='text/xml' variablePrefix='{' variableSuffix='}'>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode>109239839</faultcode>
         <faultstring>InvalidApiKey</faultstring>
         <detail>The key you presented was invalid</detail>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>
    </Payload>
    <StatusCode>400</StatusCode>
    <ReasonPhrase>Bad Request</ReasonPhrase>
  </Set>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</AssignMessage>