skip to Main Content

I have this strange issue. I’ve a web application in Vue 3 with Inertia, incorporating forms. When I open two browsers and log out in one, then trigger an Ajax request in the other, it reaches the middleware. This is as I would expect, but with the middleware I’ve written:

namespace AppHttpMiddleware;

use Closure;
use IlluminateHttpRequest;
use SymfonyComponentHttpFoundationResponse;

class ProtectAjaxCalls
{
    /**
     * Handle an incoming request.
     *
     * @param Closure(IlluminateHttpRequest): (SymfonyComponentHttpFoundationResponse) $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if ($request->ajax() && !auth()->user()) {
            return redirect()->route('login');
            // dd($request);
        }

        return $next($request);
    }
}

It redirects to the login page. Again, that’s what I would expect. What I don’t understand is that if the Ajax call is a patch request, the redirect also becomes a patch request, which fails, of course. What is happening here, and how can I properly redirect the invalid patch request to a valid get request to the login page?

One solution that I could use is to return a 403 and then execute:

window.location.href = "/login"

Is that the way to go?

2

Answers


  1. Chosen as BEST ANSWER

    I my case i had to do:

    namespace AppHttpMiddleware;
    
    use Closure;
    use IlluminateHttpRequest;
    use InertiaInertia;
    use SymfonyComponentHttpFoundationResponse;
    
    class ProtectAjaxCalls
    {
        /**
         * Handle an incoming request.
         *
         * @param Closure(IlluminateHttpRequest): (SymfonyComponentHttpFoundationResponse) $next
         */
        public function handle(Request $request, Closure $next): Response
        {
            if ($request->ajax() && !auth()->user()) {
                return Inertia::location('/login');
            }
    
            return $next($request);
        }
    }
    

    saves me a lot of code in my views


  2. Privet, Ivar! The issue you’re experiencing is due to the nature of HTTP redirects. When a server responds with a redirect status, the client is supposed to make the same type of request (GET, POST, PATCH, etc.) to the new URL. This is why your PATCH request is being redirected as a PATCH request, which is not what you want.

    To solve this, you can use a JavaScript-based solution to handle the redirect on the client side. Instead of returning a redirect response from your middleware, you can return a JSON response with the URL to redirect to. Then, in your JavaScript code, you can check for this response and perform the redirect using window.location.href.

    Here’s how you can modify your middleware:

    namespace AppHttpMiddleware;
    
    use Closure;
    use IlluminateHttpRequest;
    use SymfonyComponentHttpFoundationResponse;
    
    class ProtectAjaxCalls
    {
        /**
         * Handle an incoming request.
         *
         * @param Closure(IlluminateHttpRequest): (SymfonyComponentHttpFoundationResponse) $next
         */
        public function handle(Request $request, Closure $next): Response
        {
            if ($request->ajax() && !auth()->user()) {
                return response()->json(['redirect' => route('login')], 401);
            }
    
            return $next($request);
        }
    }
    

    In your JavaScript code, you can handle the redirect like this:

    axios.patch('/your-endpoint')
        .then(response => {
            // Handle successful response
        })
        .catch(error => {
            if (error.response.status === 401 && error.response.data.redirect) {
                window.location.href = error.response.data.redirect;
            }
        });
    

    This way, the redirect will always be a GET request, regardless of the original request type.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search