Avoid 406 Not Acceptable for error pages
Prior to this commit, the `ErrorController` would override the original error response status if the error map cannot be written due to content negotiation with the HTTP client. In that case, the error handling infrastructure returns a `406 Not Acceptable` response. This commit improves the `ErrorController` so that `HttpMediaTypeNotAcceptableException` instances thrown by that controller are not returned as is but instead we write the error response with an empty body and the original HTTP error status. Fixes gh-19522
This commit is contained in:
@@ -32,6 +32,8 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@@ -102,6 +104,12 @@ public class BasicErrorController extends AbstractErrorController {
|
||||
return new ResponseEntity<>(body, status);
|
||||
}
|
||||
|
||||
@ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
|
||||
public ResponseEntity<String> mediaTypeNotAcceptable(HttpServletRequest request) {
|
||||
HttpStatus status = getStatus(request);
|
||||
return ResponseEntity.status(status).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the stacktrace attribute should be included.
|
||||
* @param request the source request
|
||||
|
||||
@@ -200,6 +200,17 @@ class BasicErrorControllerIntegrationTests {
|
||||
assertThat(resp).contains("We are out of storage");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIncompatibleMediaType() {
|
||||
load();
|
||||
RequestEntity<?> request = RequestEntity.get(URI.create(createUrl("/incompatibleType")))
|
||||
.accept(MediaType.TEXT_PLAIN).build();
|
||||
ResponseEntity<String> entity = new TestRestTemplate().exchange(request, String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
|
||||
assertThat(entity.getHeaders().getContentType()).isNull();
|
||||
assertThat(entity.getBody()).isNull();
|
||||
}
|
||||
|
||||
private void assertErrorAttributes(Map<?, ?> content, String status, String error, Class<?> exception,
|
||||
String message, String path) {
|
||||
assertThat(content.get("status")).as("Wrong status").isEqualTo(status);
|
||||
@@ -298,6 +309,11 @@ class BasicErrorControllerIntegrationTests {
|
||||
throw new InsufficientStorageException();
|
||||
}
|
||||
|
||||
@RequestMapping(path = "/incompatibleType", produces = "text/plain")
|
||||
String incompatibleType() {
|
||||
throw new ExpectedException();
|
||||
}
|
||||
|
||||
@ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "Expected!")
|
||||
@SuppressWarnings("serial")
|
||||
static class ExpectedException extends RuntimeException {
|
||||
|
||||
Reference in New Issue
Block a user