Calling api/account/change_password returns HTTP Status Code 406 in case of invalid password requests (instead of Bad Request 400).
2.27.0
Calling REST api with an invalid (e.g. too short) password
Change Produces-Annotation ContentType to TEXT_PLAIN
406 means the request is "Not Acceptable", which is true when you try to change your password with a too short one. So for me it's not a bug, the request is correct (so we shouldn't return 400 Bad Requsest), but not acceptable.
Well, if we look at the code we see that we try to send a code HttpStatus.BAD_REQUEST with a text/plain content ("Incorrect password"). But as the produces is APPLICATION_JSON_VALUE, SB will send a 406 instead.
Not acceptable status code is often bound to Accept/Content-Type Header use cases, e.g. if you set Accept-Header as client to text/plain and backend can only produce application/json Content-Type.
btw it's the same for api/register. In case of validation errors, the ExceptionTranslator tries to return an ErrorDTO instance, but register method only defines text/plain as possible content-type. I would say it's more a Spring MVC missing feature/bug, but currently you have to define both content-types (because complex type like ErrorDto can not be converted to text/plain automatically) and to add explicitly Content-Type header for text/plain responses in such a case.
@gbrehmer Can you see if provide an array of produces works ?
for api/account/change_password
produces=MediaType.TEXT_PLAIN_VALUE
is enough.
There are more changes for api/register required:
@RequestMapping(value = "/register",
method = RequestMethod.POST,
produces={MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE})
@Timed
public ResponseEntity<?> registerAccount(@Valid @RequestBody UserDTO userDTO, HttpServletRequest request) {
HttpHeaders textPlainHeaders = new HttpHeaders();
textPlainHeaders.setContentType(MediaType.TEXT_PLAIN);
return userRepository.findOneByLogin(userDTO.getLogin())
.map(user -> new ResponseEntity<>("login already in use", textPlainHeaders, HttpStatus.BAD_REQUEST))
.orElseGet(() -> userRepository.findOneByEmail(userDTO.getEmail())
.map(user -> new ResponseEntity<>("e-mail address already in use", textPlainHeaders, HttpStatus.BAD_REQUEST))
.orElseGet(() -> {
This works, I debugged the Spring MVC code a bit and this seems the shortest solution. If special header for text-plain content is not provided, Spring selects the most restrictive content-type from accept-header (if text/plain & application/json are provided, application/json is more restrictive). This selection is done before output message converter is selected.
closed via #3158
Most helpful comment
Well, if we look at the code we see that we try to send a code HttpStatus.BAD_REQUEST with a text/plain content ("Incorrect password"). But as the produces is APPLICATION_JSON_VALUE, SB will send a 406 instead.