Affects: Spring Framework 5.2.5.RELEASE
When throwing a derived exception like:
public class NotModifiedStatusException extends ResponseStatusException {
private static final long serialVersionUID = -4380761922076567306L;
private String etag;
public NotModifiedStatusException(String etag) {
super(HttpStatus.NOT_MODIFIED);
this.etag = etag;
}
@Override
public Map<String, String> getHeaders() {
return getResponseHeaders().toSingleValueMap();
}
@Override
public HttpHeaders getResponseHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setETag(etag);
return headers;
}
}
the headers are completely ignored:
17:56:01,681 [http-nio-127.0.0.1-8081-exec-5] DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver: Resolved [...NotModifiedStatusException: 304 NOT_MODIFIED]
17:56:01,681 [http-nio-127.0.0.1-8081-exec-5] TRACE o.s.web.servlet.DispatcherServlet: No view rendering, null ModelAndView returned.
17:56:01,681 [http-nio-127.0.0.1-8081-exec-5] DEBUG o.s.web.servlet.DispatcherServlet: Completed 304 NOT_MODIFIED, headers={}
It happily ignores the headers: https://github.com/spring-projects/spring-framework/blob/8d31dcaa297c3e9001a6e8470b400641ae1c49d0/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java#L128-L133
My naive solution seems to work:
@Component
public class HeaderAwareResponseStatusExceptionResolver extends ResponseStatusExceptionResolver {
@Override
public int getOrder() {
return super.getOrder() + 1;
}
@Override
protected ModelAndView resolveResponseStatusException(ResponseStatusException ex,
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
int statusCode = ex.getStatus().value();
String reason = ex.getReason();
HttpHeaders headers = ex.getResponseHeaders();
headers.forEach((name, values) -> values.forEach(value -> response.addHeader(name, value)));
if (!StringUtils.hasLength(reason)) {
response.sendError(statusCode);
} else {
response.sendError(statusCode, reason);
}
return new ModelAndView();
}
}
Comment From: rstoyanchev
Support for headers was added recently in #24261 but only on the WebFlux side it seems.
Comment From: michael-o
Correct, this is my observation. I assume this is simply an oversight.
Comment From: michael-o
The provided solution is in consistent with the Flux version:
https://github.com/spring-projects/spring-framework/blob/ea6d2ea1ce6d42c67d8ca5e34d24bbca625c9ced/spring-web/src/main/java/org/springframework/web/server/handler/ResponseStatusExceptionHandler.java#L94-L97
It does not contain a null check.
Comment From: rstoyanchev
Yes it is a little more defensive. Spring MVC has been around longer and is used more widely. Do you foresee an issue?
Comment From: michael-o
Not right now, but this deserves to be documented.
Comment From: rstoyanchev
I've updated it to match WebMvc.