jean-beru/fos-http-cache-cloudfront
CloudFront proxy implementation for FOSHttpCache. Create a CloudFrontClient, configure your distribution ID, then purge/invalidate specific URLs or patterns (e.g., /assets/*) and flush requests. Supports caller reference generators to avoid duplicate invalidations.
composer require jean-beru/fos-http-cache-cloudfront async-aws/cloudfront
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) or Laravel’s AWS config (config/aws.php).use Aws\CloudFront\CloudFrontClient;
use JeanBeru\HttpCacheCloudFront\Proxy\CloudFront;
$client = new CloudFrontClient([
'region' => env('AWS_REGION'),
'version' => 'latest',
]);
$proxy = new CloudFront(
client: $client,
options: [
'distribution_id' => env('CLOUDFRONT_DISTRIBUTION_ID'),
]
);
$proxy->purge('/home')->flush();
UniqIdCallerReferenceGenerator) to customize deduplication logic.tests/ for edge cases (e.g., invalidation failures, rate limiting).$proxy->purge('/path/to/resource')->flush();
$proxy->purge('/assets/*')->purge('/images/*')->flush();
$proxy->purge(route('product.show', $id))->flush();
Pre-load critical paths during deployment:
$proxy->warmup('/home')->warmup('/products')->flush();
Trigger purges on model updates:
// app/Providers/EventServiceProvider.php
public function boot()
{
ProductUpdated::listen(function ($product) {
app('cloudfront.proxy')->purge(route('product.show', $product))->flush();
});
}
Combine with Laravel’s cache drivers:
// Cache in Redis, invalidate in CloudFront
Cache::put('key', $data, now()->addMinutes(5));
app('cloudfront.proxy')->purge('/cached-data')->flush();
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton('cloudfront.proxy', function ($app) {
$client = new CloudFrontClient($app['config']['aws.cloudfront']);
return new CloudFront($client, [
'distribution_id' => $app['config']['services.cloudfront.distribution_id'],
]);
});
}
Create a CloudFront facade for cleaner syntax:
// app/Facades/CloudFront.php
public static function purge(string $path): self
{
return static::getFacadeRoot()->purge($path);
}
Add an Artisan command for manual purges:
// app/Console/Commands/PurgeCloudFront.php
public function handle()
{
$proxy = app('cloudfront.proxy');
$proxy->purge($this->argument('path'))->flush();
$this->info('Purged: '.$this->argument('path'));
}
AWS SDK Conflicts:
async-aws/cloudfront with aws/aws-sdk-php (v2) may cause autoloading errors.composer.json:
"require": {
"async-aws/cloudfront": "^3.0"
},
"conflict": {
"aws/aws-sdk-php": "*"
}
Duplicate Invalidation Errors:
FOS\HttpCache\Exception\ProxyResponseException if the same caller_reference is reused.CallerReferenceGenerator (e.g., DateCallerReferenceGenerator) for time-based uniqueness:
$proxy = new CloudFront($client, [
'distribution_id' => 'XYZ123',
'caller_reference_generator' => new DateCallerReferenceGenerator('YmdHis'),
]);
CloudFront Distribution Mismatch:
distribution_id in config and use environment-specific values.TTL Misconfiguration:
DefaultCacheBehavior in CloudFront or use Cache-Control headers to override TTLs.Rate Limiting:
$proxy->purge('/path1')->purge('/path2')->flush();
Enable AWS SDK Debugging:
$client = new CloudFrontClient([
'debug' => true,
'logger' => new \Aws\Handler\Log\LogHandler(new \Monolog\Logger('CloudFront')),
]);
Check CloudFront Logs:
InvalidationList in the CloudFront console for failures.Test Locally:
$mock = Mockery::mock(CloudFrontClient::class);
$mock->shouldReceive('createInvalidation')->andReturn(new Invalidation(['status' => 'InProgress']));
Custom Caller Reference:
Implement CallerReferenceGenerator for business-specific deduplication:
class OrderIdCallerReferenceGenerator implements CallerReferenceGenerator
{
public function generate(): string
{
return 'order-'.Order::latest()->first()->id;
}
}
Pre/Post-Flush Hooks:
Extend the CloudFront class to add callbacks:
class ExtendedCloudFront extends CloudFront
{
public function flush(): self
{
$this->logPurgeRequest();
parent::flush();
$this->notifySlack();
return $this;
}
}
Multi-Distribution Support: Override the proxy to handle multiple distributions:
class MultiDistributionProxy
{
public function __construct(private array $proxies) {}
public function purge(string $path): self
{
foreach ($this->proxies as $proxy) {
$proxy->purge($path);
}
return $this;
}
}
AWS Region:
Ensure the AWS SDK region matches your CloudFront distribution’s edge location (e.g., us-east-1 for global distributions).
IAM Permissions: The IAM user/role must have:
{
"Effect": "Allow",
"Action": [
"cloudfront:CreateInvalidation",
"cloudfront:GetInvalidation"
],
"Resource": "arn:aws:cloudfront::DISTRIBUTION_ID"
}
Path Patterns:
CloudFront invalidation paths must match the distribution’s CacheBehaviors. For example:
/assets/* works if the behavior is configured for assets.*./api/* requires a separate behavior for API paths.Environment Variables:
Avoid hardcoding credentials. Use Laravel’s .env:
AWS_ACCESS_KEY_ID=your_key
AWS_SECRET_ACCESS_KEY=your_secret
CLOUDFRONT_DISTRIBUTION_ID=XYZ123
How can I help you explore Laravel packages today?