Generator-jhipster: REST Api Call returns 406 instead of 400 for invalid passwords

Created on 10 Mar 2016  路  7Comments  路  Source: jhipster/generator-jhipster

Overview of the issue

Calling api/account/change_password returns HTTP Status Code 406 in case of invalid password requests (instead of Bad Request 400).

JHipster Version(s)

2.27.0

Reproduce the error

Calling REST api with an invalid (e.g. too short) password

Suggest a Fix

Change Produces-Annotation ContentType to TEXT_PLAIN

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.

All 7 comments

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

Was this page helpful?
0 / 5 - 0 ratings