Sarp Kaya
Sarp Kaya

Reputation: 3784

Spring boot returning 200 status code for custom error pages

I want to override the whitelabel error page. So as an example I have done this simple class:

@RestController
public class MyCustomErrorController implements ErrorController {

    private static final String PATH = "/error";

    @RequestMapping(value = PATH)
    public String error() {
        return "This is the error page";
    }

    @Override
    public String getErrorPath() {
        return PATH;
    }
}

I have taken my example from here: https://gist.github.com/jonikarppinen/662c38fb57a23de61c8b

According to that gist, it actually has a comment like this:

// Appropriate HTTP response code (e.g. 404 or 500) is automatically set by Spring. 
// Here we just define response body.

However that's not what I'm seeing. For instance if I hit to a URL that I know that it should respond me a 500 status code (intentional NullPointerException), then that's what I should see, but when I hit to that URL I get a 200 response back with my error message ("This is the error page")

If I don't use this custom controller, then it shows me a 500 error page with the stacktrace on it, which is the default behavior. I have seen an old issue opened in 2014 here: https://github.com/spring-projects/spring-boot/issues/684 that someone mentioning the same problem, however their solution is to show explicitly 500 responses, which does not really pass through the HTTP response code.

Just for the record, I actually put a breakpoint to org.apache.catalina.connector.Response.sendError() method. When this custom error controller does not exist, I can clearly see that sendError() method is being called with a status 500. However if I were to add HttpServletResponse argument to my error() method I do not see that the instance has 500 status code set.

Upvotes: 0

Views: 9835

Answers (2)

alexbt
alexbt

Reputation: 17045

Explanation

In the website example you provided, the HttpStatus is retrieved from the injected HttpServletResponse. So the following:

Appropriate HTTP response code (e.g. 404 or 500) is automatically set by Spring.

means

Spring sets it on the HttpServletResponse that he gets injected into his method as argument.

  • He then has to retrieve the status and set it on his model ErrorJson.

Solution

To follow your example, you could change your method to this:

@RequestMapping(value = ERROR_MAPPING)
public ResponseEntity<String> error(HttpServletResponse response) {
    return new ResponseEntity<String>("This is the error page",
        HttpStatus.valueOf(response.getStatus()));
}
  • I used ResponseEntity<String> instead of defining a custom object (a.k.a. ErrorJson).

  • As I believe you know, alternatively to using the HttpServletResponse's status, you could just set yours with HttpStatus.

Upvotes: 1

Riddhi Gohil
Riddhi Gohil

Reputation: 1818

Here you are simply returning a message from one method, which is not an error as per SpringBoot.

Following method will help you to return http status code as you want :

 @RequestMapping(value = PATH)
    public ResponseEntity<Map<String, Object>> error() {
        Map<String, Object> map = new HashMap<>();

    String statusMessage = "This is the error page";
        String statusCode = HttpStatus.BAD_REQUEST.value();

        map.put(STATUS_CODE, statusCode);
        map.put(STATUS_MESSAGE, statusMessage);

        return ResponseEntity.badRequest().body(map);
    }

Upvotes: 0

Related Questions