0

この単純な Spring Boot アプリの例を作成して、Spring Boot がデフォルトでエラーを処理する方法に関する問題を紹介しました。

package com.pany.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

}

これは Spring Security 構成です。

package com.pany.app;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/**").anonymous();
    }

}

これは REST コントローラーです。

package com.pany.app;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.HttpClientErrorException;

@RestController
public class MyController {

    @GetMapping(path = "/", produces = { "application/json" })
    public void home() {
        throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "This is my custom 400 Bad Request message");
    }

}

ではSpring Boot 2.1.8.RELEASE、URL を呼び出すと、http://localhost:8080/500 コードの HTTP 応答と次の JSON 応答が返されます。

{
  "timestamp": "2020-09-14T07:24:22.061+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "400 This is my custom 400 Bad Request message",
  "path": "/"
}

ただし、HTTP ステータス コードは期待どおりではなく (400 ではなく 500)、JSON のさまざまなフィールド (「ステータス」、「エラー」、「メッセージ」の前に予期しない「コード」がある) もあります。

これも...でテストしましたがSpring Boot 2.3.3.RELEASE、以前のように機能しなくなりました!!

{
  "timestamp": "2020-09-14T07:34:23.154+00:00",
  "status": 500,
  "error": "Internal Server Error",
  "message": "",
  "path": "/"
}

ErrorControllerこれらはすべて、 、AbstractErrorControllerおよびなどのクラス/インターフェースを介して処理されますBasicErrorController(すべて で設定されますErrorMvcAutoConfiguration)。どうやら、元のリクエスト/および/またはレスポンスが別のものにラップされたURLへのリダイレクトがある/errorようです。たとえば、リクエストを次のようにデバッグできます。

結果として得られる JSON はDefaultErrorAttributes、キーの下のリクエストから HTTP ステータス コードを抽出するという Bean を介して生成されることがわかりました"javax.servlet.error.status_code"

そして、私はそこで読みました: https://github.com/spring-projects/spring-boot/issues/4694#issuecomment-163597864 (2015 年 12 月):

問題は実際には BasicErrorController にあり、HTML 応答に固有のものです。BasicErrorController.error は、ErrorPageFilter によって設定される javax.servlet.error.status_code 属性を使用して応答ステータスを設定しますが、BasicErrorController.errorHtml はそうしません。これにより、text/html エラー応答のステータスが 200 OK になります。

実際、私の場合、ErrorPageFilterが呼び出されることはありません。

また、Spring Boot プロジェクトでこの他の問題が見つかりました: https://github.com/spring-projects/spring-boot/issues/20412これは私の問題にかなり関連していますが、まだ解決策は提供されていません。

コントローラーの設計方法に戻ります (これは非常に単純化された例であることを思い出してください): コード 400 を使用して HTTP 応答を取得し、応答としてこの JSON を取得するために、Spring Boot を「カスタマイズ」する方法は次のとおりです。

{
  "timestamp": "2020-09-14T07:24:22.061+0000",
  "status": 400,
  "error": "Bad Request",
  "message": "This is my custom 400 Bad Request message",
  "path": "/"
}

ありがとう。

4

2 に答える 2