Laravel API uses Redis + Lua

This is a continuation of Laravel API uses Redis+Lua for request throttling

Let’s extend the Redis + Lua rate limiter so different API endpoints can have different limits and windows.


1. Update the Service to Support Endpoint Keys

In app/Services/RateLimiter.php:

php

<?php

namespace App\Services;

use Illuminate\Support\Facades\Redis;

class RateLimiter
{
    public static function attempt(string $userId, string $endpoint, int $limit, int $window): bool
    {
        $script = file_get_contents(app_path('Services/Redis/rate_limit.lua'));

        // Key includes both user and endpoint
        $key = "rate_limit:{$endpoint}:{$userId}";

        $result = Redis::eval($script, 1, $key, $limit, $window);

        return $result === 1;
    }
}

2. Example Usage in a Controller

In app/Http/Controllers/ApiController.php:

php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Services\RateLimiter;

class ApiController extends Controller
{
    public function login(Request $request)
    {
        $userId = $request->ip(); // for login, limit by IP

        // Stricter: 3 attempts per 60 seconds
        if (!RateLimiter::attempt($userId, 'login', 3, 60)) {
            return response()->json(['error' => 'Too Many Login Attempts'], 429);
        }

        return response()->json(['message' => 'Login successful']);
    }

    public function profile(Request $request)
    {
        $userId = $request->user()->id ?? $request->ip();

        // Looser: 20 requests per 60 seconds
        if (!RateLimiter::attempt($userId, 'profile', 20, 60)) {
            return response()->json(['error' => 'Too Many Profile Requests'], 429);
        }

        return response()->json(['profile' => ['name' => 'Phillip', 'age' => 30]]);
    }
}

3. Redis Keys That Will Be Created

  • rate_limit:login:192.168.1.5 → 3 per 60s
  • rate_limit:profile:42 → 20 per 60s

Each endpoint has its own counter per user/IP, so limits are independent.


Benefits:

  1. Fine-grained control (e.g., stricter on login, looser on browsing).
  2. Easy to add more endpoints with different rules.
  3. Scales horizontally (works across multiple app servers).

You can also make this configurable in a single place (like a config/rate_limits.php file), so you don’t hardcode limits in every controller. See Laravel: creating config file for rate limits.

By ice

Leave a Reply

Your email address will not be published. Required fields are marked *