Hi !
I have created a proxy where the 404, 405, 406 and 415 have a custom message as part of the business requirements.
For example, I have 3 endpoints:
GET /cars
PUT /item/order
DELETE /item
note: I use the StartsWith on my condition so that if the request matches the first string of the pathSuffix, it will run the policy that matches it. (hope this makes sense or understandable)
My sample Proxy Endpoint Flow:
<ProxyEndpoint name="default">
<FaultRules>
<FaultRule/>
<FaultRule name="HandlingErrors">
<Step>
<Name>EV-ExtractRequest</Name>
<Condition>(proxy.pathsuffix =| "/cars") or (proxy.pathsuffix =| "/item/")</Condition>
</Step>
<Step>
<Name>JS-ErrorHandlingForItems</Name>
<Condition>(proxy.pathsuffix =| "/item/")</Condition>
</Step>
<Step>
<Name>JS-ErrorHandlingForCars</Name>
<Condition>(proxy.pathsuffix =| "/cars")</Condition>
</Step>
<Step>
<Name>AM-415UnsupportedMediaType</Name>
<Condition>(request.header.content-type != "application/xml; charset=utf-8") and
(request.header.content-type != "text/xml; charset=utf-8") and
(request.verb != "GET")
</Condition>
</Step>
<Step>
<Name>AM-406NotAcceptableException</Name>
<Condition>(request.header.accept != "application/xml; charset=utf-8") and (request.header.accept != "*/*")</Condition>
</Step>
<Condition>((request.header.content-type != "application/xml; charset=utf-8") and (request.header.content-type != "text/xml; charset=utf-8")) or
((request.header.accept != "application/xml; charset=utf-8") and (request.header.accept != "*/*"))
</Condition>
</FaultRule>
</FaultRules>
<PreFlow name="PreFlow">
<Request>
<Step>
<Name>RF-406NotAcceptableException</Name>
<Condition>(request.header.accept != "application/xml; charset=utf-8") and (request.header.accept != "*/*")</Condition>
</Step>
<Step>
<Name>RF-415UnsupportedMediaType</Name>
<Condition>(request.header.content-type != "application/xml; charset=utf-8") and (request.header.content-type != "text/xml; charset=utf-8") and (request.verb != "GET")</Condition>
</Step>
</Request>
<Response/>
</PreFlow>
<Flows>
<Flow name="Item">
<Description/>
<Request/>
<Response/>
<Condition>(proxy.pathsuffix MatchesPath "/item") and (request.verb = "DELETE")</Condition>
</Flow>
<Flow name="Order Item">
<Description/>
<Request>
<Step>
<Name>EV-ExtractRequest</Name>
</Step>
</Request>
<Response/>
<Condition>(proxy.pathsuffix MatchesPath "/item/order/*") and (request.verb = "PUT")</Condition>
</Flow>
<Flow name="Cars Lists">
<Description/>
<Request/>
<Response/>
<Condition>(proxy.pathsuffix MatchesPath "/cars") and (request.verb = "GET")</Condition>
</Flow>
<Flow name="NotFound">
<Request>
<Step>
<Name>EV-ExtractRequest</Name>
<Condition>(proxy.pathsuffix =| "/cars") or (proxy.pathsuffix =| "/item/")</Condition>
</Step>
<Step>
<Name>JS-ErrorHandlingForItems</Name>
<Condition>(proxy.pathsuffix =| "/item/")</Condition>
</Step>
<Step>
<Name>JS-ErrorHandlingForCars</Name>
<Condition>(proxy.pathsuffix =| "/cars")</Condition>
</Step>
<Step>
<Name>RF-405MethodNotAllowed</Name>
<Condition>(proxy.pathsuffix MatchesPath "/cars" and request.verb != "GET") or
(proxy.pathsuffix MatchesPath "/item/order/*" and request.verb != "PUT") or
(proxy.pathsuffix MatchesPath "/item" and request.verb != "DELETE")
</Condition>
</Step>
<Step>
<Name>RF-404NotFound</Name>
</Step>
</Request>
<Response/>
<Condition>(proxy.pathsuffix MatchesPath "/**")</Condition>
</Flow>
</Flows>
For my JavaScript Policy:
JS-ErrorHandlingForCars
(Note: This is almost the same with JS-ErrorHandlingForItems, the difference would be the structure of the finalResponse, and the handling of other error statusCode)
var statusCode = context.getVariable("response.status.code");
var errorStatusCode = context.getVariable("error.status.code");
var faultName = context.getVariable("fault.name");
var httpMethod = context.getVariable("request.verb");
var formattedDate = new Date(context.getVariable("system.timestamp")).toISOString();
function errResponse(summary, description) {
var finalResponse = "<?xml version='1.0' encoding='UTF-8'?>" +
"<response>" +
"<status>error</status>" +
"<description>" + description + "</description>" +
"<summary>" + summary + "</summary>" +
"<time>" + formattedDate + "</time>" +
"</response>";
return finalResponse;
}
} if (pathSuffix != "/car") {
var description = "Resource Not Found";
var summary = "Not Found";
var errorResponse = errResponse(summary, description);
print(errorResponse);
context.setVariable("finalResponse", errorResponse);
context.setVariable("response.header.Content-Type", "application/xml");
} else if (pathSuffix == "/car/" && httpMethod != "GET") {
var description = "Method used is not allowed";
var summary = "HTTP Method Not Allowed";
var errorResponse = errResponse(summary, description);
print(errorResponse);
context.setVariable("finalResponse", errorResponse);
context.setVariable("response.header.Content-Type", "application/xml");
} else if (faultName == "RaiseFault") {
if (errorStatusCode == 406) {
var description = "Server understands but can't fulfill the request";
var summary = "Not Acceptable";
var errorResponse = errResponse(summary, description);
print(errorResponse);
context.setVariable("finalResponse", errorResponse);
context.setVariable("response.header.Content-Type", "application/xml");
} else if (errorStatusCode == 415) {
var description = "Server can't process request";
var summary = "Unsupported Media Type";
var errorResponse = errResponse(summary, description);
print(errorResponse);
context.setVariable("finalResponse", errorResponse);
context.setVariable("response.header.Content-Type", "application/xml");
}
}
The problem here is, when I try to send a request that has no content-type, in my case I use postman. I got the apigee default error message instead of the custom message that I have created:
{
"fault": {
"faultstring": "Raising fault. Fault name : RF-415UnsupportedMediaType",
"detail": {
"errorcode": "steps.raisefault.RaiseFault"
}
}
}
It’s also not working for errors: 404, 405, and 406.
Any help on this is greatly appreciated. Thank you!