Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Fos Http Cache Cloudfront Laravel Package

jean-beru/fos-http-cache-cloudfront

CloudFront proxy implementation for FOSHttpCache. Create an AWS CloudFront client, instantiate the proxy with your distribution ID, purge single URLs or wildcard patterns, then call flush(). Supports custom caller reference generators to avoid duplicate requests.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install Dependencies:

    composer require jean-beru/fos-http-cache-cloudfront:^1.3 async-aws/cloudfront
    

    Since 1.3.0: friendsofsymfony/http-cache 2.x is no longer supported. You must be on friendsofsymfony/http-cache:^3.0 (and typically FOSHttpCacheBundle 3.x). If your app is pinned to 2.x, stay on jean-beru/fos-http-cache-cloudfront:1.2.* until you migrate.

  2. Configure AWS SDK: Ensure AWS credentials are available via environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) or Laravel’s AWS config (config/aws.php).

  3. Initialize the Proxy:

    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'),
        ]
    );
    
  4. First Use Case: Purge a single URL (e.g., after content update):

    $proxy->purge('/home')->flush();
    

Where to Look First

  • README.md: The 1.3.0 release fixed broken links and corrected the code samples, so the README is now authoritative again — read the Usage section first for current syntax (especially the typed purge(string $url) signature).
  • CallerReference/: Explore generator classes (e.g., UniqIdCallerReferenceGenerator) to customize deduplication logic.
  • CHANGELOG / GitHub compare 1.2.0...1.3.0: Confirm behaviour changes before upgrading (CallerReference serialization, purge() typing, dependency drops).
  • Tests: Review tests/ for edge cases (e.g., invalidation failures, rate limiting).

Implementation Patterns

Core Workflows

1. Cache Invalidation

  • Single URL Purge (now explicitly typed string in 1.3.0):
    $proxy->purge('/path/to/resource')->flush();
    
  • Batch Invalidation:
    $proxy->purge('/assets/*')->purge('/images/*')->flush();
    
  • Dynamic Paths: Use Laravel’s route helpers to generate paths — and ensure the result is a string:
    $proxy->purge((string) route('product.show', $id))->flush();
    

2. Cache Warmup

Pre-load critical paths during deployment:

$proxy->warmup('/home')->warmup('/products')->flush();

3. Integration with Laravel Events

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();
    });
}

4. Hybrid Caching

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();

Laravel-Specific Patterns

Service Provider Binding

// 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'],
        ]);
    });
}

Facade Extension (Optional)

Create a CloudFront facade for cleaner syntax:

// app/Facades/CloudFront.php
public static function purge(string $path): self
{
    return static::getFacadeRoot()->purge($path);
}

Command-Line Invalidation

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'));
}

Gotchas and Tips

Pitfalls

  1. Upgrading from 1.2.x to 1.3.0 (Breaking Dependency Drop):

    • Issue: 1.3.0 dropped friendsofsymfony/http-cache 2.x. Composer will fail to resolve if your app still requires it.
    • Fix: Upgrade to friendsofsymfony/http-cache:^3.0 and the matching bundle before bumping this package, or pin jean-beru/fos-http-cache-cloudfront:1.2.* until ready.
  2. CallerReference Must Be a String:

    • Issue: Prior to 1.3.0 the CallerReference value could be sent to createInvalidation in a non-string form, producing SDK validation errors/odd payloads.
    • Fix: 1.3.0 normalises this, so your custom generator’s generate() must return string — cast early if you build it from an int/ULID/UUID object:
      public function generate(): string
      {
          return (string) Str::ulid();
      }
      
  3. purge() Parameter Typing:

    • Issue: 1.3.0 typed the $url parameter of CloudFront::purge() as string. UrlGenerator output, Url value objects, or route() results passed through loosely may now raise a TypeError.
    • Fix: Cast explicitly ((string) route(...)) and check for subclass overrides that widen the signature.
  4. AWS SDK Conflicts:

    • Issue: Mixing async-aws/cloudfront with aws/aws-sdk-php (v2) may cause autoloading errors.
    • Fix: Enforce SDK version in composer.json:
      "require": {
          "async-aws/cloudfront": "^3.0"
      },
      "conflict": {
          "aws/aws-sdk-php": "*"
      }
      
  5. Duplicate Invalidation Errors:

    • Issue: AWS throws FOS\HttpCache\Exception\ProxyResponseException if the same caller_reference is reused.
    • Fix: Use a custom CallerReferenceGenerator (e.g., DateCallerReferenceGenerator) for time-based uniqueness:
      $proxy = new CloudFront($client, [
          'distribution_id' => 'XYZ123',
          'caller_reference_generator' => new DateCallerReferenceGenerator('YmdHis'),
      ]);
      
  6. CloudFront Distribution Mismatch:

    • Issue: Invalidating paths for the wrong distribution (e.g., staging vs. production).
    • Fix: Validate distribution_id in config and use environment-specific values.
  7. TTL Misconfiguration:

    • Issue: CloudFront’s default TTL (24h) may conflict with Laravel’s cache TTL.
    • Fix: Adjust DefaultCacheBehavior in CloudFront or use Cache-Control headers to override TTLs.
  8. Rate Limiting:

    • Issue: AWS CloudFront API limits to 1,000 requests/second (shared across all AWS services).
    • Fix: Batch purges and implement exponential backoff:
      $proxy->purge('/path1')->purge('/path2')->flush();
      

Debugging Tips

  1. Enable AWS SDK Debugging:
    $client = new CloudFrontClient([
        'debug' => true,
        'logger' => new \Aws\Handler\Log\LogHandler(new \Monolog\Logger('CloudFront')),
    ]);
    
  2. Check CloudFront Logs:
    • Use AWS CloudTrail to audit invalidation requests.
    • Monitor InvalidationList in the CloudFront console for failures.
  3. Verify the CallerReference Payload After Upgrading:
    • Log the generated reference before flushing to confirm it is a plain string (the 1.3.0 fix). Any TypeError/validation error here usually points to a custom generator returning a non-string.
  4. Test Locally:
    • Mock the AWS client in tests:
      $mock = Mockery::mock(CloudFrontClient::class);
      $mock->shouldReceive('createInvalidation')->andReturn(new Invalidation(['status' => 'InProgress']));
      

Extension Points

  1. Custom Caller Reference: Implement CallerReferenceGenerator for business-specific deduplication (return type is string, enforced by 1.3.0):

    class OrderIdCallerReferenceGenerator implements CallerReferenceGenerator
    {
        public function generate(): string
        {
            return 'order-'.Order::latest()->first()->id;
        }
    }
    
  2. 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;
        }
    }
    
  3. 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;
        }
    }
    

Configuration Quirks

  1. AWS Region: Ensure the AWS SDK region matches your CloudFront distribution’s edge location (e.g., us-east-1 for global distributions).

  2. IAM Permissions: The IAM user/role must have:

    {
        "Effect": "Allow",
        "Action": [
            "cloudfront:CreateInvalidation",
            "cloudfront:GetInvalidation"
        ],
        "Resource": "arn:aws:cloudfront::DISTRIBUTION_ID"
    }
    
  3. 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.
  4. 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
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin