Use JavaScript Policy in Fault Rule

Hi Team, 

I tried to use JavaScript Policy in the fault rule to generate a response error, but I couldn't get the response I want. Is it possible to use JavaScript Policy in Fault Rule? or must it be an Assign Message Policy?

I simplified the code as below

Proxy code

<ProxyEndpoint name="default">
  <FaultRules>
    <FaultRule name="default-fault">
      <Step>
        <Name>JS-GenerateErrorResponse</Name>
      </Step>
    </FaultRule>
  </FaultRules>
  ...
</ProxyEndpoint>

JS code

var error = context.getVariable('fault.name');
const resp = {
    error: error
};

// context.setVariable('response.content') = JSON.stringify(resp);

var date = new Date();
context.setVariable("response.header.X-TIMESTAMP", date.toISOString());

When I tried to invoke an error/fault like InvalidClientIdentifier, I still get the default fault response.

When I tried to uncomment code in line 6. It got error 

Execution of JS-GenerateErrorResponse failed with error: Javascript runtime error: "TypeError: Cannot find default value for object. (generate-error-response.js:6)" 

 

Thanks

Solved Solved
0 4 301
2 ACCEPTED SOLUTIONS

@rizkyduut - In this case, since its thrown the Fault in the Request flow, the "response" object is not available for you to use within the JS policy. 

The best practice is to use the AssignMessage policy. Here is an example 

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage continueOnError="false" enabled="true" name="AM-SetErrorReponse">
    <DisplayName>AM-SetErrorReponse</DisplayName>
    <Properties/>
    <Set>
        <Headers>
            <Header name="X-TIMESTAMP">{system.time}</Header>
        </Headers>
        <Payload contentType="application/json">
            {
                "error": "{fault.name}"
            }
        </Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

 

This should do the trick

Or if you have some specific functionality you want to do via JS (that is not available in Assign Message), you could include both the policies in the FaultRules like

 

<FaultRules>
    <FaultRule name="default-fault">
        <Step>
            <Name>JS-GenerateErrorResponse</Name>
        </Step>
        <Step>
            <Name>AM-SetErrorResponse</Name>
        </Step>
    </FaultRule>
</FaultRules>

 

And in the JS you can have specific logic for example,

 

context.setVariable("X-TimeStamp-Header", new Date().toISOString());

 

 

and in the AssignMessage policy you can use all those variables you set in the JS policy

 

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage continueOnError="false" enabled="true" name="AM-SetErrorResponse">
    <DisplayName>AM-SetErrorResponse</DisplayName>
    <Properties/>
    <Set>
        <Headers>
            <Header name="X-TIMESTAMP">{X-TimeStamp-Header}</Header>
        </Headers>
        <Payload contentType="application/json">
            {
                "error": "{fault.name}"
            }
        </Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

 

 

View solution in original post

Just a couple notes.

1. This snip within an AssignMessage

 

   <AssignTo createNew="false" transport="http" type="response"/>

 

 ..is a no-op. It doesn't do anything.  You can omit it. 

2. I am able to use JavaScript things to manipulate the fault message. But I cannot use "response".  I use "message". For example if I attach this as a policy to the proxy FaultRules,

 

...

  <FaultRules>
    <FaultRule name='rule1'>
      <Step>
        <Name>JS-Manipulate-Response</Name>
      </Step>
    </FaultRule>
  </FaultRules>

...

 

...and if this is the JavaScript....

 

// manipulate-Response.js
// ------------------------------------------------------------------
/* jshint esversion:9, node:true, strict:implied */
/* global process, console, Buffer */

var m = context.getVariable('message.content');
m = JSON.parse(m);
m.timestamp = (new Date()).toISOString();
context.setVariable('message.content', JSON.stringify(m, null, 2));

 

...then the response I see looks like this: 

 

{
  "error": {
    "code": 500.01,
    "message": "random fault."
  },
  "timestamp": "2022-10-03T15:34:58.505Z"
}                                                                                                                                                                          

 

 

View solution in original post

4 REPLIES 4

@rizkyduut - In this case, since its thrown the Fault in the Request flow, the "response" object is not available for you to use within the JS policy. 

The best practice is to use the AssignMessage policy. Here is an example 

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage continueOnError="false" enabled="true" name="AM-SetErrorReponse">
    <DisplayName>AM-SetErrorReponse</DisplayName>
    <Properties/>
    <Set>
        <Headers>
            <Header name="X-TIMESTAMP">{system.time}</Header>
        </Headers>
        <Payload contentType="application/json">
            {
                "error": "{fault.name}"
            }
        </Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

 

This should do the trick

Or if you have some specific functionality you want to do via JS (that is not available in Assign Message), you could include both the policies in the FaultRules like

 

<FaultRules>
    <FaultRule name="default-fault">
        <Step>
            <Name>JS-GenerateErrorResponse</Name>
        </Step>
        <Step>
            <Name>AM-SetErrorResponse</Name>
        </Step>
    </FaultRule>
</FaultRules>

 

And in the JS you can have specific logic for example,

 

context.setVariable("X-TimeStamp-Header", new Date().toISOString());

 

 

and in the AssignMessage policy you can use all those variables you set in the JS policy

 

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage continueOnError="false" enabled="true" name="AM-SetErrorResponse">
    <DisplayName>AM-SetErrorResponse</DisplayName>
    <Properties/>
    <Set>
        <Headers>
            <Header name="X-TIMESTAMP">{X-TimeStamp-Header}</Header>
        </Headers>
        <Payload contentType="application/json">
            {
                "error": "{fault.name}"
            }
        </Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

 

 

Just a couple notes.

1. This snip within an AssignMessage

 

   <AssignTo createNew="false" transport="http" type="response"/>

 

 ..is a no-op. It doesn't do anything.  You can omit it. 

2. I am able to use JavaScript things to manipulate the fault message. But I cannot use "response".  I use "message". For example if I attach this as a policy to the proxy FaultRules,

 

...

  <FaultRules>
    <FaultRule name='rule1'>
      <Step>
        <Name>JS-Manipulate-Response</Name>
      </Step>
    </FaultRule>
  </FaultRules>

...

 

...and if this is the JavaScript....

 

// manipulate-Response.js
// ------------------------------------------------------------------
/* jshint esversion:9, node:true, strict:implied */
/* global process, console, Buffer */

var m = context.getVariable('message.content');
m = JSON.parse(m);
m.timestamp = (new Date()).toISOString();
context.setVariable('message.content', JSON.stringify(m, null, 2));

 

...then the response I see looks like this: 

 

{
  "error": {
    "code": 500.01,
    "message": "random fault."
  },
  "timestamp": "2022-10-03T15:34:58.505Z"
}                                                                                                                                                                          

 

 

Thanks @dchiesa1 - I totally forgot about "message" object. 

@rizkyduut - that being said, you can just get it to work with JS policy, just update your JS to something like this

var resp = {
    error: context.getVariable('fault.name')
};
context.setVariable('message.content', JSON.stringify(resp, null, 2));
var date = new Date();
context.setVariable("message.header.X-TIMESTAMP", date.toISOString());

wah thanks @dchiesa1! I think this way is neater