Customize Default Fault format

Not applicable

By Fault Errors responded in below format. Is there anyway we can customize the format. I want to make consistent fault response between my target server and apigee' fault. Thanks.

{
  "fault": {
    "faultstring": "Invalid Id",
    "detail": {
      "errorcode": "400",
      "info": "Contact: support@support.com"
    }
  }
}
1 14 926
14 REPLIES 14

Yes you can! With FaultRules.

Basically FaultRules are like "catch" clauses in a proxy or target flow. You insert them, and then you can use a JS policy or an AssignMessage to set the precise message you would like to send.

I've attached here an example proxy bundle that illustrates. It contains two proxy endpoints: one to dispense a token, and another to validate the token, and potentially reformat the error message if the token is not legal.

To use it, deploy it to an Edge environment. Create an API Product and include the API proxy into it. Add a developer app with authorization to the API Product. Then create a token:

curl -i -X POST -u CLIENT_ID:CLIENT_SECRET https://ORGNAME-ENVNAME.apigee.net/kumaresan1/oauth2-cc/token -d grant_type_client_credentials 

This token is set to expire in 60 seconds. Then, invoke the other proxy endpoint to verify the token:

curl -i -H 'Authorization: Bearer TOKEN_HERE' https://ORGNAME-ENVNAME.apigee.net/kumaresan1/resource/t1

You will see a valid message if you invoke this API within 60 seconds. After 60 seconds, you will see a reformatted error message, like this:

{
  "error": {
    "detail": {
      "errorcode": 401,
      "info": "Contact: support@support.com"
    },
    "message": "Access Token expired"
  }
}

kumaresan1.zip

well !! I have seen Fault Handling where I need to define the condition(s) and anytime flow matches with that condition and control will enter into Error Flow.

But, My question scenarios which are not handled using Fault Handling or Raise Fault, that situation Apigee returns a response as Standard Format as shown above my original Post. I want to Edit that format. Is that Achievable ?

In Edge, there are two interesting aspects to Faults - Raising them, or Handling them.

You wrote: "I need to define the condition(s) and anytime flow matches with that condition and control will enter into Error Flow." I think your statement refers to raising faults explicitly, with the RaiseFault policy. For example you could raise a fault if an incorrect content-type is passed in, with a POST request. This might look like this:

<Step>
  <Name>RaiseFault-1</Name>
  <Condition>Not (request.content-type =| "application/json")</Condition>
</Step>

Or you could explicitly Raise a Fault when the inbound request uses a malformed ID in the url path. This would look the same as the above, except it would use a different condition. Then int he RaiseFault policy, you can specify the response status code , the response payload, and the response headers. It's nice to be able to explicitly raise faults based on conditions in the flow.

In Apigee Edge, the built policies can implicitly raise faults, as for example with VerifyApiKey, or AccessControl. Faults can also occur when backend systems fail to respond, or respond with 400 or 500 errors.

In any of these cases, whether you explicitly raise a fault with RaiseFault, or if a Fault occurs due to some other occurrence, the processing of the message enters "fault flow". And at this point you can use FaultRules to handle the faults. This is all described in the documentation I linked to above.

Within FaultRules, you do not normally raise new faults. You would not use RaiseFault, normally, within a FaultRules section. There's already a fault, so no need to raise one. Instead, you have the opportunity to adjust the fault message, which i think is exactly what you asked about.

Within a FaultRules sequence, you can use AssignMessage, or a JS policy, to modify the response payload, or the status code, etc.

Does that cover what you want to do?

@Dino

Thanks ! Sorry, if my question is confused. I know how to work with Raise Fault or Fault Rules. But my Question is, how to change or update the built-in policies implicit fault error JSON format in Apigee Edge ? Example : As you mentioned your last reply, "with VerifyApiKey, or AccessControl. Faults can also occur when backend systems fail to respond, or respond with 400 or 500 errors." -- This returns a certain format of fault. Is there anyway i can change that JSON format ? thank you once again.

There is no way to change the built-in fault messages that policies emit. The best way to do what you want - to change the JSON payload - is to use FaultRules, with a JS policy, to modify the messages that have been generated.

In JS, you would do something like this:

// modifyFault.js

var c = JSON.parse(response.content);

// modify c here.
c.newField = "anything you like";
c.error = {
  property1 : "something",
  property2 : (new Date()).toString()
};

// can also remove properties
if (c.fault) {delete c.fault};

// finally, put the hash back into response content:
response.content = JSON.stringify(c);

// or, prettified: 
// response.content = JSON.stringify(c, null, 2)+'\n';

@Dino Thanks !! When you say JSON payload, I think you meant JSON format which i want. Isn't it ? How do i change the message format using JS policy ? Do you have any Samples? Appriciate your help.

See above - I showed the code. If that anwer is not clear, let me know what else I can explain.

Thanks

@Dino

I think your suggestion would gratefully help since can not edit build-in fault message.

I have taken your example above and worked through following for Oauth Policy. At Proxy Endpoint Preflow, I have Oauth Policy to verify the access code. I have put my DefaultFaultRules as below at Target Endpoint in order capture when Access Token Expired like below.

 <DefaultFaultRule name="Default-Fault-rule">        
       <Step>
        <Name>Custom-Fault-Message</Name>
        <Condition>(fault.name = "access_token_expired")</Condition>
       </Step>
        <AlwaysEnforce>true</AlwaysEnforce>
  </DefaultFaultRule>

Here "Custom-Fault-Message" is nothing but, my custom JS Policy code as you mentioned on your example.

So, when I run my proxy after access token is expired, i get stopped at Oauth Policy itself and response is default standard fault message and Did not go to DefaultFaultRules which is under Target Endpoint - default.

2946-capture33.png

In case, I put my DefaultFaultRule in Proxy End Point - default, it reached fault condition and tried to execute custom JS, but it fails due to I think response.content is null at this time since this proxy endpoint preflow. I think response.content is not available at this stage. I am not sure...

2947-capture34.png

But, at UI I still get build-in fault message.

{
  "fault": {
    "faultstring": "Access Token expired",
    "detail": {
      "errorcode": "keymanagement.service.access_token_expired"
    }
  }
}

So, How do i handle this situation ? Is there anyway to write common to handle all type of faults to customize ? Thanks for your help !!

Hi Kumaresan. See my original answer. I posted working code there.

@Dino Thanks !! I imported the Sample Proxy Bundle and loaded into Edge. I did not configured secure proxy, So I changed to default and run the first Curl command which did not provide me the Access Token some reason. But, I see the JS file which handles Custom Error. But, I am still going through the proxy to understand and how it would work for me. Does CURL expected to return Access Token only on secure type ?

Ah, yes. the "secure" vhost implies https as the scheme.

the "default" vhost implies http.

so if you do not use the vhost named "secure", and you are using the vhost name "default" you must modify the curl command to use http, and not https.

@Dino

Yes, I changed to "default" and updated the Curl command to look http and corresponding Port #. But, I did not produced the access token from first Curl Command.

yes, well then you have a separate problem. I suppose to diagnose that you will have to look at the actual message returned.

@Kumaresan Sithambaram , Article here by @oseymen@apigee.com explains exactly your use case, How to make consistent fault response. Keep us posted.