bedrockstreaming/rate-limit-bundle
Installation:
composer require bedrockstreaming/rate-limit-bundle
Add to config/bundles.php:
Bedrock\Bundle\RateLimitBundle\RateLimitBundle::class => ['all' => true],
Configuration:
Create config/packages/bedrock_rate_limit.yaml with defaults:
bedrock_rate_limit:
limit: 25
period: 600
limit_by_route: false
display_headers: false
First Use Case:
Apply the #[RateLimit] attribute to a controller method:
use Bedrock\Bundle\RateLimitBundle\Attribute\RateLimit;
#[RateLimit]
public function sensitiveAction(): Response
{
return new Response('Protected content');
}
Test by hitting the endpoint repeatedly to observe rate-limiting behavior.
Global Rate Limiting:
#[RateLimit] to controller methods for uniform protection.Route-Specific Limits:
limit_by_route: true in config to isolate limits per route.GraphQL Integration (if using #[GraphQLRateLimit]):
symfony/webpack-encore-bundle (suggested dependency).Dynamic Limits:
#[RateLimit(limit: 10, period: 300)]
Middleware Integration:
Combine with Symfony’s LimitRequestMiddleware for hybrid approaches:
# config/packages/framework.yaml
framework:
http_client:
middleware:
- Bedrock\Bundle\RateLimitBundle\Middleware\RateLimitMiddleware
Event-Based Triggers:
Listen for rate_limit.exceeded events to log or notify:
use Bedrock\Bundle\RateLimitBundle\Event\RateLimitExceededEvent;
public function onRateLimitExceeded(RateLimitExceededEvent $event): void
{
// Custom logic (e.g., send email, log IP)
}
Testing:
Use RateLimitTestTrait for unit tests:
use Bedrock\Bundle\RateLimitBundle\Test\RateLimitTestTrait;
class MyTest extends TestCase
{
use RateLimitTestTrait;
public function testRateLimit()
{
$this->assertRateLimitExceeded(...);
}
}
Shared Limits by Default:
limit_by_route: true, all #[RateLimit] routes share the same pool.limit_by_route: true or use unique attributes per route.GraphQL Dependency:
#[GraphQLRateLimit] requires symfony/webpack-encore-bundle (not auto-installed).composer.json or check suggest in composer require.Header Overhead:
display_headers: true adds 3 headers to every response, increasing payload size.Caching Conflicts:
php bin/console cache:clear
Attribute Scope:
Headers:
Enable display_headers: true to inspect:
x-rate-limit: Max allowed requests.x-rate-limit-hits: Current request count.x-rate-limit-until: Reset timestamp (Unix).Logs:
Check monolog for rate_limit.exceeded events if custom logic fails.
Storage:
Limits are stored in Symfony’s cache (default: app/cache). Verify storage path in config/packages/framework.yaml.
Custom Storage:
Override the default RateLimitStorage service to use Redis or DB:
# config/services.yaml
Bedrock\Bundle\RateLimitBundle\Storage\RateLimitStorageInterface: '@custom.redis_storage'
Dynamic Attributes: Create a compiler pass to inject dynamic limits from request data (e.g., user roles):
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
class DynamicRateLimitPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->findDefinition('bedrock_rate_limit.listener');
$definition->addMethodCall('setDynamicResolver', [new Reference('my.dynamic_resolver')]);
}
}
IP vs. User Limits: Extend the storage to track limits per user (via token) or IP:
class UserAwareRateLimitStorage implements RateLimitStorageInterface
{
public function getKey(Request $request): string
{
return $request->get('user_id') ?: $request->getClientIp();
}
// ...
}
Rate Limit Events:
Subscribe to rate_limit.hit and rate_limit.reset for analytics:
use Bedrock\Bundle\RateLimitBundle\Event\RateLimitEvent;
public function onRateLimitHit(RateLimitEvent $event): void
{
// Track usage patterns
}
How can I help you explore Laravel packages today?