programing

Larabel 5: 요청이 JSON을 원할 때 예외 처리

easyjava 2023. 3. 20. 23:39
반응형

Larabel 5: 요청이 JSON을 원할 때 예외 처리

Larabel 5에서 AJAX를 통해 파일을 업로드하고 있습니다.한 가지만 빼고 거의 모든 게 잘 되고 있어요.

너무 큰 파일을 업로드하려고 할 때(보다 큰 파일)upload_max_filesize그리고.post_max_sizeToken Mismatch Exception이 느려집니다.

단, 이 제한을 초과하면 입력이 비어 버리기 때문에 이것은 예상할 수 있는 것입니다.빈 입력, 즉 '아니오'_token이 때문에 CSRF 토큰을 검증하는 미들웨어가 소란을 피우고 있습니다.

그러나 나의 문제는 이 예외가 던져지고 있다는 것이 아니라 어떻게 표현되고 있는가 하는 것이다.이 예외가 Larabel에 의해 포착되면 일반적인 Whoops 페이지에 대한 HTML이 출력됩니다(디버깅모드이기 때문에 스택트레이스가 로드됩니다).

기본 동작을 유지하면서 JSON이 AJAX(또는 JSON이 요청되었을 때)를 통해 반환되도록 이 예외를 처리하는 가장 좋은 방법은 무엇입니까?


편집: 이는 예외가 발생하더라도 발생할 수 있습니다.404를 얻기 위해 존재하지 않는 페이지에 AJAX(Datype: JSON)를 통해 요청을 시도했지만 같은 일이 일어났다.HTML이 반환되고 JSON에 친숙한 것은 아무것도 없다.

@Wader의 답변과 @Tyler Crompton의 코멘트를 고려하여 직접 시도해 보겠습니다.

앱/예외/핸들러php

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception $e
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $e)
{
    // If the request wants JSON (AJAX doesn't always want JSON)
    if ($request->wantsJson()) {
        // Define the response
        $response = [
            'errors' => 'Sorry, something went wrong.'
        ];

        // If the app is in debug mode
        if (config('app.debug')) {
            // Add the exception class name, message and stack trace to response
            $response['exception'] = get_class($e); // Reflection might be better here
            $response['message'] = $e->getMessage();
            $response['trace'] = $e->getTrace();
        }

        // Default response of 400
        $status = 400;

        // If this exception is an instance of HttpException
        if ($this->isHttpException($e)) {
            // Grab the HTTP status code from the Exception
            $status = $e->getStatusCode();
        }

        // Return a JSON response with the response array and status code
        return response()->json($response, $status);
    }

    // Default to the parent class' implementation of handler
    return parent::render($request, $e);
}

응용 프로그램에서는app/Http/Middleware/VerifyCsrfToken.php이 파일에서 미들웨어 실행 방법을 처리할 수 있습니다.그래서 당신은 요청이 ajax인지 확인하고 당신이 원하는 방식으로 처리할 수 있습니다.

또는 예외 핸들러를 편집하여 json을 반환하는 것이 좋습니다.app/exceptions/Handler.php, 다음과 같은 것이 출발지가 될 것입니다.

public function render($request, Exception $e)
{
    if ($request->ajax() || $request->wantsJson())
    {
        $json = [
            'success' => false,
            'error' => [
                'code' => $e->getCode(),
                'message' => $e->getMessage(),
            ],
        ];

        return response()->json($json, 400);
    }

    return parent::render($request, $e);
}

@Jonathon의 핸들러 렌더링 기능을 기반으로 검증 제외 조건을 변경하기만 하면 됩니다.예외 인스턴스

// If the request wants JSON + exception is not ValidationException
if ($request->wantsJson() && ( ! $exception instanceof ValidationException))

Larabel 5는 적절한 경우 이미 JSON에서 검증 오류를 반환합니다.

App/Exceptions/Handler의 전체 메서드입니다.php:

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $exception
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $exception)
{
    // If the request wants JSON + exception is not ValidationException
    if ($request->wantsJson() && ( ! $exception instanceof ValidationException))
    {
        // Define the response
        $response = [
            'errors' => 'Sorry, something went wrong.'
        ];

        // If the app is in debug mode
        if (config('app.debug'))
        {
            // Add the exception class name, message and stack trace to response
            $response['exception'] = get_class($exception); // Reflection might be better here
            $response['message'] = $exception->getMessage();
            $response['trace'] = $exception->getTrace();
        }

        // Default response of 400
        $status = 400;

        // If this exception is an instance of HttpException
        if ($this->isHttpException($exception))
        {
            // Grab the HTTP status code from the Exception
            $status = $exception->getCode();
        }

        // Return a JSON response with the response array and status code
        return response()->json($response, $status);
    }
    return parent::render($request, $exception);
}

Laravel 5.3에서 동작하도록 여기서 발견된 몇 가지 구현을 변경했습니다.주요 차이점은 내 것이 올바른 HTTP 상태 텍스트를 반환한다는 것입니다.

app\의 render() 함수에서예외 \Handler.php는 이 스니펫을 맨 위에 추가합니다.

    if ($request->wantsJson()) {
        return $this->renderExceptionAsJson($request, $exception);
    }

renderExceptionAsJson 내용:

/**
 * Render an exception into a JSON response
 *
 * @param $request
 * @param Exception $exception
 * @return SymfonyResponse
 */
protected function renderExceptionAsJson($request, Exception $exception)
{
    // Currently converts AuthorizationException to 403 HttpException
    // and ModelNotFoundException to 404 NotFoundHttpException
    $exception = $this->prepareException($exception);
    // Default response
    $response = [
        'error' => 'Sorry, something went wrong.'
    ];

    // Add debug info if app is in debug mode
    if (config('app.debug')) {
        // Add the exception class name, message and stack trace to response
        $response['exception'] = get_class($exception); // Reflection might be better here
        $response['message'] = $exception->getMessage();
        $response['trace'] = $exception->getTrace();
    }

    $status = 400;
    // Build correct status codes and status texts
    switch ($exception) {
        case $exception instanceof ValidationException:
            return $this->convertValidationExceptionToResponse($exception, $request);
        case $exception instanceof AuthenticationException:
            $status = 401;
            $response['error'] = Response::$statusTexts[$status];
            break;
        case $this->isHttpException($exception):
            $status = $exception->getStatusCode();
            $response['error'] = Response::$statusTexts[$status];
            break;
        default:
            break;
    }

    return response()->json($response, $status);
}

Laravel 8.x에서는

app/Http/예외/핸들러.php

public function render($request, Throwable $exception)
{
    if ($request->wantsJson()) {
        return parent::prepareJsonResponse($request, $exception);
    }

    return parent::render($request, $exception);
}

JSON을 호출하십시오.parent::prepareJsonResponseparent::render.

이 JSON과 함께 APP_DEBUG=true완전한 오류 보고서와 스택트레이스가 표시됩니다.APP_DEBUG=false어플리케이션의 상세 내용을 실수로 공개하지 않도록 범용 메시지가 표시됩니다.

@Jonathon의 코드를 사용하여 Larabel/Lumen 5.3의 빠른 수정을 소개합니다.

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception $e
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $e)
{
    // If the request wants JSON (AJAX doesn't always want JSON)
    if ($request->wantsJson())
    {
        // Define the response
        $response = [
            'errors' => 'Sorry, something went wrong.'
        ];

        // If the app is in debug mode
        if (config('app.debug'))
        {
            // Add the exception class name, message and stack trace to response
            $response['exception'] = get_class($e); // Reflection might be better here
            $response['message'] = $e->getMessage();
            $response['trace'] = $e->getTrace();
        }

        // Default response of 400
        $status = 400;

        // If this exception is an instance of HttpException
        if ($e instanceof HttpException)
        {
            // Grab the HTTP status code from the Exception
            $status = $e->getStatusCode();
        }

        // Return a JSON response with the response array and status code
        return response()->json($response, $status);
    }

    // Default to the parent class' implementation of handler
    return parent::render($request, $e);
}

마이웨이:


    // App\Exceptions\Handler.php
    public function render($request, Throwable $e) {
        if($request->is('api/*')) {
            // Setting Accept header to 'application/json', the parent::render
            // automatically transform your request to json format.
            $request->headers->set('Accept', 'application/json');
        }
        return parent::render($request, $e);
    }

다음과 같이 err.response를 쉽게 포착할 수 있습니다.

axios.post().then().catch(function(err){


 console.log(err.response);  //is what you want

};

언급URL : https://stackoverflow.com/questions/28944097/laravel-5-handle-exceptions-when-request-wants-json

반응형