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
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);
}
Quick note on this... In Laravel 5.5 the exception is named "$exception" and not "$e" in the method.
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);
}
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);
}
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);
}
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);
}