Hello I want to modify some of my API's response Headers after I have completed processing (executed logic) and have concluded with an HTTP status code.
For example if the response is 404, then include specific for example Cache-Control
Headers example dont cache, or something like that.
I have already 2 OncePerRequestFilter
registered, which work fine - but obviously I can not do logic - once the processing is complete. The CacheControlFilter
already has logic that adds by default some Cache-Control
headers - e.g cache for 15 sec etc. It seems though that this happens (the addition of headers on the response) on a very early stage of the dispatch and when it reaches to the phase of executing the actual Controller/Endpoint
and there is an exception or Error that obviously is going to be handled by an advice etc, I can not mutate
these already existing headers- that were already added by the filter.
@Bean
public FilterRegistrationBean filterOne() {
Filter filter = new FilterOne();
return createFilter(filter, "FilterOne",List.of("/*"));
}
@Bean
public FilterRegistrationBean cacheControlFilter() {
Filter filter = new CacheControlFilter();
return createFilter(filter, "CacheControlFilter", List.of("/*"));
}
private FilterRegistrationBean createFilter(Filter aFilter, String filterName,
List<String> urlPatterns) {
FilterRegistrationBean filterRegBean = new FilterRegistrationBean(aFilter);
filterRegBean.addUrlPatterns(urlPatterns.toArray(new String[0]));
filterRegBean.setName(filterName);
filterRegBean.setEnabled(true);
filterRegBean.setAsyncSupported(true);
return filterRegBean;
}
I have already tried, to add an HttpServletResponseWrapper
as indicated on these post here and here on the CacheControlFilter
but it does not seem to work. I have also seen a similar S.O thread here.
HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper(response) {
@Override
public void setStatus(int sc) {
super.setStatus(sc);
handleStatus(sc);
}
@Override
@SuppressWarnings("deprecation")
public void setStatus(int sc, String sm) {
super.setStatus(sc, sm);
handleStatus(sc);
}
@Override
public void sendError(int sc, String msg) throws IOException {
super.sendError(sc, msg);
handleStatus(sc);
}
@Override
public void sendError(int sc) throws IOException {
super.sendError(sc);
handleStatus(sc);
}
private void handleStatus(int code) {
if(code == 404)
addHeader("Cache-Control, "xxx");
}
};
But the code is not executed at all! So I want to manipulate the Cache-Control headers on the second filter only after though the processing is complete and I am ready to return a response.
I am not sure if the fact that I also have, doing some clean up and setting responses upon errors - mixes things up!
@ControllerAdvice
@Slf4j
public class GlobalErrorHandler
Update: As a note, when my Controller is throwing an Exception or Error, the above GlobalErrorHandler
is invoked and there I execute a special handling, returning an error response
. What I see though is that magically
the response has already the default
headers populated by the Filter (CacheControlFilter). So it ends up being a bit weird, I add extra logic,to change the control header and I end up with a response that has the same header 2 times (1 with the value set by the CacheControlFilter
and then any special value I am trying to override on the ControllerAdvice
Any tips or help appreciated thanks! I am using Spring Boot 2.1.2
with Undertow
as my underlying servlet container.