diff --git a/.env.docker.example b/.env.docker.example index 6f1c7de..7774ec3 100644 --- a/.env.docker.example +++ b/.env.docker.example @@ -21,6 +21,9 @@ LOG_STACK=daily LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +# API Rate Limiting Configuration +DEFAULT_API_RATE_LIMIT=60 + # Docker MySQL Configuration DB_CONNECTION=mysql DB_HOST=mysql diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 00e7987..f8cc96a 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -5,9 +5,12 @@ namespace App\Providers; use Carbon\CarbonImmutable; +use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Database\Eloquent\Model; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Date; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider @@ -28,5 +31,16 @@ public function boot(): void Date::use(CarbonImmutable::class); Model::shouldBeStrict(! $this->app->isProduction()); DB::prohibitDestructiveCommands($this->app->isProduction()); + + // Disable rate limiting during testing + if ($this->app->environment('testing')) { + RateLimiter::for('api', fn () => Limit::none()); + } else { + // Rate Limiting for API routes + RateLimiter::for('api', function (Request $request) { + return Limit::perMinute((int) config('rate-limiting.api.default_rate_limit')) + ->by($request->user()?->id ?: $request->ip()); + }); + } } } diff --git a/bootstrap/app.php b/bootstrap/app.php index e2fe230..324c832 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -16,6 +16,7 @@ ->withMiddleware(function (Middleware $middleware): void { $middleware->alias([ 'ability' => \App\Http\Middleware\CheckTokenAbility::class, + 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, ]); }) ->withExceptions(function (Exceptions $exceptions): void { diff --git a/config/rate-limiting.php b/config/rate-limiting.php new file mode 100644 index 0000000..3b7a880 --- /dev/null +++ b/config/rate-limiting.php @@ -0,0 +1,7 @@ + [ + 'default_rate_limit' => env('DEFAULT_API_RATE_LIMIT', 60), + ], +]; diff --git a/routes/api_v1.php b/routes/api_v1.php index 65d432a..5aae028 100644 --- a/routes/api_v1.php +++ b/routes/api_v1.php @@ -3,7 +3,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; -Route::prefix('v1')->group(function () { +Route::prefix('v1')->middleware(['throttle:api'])->group(function () { Route::get('/', function (Request $request) { return 'Laravel Blog API V1 Root is working'; })->name('api.v1.status');