Customizing Zuul Exception
The Zuul RequestContext doesn't contain the error.exception
as mentioned in this answer.
Up to date the Zuul error filter:
@Component
public class ErrorFilter extends ZuulFilter {
private static final Logger LOG = LoggerFactory.getLogger(ErrorFilter.class);
private static final String FILTER_TYPE = "error";
private static final String THROWABLE_KEY = "throwable";
private static final int FILTER_ORDER = -1;
@Override
public String filterType() {
return FILTER_TYPE;
}
@Override
public int filterOrder() {
return FILTER_ORDER;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
final RequestContext context = RequestContext.getCurrentContext();
final Object throwable = context.get(THROWABLE_KEY);
if (throwable instanceof ZuulException) {
final ZuulException zuulException = (ZuulException) throwable;
LOG.error("Zuul failure detected: " + zuulException.getMessage());
// remove error code to prevent further error handling in follow up filters
context.remove(THROWABLE_KEY);
// populate context with new response values
context.setResponseBody("Overriding Zuul Exception Body");
context.getResponse().setContentType("application/json");
// can set any error code as excepted
context.setResponseStatusCode(503);
}
return null;
}
}
We finally got this working [Coded by one of my colleague]:-
public class CustomErrorFilter extends ZuulFilter {
private static final Logger LOG = LoggerFactory.getLogger(CustomErrorFilter.class);
@Override
public String filterType() {
return "post";
}
@Override
public int filterOrder() {
return -1; // 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
return RequestContext.getCurrentContext().containsKey("error.status_code");
}
@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
}
}
catch (Exception ex) {
LOG.error("Exception filtering in custom error filter", ex);
ReflectionUtils.rethrowRuntimeException(ex);
}
return null;
}
}
I had the same problem and was able to solve it in simpler way
Just put this into you Filter run()
method
if (<your condition>) {
ZuulException zuulException = new ZuulException("User message", statusCode, "Error Details message");
throw new ZuulRuntimeException(zuulException);
}
and SendErrorFilter
will deliver to the user the message with the desired statusCode
.
This Exception in an Exception pattern does not look exactly nice, but it works here.