Open5

Laravel 8.x Validationエラーで常に200 OKが返る

無職の学び舎無職の学び舎

一応使ってるのは、Laravel 8.47.0

APIを実装していて、入力内容の検証にValidatorを使うと
エラー発生時、常にstatus code 200が返される。

この問題はLaravel 5.xでもあったようで、同じ問題に遭遇している人はいたらしいが
その時は、RequestにAccept:application/jsonを含めればいいということで解決していたらしい。

しかしやってみたけど、うまくいかなかった。

今回はRequestFormを使って検証してみたが、普通にRequestのvalidatorを使っても結果は同じであった。

LaravelのRequestFormクラスでは、検証失敗時に以下のメソッドが呼ばれて例外が投げられるらしい。

    /**
     * Handle a failed validation attempt.
     *
     * @param  \Illuminate\Contracts\Validation\Validator  $validator
     * @return void
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    protected function failedValidation(Validator $validator)
    {
        throw (new ValidationException($validator))
                    ->errorBag($this->errorBag)
                    ->redirectTo($this->getRedirectUrl());
    }

ValidationExceptionの中を見るとメンバに$status = 422というのがおり、そもそも422を返すおつもりであることはうかがえる。
しかしなぜか200が返る。

このメソッドをオーバーライドすることもできるので、自分で作ったRequestFormクラスにて
以下のようにオーバーライドしてみた。

  /**
   * オーバライドした。
   *
   * @param  \Illuminate\Contracts\Validation\Validator  $validator
   * @return void
   *
   * @throws \Illuminate\Validation\HttpResponseException
   */  
  protected function failedValidation(Validator $validator)
  {
    $error = (new ValidationException($validator))->errors();
    throw new HttpResponseException(response()->json($error, 422));
  }

オーバーライドはされて処理もちゃんと動いているようだが、これでも200 OKが返される。

もうindex.phpが追いかけていくしかないが、めんどくさいので
力が蓄えられるまではやらない。

無職の学び舎無職の学び舎

‘app/Exceptions/Handler.php'

    protected function invalidJson($request, ValidationException $exception)
    {
      return response()->json([
        'message' => $exception->getMessage(),
        'errors'  => $exception->errors(),
      ], 422);
    }

invalidJsonをオーバライドしても結果は同じで200OKが返却される。

無職の学び舎無職の学び舎

環境のおさらい

Laravel 8.47.0

Docker for Windows

  • web:Nginx
  • app:PHP-fpm
  • db:MySQL

コンテナは上記3つを組み合わせた環境。

無職の学び舎無職の学び舎

今のところトリガーはValidationExceptionが発生したときにおこるということ
例外を発生させずにresponse()->json([], 422)をすると422が返る。

このあたりを色んなケースで試してみるのがいいか🤔