How to detect a request is API or Web in laravel
Viktor Le
Posted on August 26, 2024
I am working on a Project, of which the structure is based on Laravel and, my situation is to return a Validation Error JSON Format or Auto-Carried in Flashed Session (stored in $errors variable) given by a Request.
To strategize the JSON response format, I actually work with Handler Exception. So, I implement a custom ApiValidationErrorException class for Json Format, which looks like as bellow:
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\Response;
class ApiValidationErrorException extends ValidationException
{
public function render($request): JsonResponse
{
return new JsonResponse([
// This is the array that you will return in case of an error.
// You can put whatever you want inside.
'message' => 'There were some errors',
'status' => false,
'additionalThings' => 'Some additional things',
'errors' => $this->validator->errors()->getMessages(),
], Response::HTTP_UNPROCESSABLE_ENTITY);
}
}
then, call this custom class in Handler->register function, it looks like
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Validation\ValidationException;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* Register the exception handling callbacks for the application.
*/
public function register(): void
{
$this->renderable(function (ValidationException $exception, $request) {
throw ApiValidationErrorException::withMessages(
$exception->validator->getMessageBag()->getMessages()
);
});
$this->reportable(function (Throwable $e) {
//
});
}
}
However, this register throws a problem for returning errors on web request. Instead of displaying messages in HTML which is generated from blade templates, it returns a JSON response because the renderable method always throws ApiValidationErrorException format.
So, this definitely needs a if else statement
here to control the response properly.
So, the conditional statement detect the request whether it is RESTful Request or Form Request. Alright, Laravel provides a method on request Object name wantsJson()
, which checks the client request sends Accept=application/json
in Header
. So to use it, we have to set Accept=application/json
in Header
otherwise, this method returns false always. Then, I ask myself, is there any options to check API request? . Right, I search and search ... it comes up with a method, $request->is('api/*'). Utimately, the register()
method looks like
public function register(): void
{
$this->renderable(function (ValidationException $exception, $request) {
if ($request->wantsJson() || $request->is('api/*')) {
throw ApiValidationErrorException::withMessages(
$exception->validator->getMessageBag()->getMessages()
);
}
return null;
});
$this->reportable(function (Throwable $e) {
//
});
}
I hope this post could help some of you strategize the reponse format in such a situation
Posted on August 26, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.