More than 3 years have passed since last update.

Spring Boot の Whitelabel Error Page と JSON レスポンス

Last updated at Posted at 2019-11-18

Spring Boot のデフォルトの状態では、404 Not Found 等が発生した際に Whitelabel Error Page というエラーページが表示される。

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Mon Nov 18 22:16:56 JST 2019
There was an unexpected error (type=Not Found, status=404).
No message available

curl で同等の動きを確認するには -H オプションでリクエストヘッダに accept: text/html を指定する。

$ curl -H "accept: text/html" http://localhost:8080/
<html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div id='created'>Mon Nov 18 22:18:01 JST 2019</div><div>There was an unexpected error (type=Not Found, status=404).</div><div>No message available</div></body></html>

-H オプションをつけない場合は JSON フォーマットのデータが返ってくる。

$ curl http://localhost:8080/
{"timestamp":"2019-11-18T13:19:03.320+0000","status":404,"error":"Not Found","message":"No message available","path":"/"}

Spring Boot のドキュメントには、マシンクライアントでは JSON レスポンスを生成し、ブラウザクライアントには HTML 形式で表示する whitelabel エラービューを生成すると書いてある。

Spring Boot Reference Documentation

For machine clients, it produces a JSON response with details of the error, the HTTP status, and the exception message. For browser clients, there is a “whitelabel” error view that renders the same data in HTML format (to customize it, add a View that resolves to error).

Spring Boot でエラーページを処理しているのは BasicErrorController クラス。

BasicErrorController クラスの errorHtml メソッドには、@RequestMapping アノテーションで produces = MediaType.TEXT_HTML_VALUE が指定されている。

そのためリクエストの Accept ヘッダに text/html が含まれる場合にこの errorHtml メソッドが呼び出される。
また Accept ヘッダに text/html が含まれないリクエストの場合は error メソッドが呼び出される。

errorHtml メソッドは HTML のレスポンスを返し、 error メソッドは JSON のレスポンスを返している。


spring-boot/BasicErrorController.java at v2.2.1.RELEASE · spring-projects/spring-boot · GitHub

@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
  HttpStatus status = getStatus(request);
  Map<String, Object> model = Collections
      .unmodifiableMap(getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
  ModelAndView modelAndView = resolveErrorView(request, response, status, model);
  return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);

public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
  HttpStatus status = getStatus(request);
  if (status == HttpStatus.NO_CONTENT) {
    return new ResponseEntity<>(status);
  Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
  return new ResponseEntity<>(body, status);

text/html のような Content Type を示すクラスである MediaType は Spring Boot ではなく Spring Framework が提供している。

spring-framework/MediaType.java at v5.2.1.RELEASE · spring-projects/spring-framework · GitHub

 * A String equivalent of {@link MediaType#TEXT_HTML}.
public static final String TEXT_HTML_VALUE = "text/html";


Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up