Because of #1088, a zuul proxy now mangles with error messages returned from the backend in Brixton.SR1.
For example, if I have an backend service who returns a 404 with the body foo, this will end up in the SendErrorFilter because the error.status_code was set. It will finish it's course in the default error endpoint, /error in a default spring boot application, and return the default 404 page, if defined.
I'm a strong believer (and I've said it in other issues/PR) that proxies should not change what is received from the backend. The SendResponseFilter should only serve when there is an error during filtering, aka an error while trying to proxy the request to the backend (service not available, NPE in a ZuulFilter, etc.).
I would need more background on why #1088 was necessary since the PreDecorationFilter already forwards the request to the dispatcherServlet when no route is found.
/cc @marcingrzejszczak
Hmm yeah, I guess you're right.
To make the story short the rationale behind this change was to make TraceFilter from Sleuth be used to close spans as late as possible. Meaning that if we have exceptions thrown in the code we wanted all the ErrorControllers to have tracing info in the logs too. It worked fine for everything but Zuul since, like you've mentionedtheSendErrorFilter` wasn't called.
But I agree that it seems not to have been the best of choices. I guess we'll remove that solution and hack things around in Sleuth.
Thanks for the quick answer! A quick fix for anyone else affected by this bug, just add this class in the classpath scanning range of your application and it will fix the issue :
package com.coveo.cloud.proxyserver.filters;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
/*
* https://github.com/spring-cloud/spring-cloud-netflix/issues/1110
*/
@Component
public class Remove4xxErrorCodeSetZuulFilter extends ZuulFilter
{
private static final String ERROR_STATUS_CODE_KEY = "error.status_code";
@Override
public boolean shouldFilter()
{
Integer statusCode = (Integer) RequestContext.getCurrentContext().get(ERROR_STATUS_CODE_KEY);
return statusCode != null && statusCode >= 400 && statusCode < 500;
}
@Override
public Object run()
{
RequestContext.getCurrentContext().set(ERROR_STATUS_CODE_KEY, null);
return null;
}
@Override
public String filterType()
{
return "post";
}
@Override
public int filterOrder()
{
return Integer.MIN_VALUE;
}
}
@jebeaudet as a work around you can add a post filter that runs before SendErrorFilter that removes the error.status_code from the context if it is 4xx.
you read through my mind it seems :+1: