Hello, I have a proxy with more than one ServiceCallouts, and I want to make a generic RaiseFault in case of error in my ServiceCallouts. The problem is that I want to return the status code of my ServiceCallout, and I just can return the content body.
I created this RaiseFault to catch my ServiceCallout errors, as you can see the <serviceCallout>.status.code doesn't work. The only way I could make this working was to put the ServiceCalloutResponse variable on the status code, but by doing this I will have to create a RaiseFault for each ServiceCallout policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RaiseFault async="false" continueOnError="false" enabled="true" name="RF-ServiceCalloutHandler">
<DisplayName>RF-ServiceCalloutErrorHandler</DisplayName>
<FaultRules/>
<Properties/>
<FaultResponse>
<Set>
<Payload contentType="application/json">
{
"type": "SERVICE CALLOUT ERROR",
"message": {ServiceCallout.response}// works
}
</Payload>
<StatusCode>{Dynamic.status.code}</StatusCode> // not working
<ReasonPhrase>Gateway Exception</ReasonPhrase>
</Set>
</FaultResponse>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<ShortFaultReason>false</ShortFaultReason>
</RaiseFault>
<Step>
<FaultRules/>
<Name>SC-MyServiceCallout</Name>
</Step>
<Step>
<Condition>(calloutResponse.status.code != 200)</Condition>
<Name>RF-ServiceCalloutHandler</Name>
</Step>
Solved! Go to Solution.
(I don't like this solution because it uses regex to get the error code)
I made a JS to get the ServiceCallout error code dynamic.
So, if my callout error code, is not a success.code it throw a exception, then I check on DefaultFaultRule if its a ServiceCallout error.
I used this repo as example:
Github - ServiceCalloutHandler
JS:
const SERVICE_CALLOUT_ERROR = "steps.servicecallout.ExecutionFailed"
const errorBody = JSON.parse(error.content);
const regex = /ResponseCode (\d+)/;
function handleCalloutError() {
const fault = errorBody.fault.faultstring;
const detail = errorBody.fault.detail.errorcode;
var match = fault.match(regex);
var statusCode = match ? match[1] : 500;
return {
isServiceCalloutError: detail == SERVICE_CALLOUT_ERROR,
statusCode: statusCode
}
}
const serviceCalloutError = handleCalloutError()
context.setVariable("is_service_callout_error",serviceCalloutError.isServiceCalloutError);
context.setVariable("service_callout_error_code", serviceCalloutError.statusCode);
RaiseFault:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RaiseFault async="false" continueOnError="false" enabled="true" name="RF-ServiceCalloutHandler">
<DisplayName>RF-ServiceCalloutErrorHandler</DisplayName>
<FaultRules/>
<Properties/>
<FaultResponse>
<Set>
<Payload contentType="application/json">
{ServiceCallout.response}
</Payload>
<StatusCode>{service_callout_error_code}</StatusCode>
<ReasonPhrase>Gateway Exception</ReasonPhrase>
</Set>
</FaultResponse>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<ShortFaultReason>false</ShortFaultReason>
</RaiseFault>
Proxy:
<Step>
<FaultRules/>
<Name>JS-ExtractServiceCalloutError</Name>
<Condition>(fault.name Matches "ExecutionFailed")</Condition>
</Step>
<Step>
<FaultRules/>
<Name>RF-ServiceCalloutHandler</Name>
<Condition>(fault.name Matches "ExecutionFailed") and (is_service_callout_error == true)</Condition>
</Step>