I'm trying to override the default senderorfilter for zuul proxy so that I can present a better response when a service behind my gateway has crashed/is down. Here is the code that I took from the answer in Customizing Zuul Exception
public class RabbrErrorFilter extends ZuulFilter {
private static final Logger log = LoggerFactory.getLogger(RabbrErrorFilter.class);
protected static final String SEND_ERROR_FILTER_RAN = "sendErrorFilter.ran";
@Override
public String filterType() {
return "post";
}
@Override
public int filterOrder() {
return Integer.MIN_VALUE; // Needs to run before SendErrorFilter which has filterOrder == 0
}
@Override
public boolean shouldFilter() {
// only forward to errorPath if it hasn't been forwarded to already
RequestContext ctx = RequestContext.getCurrentContext();
return ctx.containsKey("error.status_code") && !ctx.getBoolean(SEND_ERROR_FILTER_RAN,false);
}
@Override
public Object run() {
try {
RequestContext ctx = RequestContext.getCurrentContext();
Object e = ctx.get("error.exception");
if (e != null && e instanceof ZuulException) {
ZuulException zuulException = (ZuulException)e;
log.error("Zuul failure detected: " + zuulException.getMessage(), zuulException);
// Remove error code to prevent further error handling in follow up filters
ctx.remove("error.status_code");
// Populate context with new response values
ctx.setResponseBody("Overriding Zuul Exception Body");
ctx.getResponse().setContentType("application/json");
ctx.setResponseStatusCode(500); //Can set any error code as excepted
ctx.setSendZuulResponse(false);
}
}
catch (Exception ex) {
log.error("Exception filtering in custom error filter", ex);
ReflectionUtils.rethrowRuntimeException(ex);
}
return null;
}
I've checked with a debugger that the code in run() is executed when a zuul exception is thrown, but in the console log I get this:
com.netflix.zuul.exception.ZuulException: Forwarding error
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.handleException(RibbonRoutingFilter.java:157) ~[spring-cloud-netflix-core-1.1.0.RC2.jar:1.1.0.RC2]
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:132) ~[spring-cloud-netflix-core-1.1.0.RC2.jar:1.1.0.RC2]
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:78) ~[spring-cloud-netflix-core-1.1.0.RC2.jar:1.1.0.RC2]
at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112) ~[zuul-core-1.1.0.jar:1.1.0]
at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:197) ~[zuul-core-1.1.0.jar:1.1.0]
at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:161) ~[zuul-core-1.1.0.jar:1.1.0]
at com.netflix.zuul.FilterProcessor.route(FilterProcessor.java:120) ~[zuul-core-1.1.0.jar:1.1.0]
at com.netflix.zuul.ZuulRunner.route(ZuulRunner.java:96) ~[zuul-core-1.1.0.jar:1.1.0]
at com.netflix.zuul.http.ZuulServlet.route(ZuulServlet.java:116) ~[zuul-core-1.1.0.jar:1.1.0]
at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:81) ~[zuul-core-1.1.0.jar:1.1.0]
and the response from the service behind the gateway is timed out with status 500.
-- Edit* Updating the spring-cloud dependencies (contains zuul 1.3.0 core) did not fix this
Please check this solution: Spring Cloud: Zuul error handling. It worked for me, specially for Forwarding error of Zuul.
The Zuul error handling is being handled through RibbonRoutingFilter and SendErrorFilter and will forward any errored request to ${error.path}, which defaults to ‘/error’. In case you relay on the defaults that will be handled by Spring Boot’s BasicErrorController. You can overide this behaviour and implement your own ErrorController.
You don't necessarily need to follow a Vnd error style, just follow the general logic of coding a custom implementation of Spring's ErrorController
.