async-aws/cloud-front
AsyncAws CloudFront Client is a lightweight PHP API client for AWS CloudFront. Install via Composer and use AsyncAws to create and manage CloudFront resources with typed requests and responses. Documentation and contribution guides available at async-aws.com.
Install the Package
composer require async-aws/cloud-front
Ensure your project uses PHP 8.2+ (Laravel 10+).
Configure AWS Credentials
Use Laravel’s existing AWS config (config/aws.php) or set environment variables:
AWS_ACCESS_KEY_ID=your_key
AWS_SECRET_ACCESS_KEY=your_secret
AWS_DEFAULT_REGION=us-east-1
First Use Case: Create a Distribution
use AsyncAws\CloudFront\CloudFrontClient;
use AsyncAws\CloudFront\Input\CreateDistributionInput;
$client = new CloudFrontClient();
$input = new CreateDistributionInput([
'CallerReference' => uniqid(),
'Origins' => [/* ... */],
'DefaultCacheBehavior' => [/* ... */],
]);
// Run asynchronously (e.g., in a Laravel job)
$distribution = await $client->createDistribution($input);
Trigger a Cache Invalidation
$invalidation = await $client->createInvalidation([
'DistributionId' => 'YOUR_DISTRIBUTION_ID',
'InvalidationBatch' => [
'Paths' => ['/path/to/invalidate'],
'CallerReference' => uniqid(),
],
]);
Check the Official Docs
Wrap AsyncAws calls in Laravel jobs to avoid blocking requests:
use AsyncAws\CloudFront\CloudFrontClient;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class CloudFrontInvalidationJob implements ShouldQueue
{
use Dispatchable, Queueable;
public function handle(CloudFrontClient $client)
{
$result = await $client->createInvalidation([
'DistributionId' => 'YOUR_ID',
'InvalidationBatch' => ['Paths' => ['/assets/*'], 'CallerReference' => uniqid()],
]);
}
}
Dispatch from a controller/command:
CloudFrontInvalidationJob::dispatch();
Create a Laravel service to centralize CloudFront logic:
// app/Services/CloudFrontService.php
class CloudFrontService
{
public function __construct(private CloudFrontClient $client) {}
public function invalidateCache(string $distributionId, array $paths): void
{
$job = new CloudFrontInvalidationJob($distributionId, $paths);
dispatch($job);
}
public function getDistribution(string $id): array
{
return await $this->client->getDistribution(['Id' => $id]);
}
}
Register as a singleton in AppServiceProvider:
$this->app->singleton(CloudFrontService::class, function ($app) {
return new CloudFrontService(new CloudFrontClient());
});
Use AsyncAws’s PSR-15 middleware to add logging or retries:
use AsyncAws\CloudFront\Middleware\Middleware;
use Psr\Http\Message\RequestInterface;
$client = new CloudFrontClient();
$client->addMiddleware(new class implements Middleware {
public function __invoke(RequestInterface $request, callable $next): mixed {
// Log request
\Log::debug('CloudFront request:', $request->getBody());
return $next($request);
}
});
Trigger Laravel events after CloudFront operations:
// In CloudFrontService
public function createDistribution(array $config): array
{
$distribution = await $this->client->createDistribution($config);
event(new DistributionCreated($distribution));
return $distribution;
}
Listen in an Event Service Provider:
protected $listen = [
DistributionCreated::class => [DistributionLogger::class],
];
StoreFiles).CloudFrontInvalidationJob::dispatch($distributionId, ['/uploads/' . $file->path()]);
afterCommitted hook for database operations:
Model::afterCommitted(function ($model) {
if ($model->isUploaded()) {
CloudFrontInvalidationJob::dispatch($model->distributionId, [$model->cdnPath]);
}
});
Use CloudFront’s OriginGroups to route traffic based on origin health:
$client->updateDistribution([
'Id' => 'YOUR_ID',
'DistributionConfig' => [
'OriginGroups' => [
[
'Id' => 'primary-origin',
'FailoverCriteria' => ['StatusCodes' => [500, 503]],
'Members' => [/* ... */],
],
],
],
]);
Process multiple distributions in parallel using Laravel’s Bus:
Bus::batch([
new UpdateDistributionJob('dist-1', $config1),
new UpdateDistributionJob('dist-2', $config2),
])->then(function (Batch $batch) {
\Log::info('Batch completed', $batch->id);
});
Leverage Laravel’s HTTP Client for Sync Fallback If async isn’t critical, use Laravel’s HTTP client with AsyncAws’s endpoint:
$response = Http::withHeaders([
'X-Amz-Date' => Carbon::now()->toRfc3339String(),
'Authorization' => 'AWS4-HMAC-SHA256 Credential=...',
])->post('https://cloudfront.amazonaws.com/2021-06-30/distribution', $data);
Use Enums for Strong Typing
AsyncAws uses PHP 8.2 enums for operations (e.g., CreateDistributionInput::class). Validate inputs early:
$input = new CreateDistributionInput([
'CallerReference' => uniqid(),
'Origins' => [
new Origin([
'Id' => 'origin-1',
'DomainName' => 'example.s3.amazonaws.com',
'CustomOriginConfig' => new CustomOriginConfig([
'HTTPPort' => 80,
'HTTPSPort' => 443,
]),
]),
],
]);
Mock AsyncAws in Tests
Use AsyncAws\MockClient for unit tests:
use AsyncAws\MockClient;
$mock = new MockClient();
$mock->shouldReceive('createInvalidation')
->once()
->andReturn(['Invalidation' => ['Id' => 'I123']]);
$service = new CloudFrontService($mock);
$service->invalidateCache('dist-id', ['/test']);
Async/Await Syntax
await before AsyncAws calls will throw RuntimeException.await or wrap in a coroutine:
$loop = \Amp\Loop::get();
$loop->run(function () {
$result = await $client->getDistribution(['Id' => 'YOUR_ID']);
});
Credential Conflicts
aws.php config by default. Explicitly set credentials:
$client = new CloudFrontClient([
'credentials' => new AsyncAws\Credentials\Credentials(
'YOUR_KEY',
'YOUR_SECRET',
'YOUR_TOKEN' // Optional
),
'region' => 'us-east-1',
]);
Region Fallback
us-east-1 by default. Override in config:
$client = new CloudFrontClient(['region' => 'eu-west-1']);
Exception Handling
DistributionNotFoundException). Catch and normalize:
try {
await $client->getDistribution(['Id' => 'INVALID_ID']);
} catch (DistributionNotFoundException $e) {
throw new \RuntimeException('Distribution not found', 0, $e);
}
PHP 8.2+ Features
Rate Limiting
How can I help you explore Laravel packages today?