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)));
response.setStatus(status.value());
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
}
@RequestMapping
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";
参考: