Correct Way to Return Error from JavaScript Policy

Can someone point me to an example of having EDGE return a 400 error (with message) from within a pre-flow JavaScript policy?

Solved Solved
3 11 16.5K
2 ACCEPTED SOLUTIONS

akoo
Participant V

The following is the most typical pattern for JS error checking:

try{
< ..JS CODE..>
} catch (err) {
throw 'Error in JavaScript';
}

and then you can further refine the error message code and other details in Fault Rules. You could also refine the error message further in the JS itself, like below:

try{
< ..JS CODE..>
} catch (err) {
setResponse(outputFormat, "500", "Internal Server Error", "Unknown Error Occurred", err.message);
}

function setResponse(errorStatus, errorReason, errorMessage, errorDetail) {


	var errorContent = "";



	var json = {};
	json.Error = {};
	json.Error.Message = errorMessage;
	json.Error.Detail = errorDetail;

	errorContent = JSON.stringify(json);

	context.setVariable("error.status.code", errorStatus);
	context.setVariable("error.reason.phrase", errorReason);
	context.setVariable("error.header.Content-Type", "application/json");
	context.setVariable("error.content", errorContent);


}

View solution in original post

Thanks for the suggestions @Claudius Mbemba and @Alex Koo.

I ended up setting a variable in the JS policy and then conditionally running a "Raise Fault" policy based on that variable. Eg:

JS-Policy:

context.setVariable("triggerError", "true");

Pre-Flow:

<Step> 
    <FaultRules/>
    <Name>JS-Policy</Name> 
</Step>
<Step> 
    <Condition>triggerError equals "true"</Condition> 
    <FaultRules/> 
    <Name>RaiseFault-Policy</Name> 
</Step>

View solution in original post

11 REPLIES 11

Hi @williamking, you can try something along these lines:

//Create the payload
var response = {};
response.message = "Bad request. Mandatory params missing.";
response.code = 49; //Any custom values that you need in the error message


//Set the payload
response = JSON.stringify(response);
context.setVariable("response.content", response);


//Set the http response code
context.setVariable("response.status.code", 400);

//Set the http response phrase
context.setVariable("response.reason.phrase", "Bad Request");

Let me know if this took care of your problem.

Thanks @Cladius Fernando. I let you know when I am able to test that. Does setting the status code trigger an immediate return after that policy?

@williamking, I did not notice the "pre-flow" (assuming request) part of your question. The above snippet will only work in the response flow. If you want to return control from a JS policy in the request flow, you might want to explore setting a custom-error apigee flow variable from your JS. Additionally, to return the flow from the JS script you would need to throw an error and ensure that the JS policy has "continueOnError" set to false. You can then have a FaultRule to handle the payload with the condition based on this flow variable. Makes sense?

akoo
Participant V

The following is the most typical pattern for JS error checking:

try{
< ..JS CODE..>
} catch (err) {
throw 'Error in JavaScript';
}

and then you can further refine the error message code and other details in Fault Rules. You could also refine the error message further in the JS itself, like below:

try{
< ..JS CODE..>
} catch (err) {
setResponse(outputFormat, "500", "Internal Server Error", "Unknown Error Occurred", err.message);
}

function setResponse(errorStatus, errorReason, errorMessage, errorDetail) {


	var errorContent = "";



	var json = {};
	json.Error = {};
	json.Error.Message = errorMessage;
	json.Error.Detail = errorDetail;

	errorContent = JSON.stringify(json);

	context.setVariable("error.status.code", errorStatus);
	context.setVariable("error.reason.phrase", errorReason);
	context.setVariable("error.header.Content-Type", "application/json");
	context.setVariable("error.content", errorContent);


}

@Alex Koo, can you describe how you would use these error messages in the Fault Flow? I tried putting in a "<Condition>(error.content = "some_error_message")</Condition>" but that doesn't seem to work.

Try checking for values in any of those variables, e.g., error.status.code != "". Then in the policy with the condition, you can format the error message to your liking.

@alexkoo Is there a way we can catch the faultstring that we would normally get without the try catch?

And if we activate continueOnError, could we catch faultstring?

ex: 

{
    "fault": {
        "faultstring""Execution of mapping_response failed with error: Javascript runtime error: \"TypeError: Cannot find function forEach in object 2BXNCBC10DV000127. (mapping_response.js:20)\"",
        "detail": {
            "errorcode""steps.javascript.ScriptExecutionFailed"
        }
    }
}

Im interested in having the error line: (mapping_response.js:20) and i cant catch it with your try_catch.

ask a new question please, instead of embedding a question in a response to a thread that is 7 years old.

ask-a-new-question.png

Thanks for the suggestions @Claudius Mbemba and @Alex Koo.

I ended up setting a variable in the JS policy and then conditionally running a "Raise Fault" policy based on that variable. Eg:

JS-Policy:

context.setVariable("triggerError", "true");

Pre-Flow:

<Step> 
    <FaultRules/>
    <Name>JS-Policy</Name> 
</Step>
<Step> 
    <Condition>triggerError equals "true"</Condition> 
    <FaultRules/> 
    <Name>RaiseFault-Policy</Name> 
</Step>

I like this solution the best. Simple and clear.

Hi @williamking, While your solution is succinct, it will not catch errors at the meta-JS level. When the JS code fails, itself, then the Edge engine will send flow control to the Fault section of your proxy. Flow control will not continue to the next Step in the flow, and so your condition will not be checked.