DEV Community

Viktor Le
Viktor Le

Posted on

How to detect a request is API or Web in laravel

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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) {
            //
        });
    }
}

Enter fullscreen mode Exit fullscreen mode

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) {
            //
        });
    }
Enter fullscreen mode Exit fullscreen mode

I hope this post could help some of you strategize the reponse format in such a situation

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay