Laravel 5: Handle exceptions when request wants JSON

前端 未结 8 1607
野的像风
野的像风 2021-01-30 05:30

I\'m doing file uploads via AJAX on Laravel 5. I\'ve got pretty much everything working except one thing.

When I try to upload a file that is too big (Bigger than

相关标签:
8条回答
  • 2021-01-30 05:44

    In your application you should have app/Http/Middleware/VerifyCsrfToken.php. In that file you can handle how the middleware runs. So you could check if the request is ajax and handle that how you like.

    Alternativly, and probably a better solution, would be to edit the exception handler to return json. See app/exceptions/Handler.php, something like the below would be a starting place

    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);
    }
    
    0 讨论(0)
  • 2021-01-30 05:46

    Quick note on this... In Laravel 5.5 the exception is named "$exception" and not "$e" in the method.

    0 讨论(0)
  • 2021-01-30 05:50

    Building on @Jonathon's handler render function, I would just modify the conditions to exclude ValidationException instances.

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

    Laravel 5 returns validation errors in JSON already if appropriate.

    The full method in 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);
    }
    
    0 讨论(0)
  • 2021-01-30 05:57

    I have altered several implementations found here to work on Laravel 5.3. The main difference is that mine will return the correct HTTP status texts

    In your render() function in app\Exceptions\Handler.php add this snippet to the top:

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

    Contents of 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);
    }
    
    0 讨论(0)
  • 2021-01-30 05:58

    My way:

    
        // 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);
        }
    
    0 讨论(0)
  • 2021-01-30 05:59

    Using @Jonathon's code, here's a quick fix for Laravel/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);
    }
    
    0 讨论(0)
提交回复
热议问题