가희의자기개발블로그

<Laravel> ValidationException -json Type으로 return 하기 본문

백엔드/Laravel

<Laravel> ValidationException -json Type으로 return 하기

가희gahui 2021. 5. 1. 12:20
반응형

라라벨 RestApi 템플릿 프로젝트를 구현 중에, validation 규칙이 맞지 않으면 error메시지를 출력해 보고 싶었다. 그런데 자꾸 이전 페이지로 redirect되는 문제가 발생했고 공식문서를 찾아보니 아래와 같이 나와있었다.

 

이제 새로운 블로그 포스트에 대해 유효성을 검사하는 로직을 store 메소드에 채워넣을 준비가 되었습니다. 이를 위해서 Illuminate\Http\Request 객체에 제공되는 validate 메소드를 사용할 것입니다. 유효성 검사 규칙들을 통과하게되면 코드는 계속해서 정상적으로 실행됩니다. 하지만 유효성 검사를 통과하지 못할 경우, 예외-exception가 던져지고 적절한 오류 응답이 사용자에게 자동으로 보내질 것입니다. 전통적인 HTTP 요청의 경우, 리다이렉트 응답이 생성될 것이며 AJAX 요청에는 JSON 응답이 보내질 것입니다.

AJAX 요청과 유효성 검사

이 예제에서는, 애플리케이션에 전통적인 form을 이용하여 데이터를 보냈습니다. 하지만 많은 애플리케이션이 AJAX 요청을 사용합니다. AJAX reqeust 중에서 validate 메소드를 사용한다면 라라벨은 리다이렉트 응답을 생성하지 않을 것입니다. 대신 라라벨은 유효성 검사의 모든 실패 에러들을 포함하는 JSON 응답을 생성할 것입니다. 이 JSON 응답은 422 HTTP 상태 코드와 함께 보내질 것입니다.

 

실제로 validationException을 처리하는 코드 부분을 확인해 보면서 이해해보자. 이 클래스는 app/Exceptions/Handler.php클래스를 상속하는 ExceptionHandler코드의 일부분이다. 

/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php

/**
     * Create a response object from the given validation exception.
     *
     * @param  \Illuminate\Validation\ValidationException  $e
     * @param  \Illuminate\Http\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function convertValidationExceptionToResponse(ValidationException $e, $request)
    {
        if ($e->response) {
            return $e->response;
        }
        return $request->expectsJson()
            ? $this->invalidJson($request, $e)
            : $this->invalid($request, $e);
    }

    /**
     * Convert a validation exception into a response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Validation\ValidationException  $exception
     * @return \Illuminate\Http\Response
     */
    protected function invalid($request, ValidationException $exception)
    {
        return redirect($exception->redirectTo ?? url()->previous())
            ->withInput(Arr::except($request->input(), $this->dontFlash))
            ->withErrors($exception->errors(), $request->input('_error_bag', $exception->errorBag));
    }

    /**
     * Convert a validation exception into a JSON response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Validation\ValidationException  $exception
     * @return \Illuminate\Http\JsonResponse
     */
    protected function invalidJson($request, ValidationException $exception)
    {
        return response()->json([
            'message' => $exception->getMessage(),
            'errors' => $exception->errors(),
        ], $exception->status);
    }

 

convertValidationExceptionToResponse 메소드를 확인해보면 $request->expectsJson() 이 False일 경우 invalid()함수를 호출해 실제로 이전페이지로 redirect시키고 만약 True일경우, invalidJson()을 호출해서  message와 errors를 json타입으로 return해준다. 

 

그렇다면 저 expectsJson()을 true가 나오도록 해줘야한다.

어떻게 해줘야 할까? 

 

Request에 Content-Type과 Accept에 json 타입이라고 명시해주면된다. 

middleware에서 요청이오는 Request의 Header에 json 타입을 명시하게 해줘서 라우터로 흘러가게 만들면된다.

 

1. middleware를 생성해준다.

php artisan make:middleware ForceResponseAsJson

2. ForceResponseAsJson 파일에 아래코드를 넣어준다.

	$request->headers->set('Accept', 'application/json');
        $request->headers->set('Content-Type', 'application/json');

 

3. app/http/Kernel.php 파일에 middleware를 등록시켜준다.

/**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Fruitcake\Cors\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\ForceResoponseAsJson::class,
    ];

 

postman으로 확인해봤을때 아주 잘나온다!

 

 

반응형

'백엔드 > Laravel' 카테고리의 다른 글

Route : routes파일 구조  (0) 2020.10.12
Laravel 시작  (3) 2020.10.10
Comments