Search code examples
laravellaravel-vapor

Laravel API throttle issue when deployed via Vapor


I have deployed a Laravel application on Vapor with frontend on Vue (basically a SPA with authentication via Laravel Sanctum). Details below:

Laravel Version: 7.11.0 PHP Version: 7.4 Database Driver & Version: MySQL 5.8

The Laravel default API throttling is behaving very strangely as in it throws "Too Many Requests" error when not logged in.

I added the issue on Github here which Taylor closed stating that throttling works on the basis of IP for not logged in users. Which is good until the fact that when I was receiving that error that was none in my network using the site so no way it can have same IP and hence shouldn't throw the "Too Many Requests" error.

So I dived in to the code and found:

protected function resolveRequestSignature($request)
{
    if ($user = $request->user()) {
        return sha1($user->getAuthIdentifier());
    }
    if ($route = $request->route()) {
        return sha1($route->getDomain().'|'.$request->ip());
    }
    throw new RuntimeException('Unable to generate the request signature. Route unavailable.');
}

the above code being used to resolve the signature on the basis of domain and IP.

So to debug I put logs for domain and IP which gives the following on my local machine:

enter image description here

While on an actual EC2 instance it showed this:

enter image description here

Good so far, but when I logged it on Vapor it produced the following:

enter image description here

Which clearly shows that that both: domain and IP are null and hence the signature might be same for all the non logged in users.

Is it something anyone else faced here? If yes, what's the way out? Should I implement my own throttle middleware? Then again the issue will be that the IP when deployed via Vapor is null.

I posted this as issue on Github but it got closed and no reply on my further comments.


Solution

  • To anyone who find it after facing the issue: Don't use Laravel's default middleware for throttling when you using Vapor.

    We figured it the hard way after our site was down for 5 minutes (a heavy traffic project).

    The issue?

    Laravel uses a wrapper on Symphony's to get the user's IP. But it seems that because of Vapor's design it was overriding that and hence outputs only the 127.0.0.1 as an IP for all users which in turns makes the signature used by the default throttle same for all the non logged-in users.

    The solution

    Use the x-vapor-source-ip header to identify the User's IP mentioned in this answer.

    It's not mentioned in Vapor's docs so mailed Vapor's team to fix it.