Installation
composer require xlabs/hwcdnbundle
Add to config/app.php under providers:
Xlabs\HwcdnBundle\HwcdnBundle::class,
Configuration Publish the default config:
php artisan vendor:publish --provider="Xlabs\HwcdnBundle\HwcdnBundle" --tag=config
Update config/hwcdn.php with your HighWinds CDN credentials (API key, account ID, etc.).
First Use Case: Upload a File
use Xlabs\HwcdnBundle\Services\HwcdnService;
$hwcdn = app(HwcdnService::class);
$filePath = storage_path('app/example.jpg');
$result = $hwcdn->upload($filePath, 'my-bucket-name', 'example.jpg');
Verify API Access Test connectivity with:
$hwcdn->ping(); // Returns true if API is reachable
Upload Files
$result = $hwcdn->upload($localPath, $bucket, $remoteName, [
'contentType' => 'image/jpeg',
'cacheControl' => 'public, max-age=31536000',
]);
cacheControl, contentType).HwcdnResponse with URL, status, and metadata.Delete Files
$hwcdn->delete('my-bucket-name', 'example.jpg');
List Files
$files = $hwcdn->listFiles('my-bucket-name', [
'prefix' => 'folder/',
'limit' => 100,
]);
Create/Update Bucket
$hwcdn->createBucket('my-new-bucket', [
'region' => 'us-east-1',
'acl' => 'public-read',
]);
Set Bucket Policy
$hwcdn->setBucketPolicy('my-bucket', file_get_contents('policy.json'));
Generate Signed URLs
$url = $hwcdn->generateSignedUrl('my-bucket', 'example.jpg', '+1hour');
CDN URLs
$cdnUrl = $hwcdn->getCdnUrl('my-bucket', 'example.jpg');
config/hwcdn.php:
'webhooks' => [
'url' => 'https://your-app.com/hwcdn-webhook',
'events' => ['file.uploaded', 'file.deleted'],
],
Handle events in a controller:
public function handleWebhook(Request $request) {
$event = $request->input('event');
$data = $request->input('data');
// Process event (e.g., update DB, trigger notifications)
}
Upload Multiple Files
$files = ['file1.jpg', 'file2.jpg'];
$results = $hwcdn->uploadBatch('my-bucket', $files);
Parallel Uploads Use Laravel queues for async uploads:
UploadFileJob::dispatch($filePath, 'my-bucket', 'remote-name.jpg')->onQueue('hwcdn');
Extend Laravel’s filesystem to use HWCDN:
// config/filesystems.php
'disks' => [
'hwcdn' => [
'driver' => 'hwcdn',
'bucket' => env('HWCDN_BUCKET'),
'api_key' => env('HWCDN_API_KEY'),
],
],
Usage:
Storage::disk('hwcdn')->put('file.jpg', file_get_contents('local.jpg'));
Create a Blade directive for CDN URLs:
// app/Providers/BladeServiceProvider.php
Blade::directive('cdn', function ($expression) {
return "<?php echo app('Xlabs\\HwcdnBundle\\Services\\HwcdnService')->getCdnUrl(...{$expression}); ?>";
});
Usage in Blade:
<img src="{{ cdn('my-bucket', 'image.jpg') }}">
Create custom commands for bulk operations:
// app/Console/Commands/SyncLocalToHwcdn.php
public function handle() {
$files = Storage::disk('local')->files('path/to/files');
foreach ($files as $file) {
$hwcdn = app(HwcdnService::class);
$hwcdn->upload(storage_path($file), 'my-bucket', $file);
}
}
API Rate Limits
retry helper.try {
$hwcdn->upload(...);
} catch (\Xlabs\HwcdnBundle\Exceptions\RateLimitExceeded $e) {
retry()->times(3)->later(2)->try(fn() => $hwcdn->upload(...));
}
File Size Limits
CORS Issues
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedOrigins": ["https://yourdomain.com"],
"ExposeHeaders": []
}
]
Webhook Verification
public function handleWebhook(Request $request) {
$signature = $request->header('X-HW-Signature');
$expected = hash_hmac('sha256', $request->getContent(), env('HWCDN_WEBHOOK_SECRET'));
if (!hash_equals($expected, $signature)) {
abort(403);
}
// Process event
}
Retry Logic for Failures
$hwcdn->withRetry(3, 100)->upload(...);
Enable Debug Mode
Set in config/hwcdn.php:
'debug' => env('APP_DEBUG', false),
Logs API requests/responses to storage/logs/hwcdn.log.
Common Errors
| Error | Cause | Solution |
|---|---|---|
InvalidCredentials |
Wrong API key/account ID | Check config/hwcdn.php |
BucketNotFound |
Bucket doesn’t exist | Create bucket first |
FileNotFound |
File missing in bucket | Verify remote path |
SignatureDoesNotMatch |
Webhook signature mismatch | Regenerate secret in config |
Logging API Responses Extend the service to log responses:
$hwcdn = app(HwcdnService::class);
$hwcdn->setLogger(app(\Psr\Log\LoggerInterface::class));
Custom Storage Adapter
Extend HwcdnAdapter to add features:
namespace App\Services;
use Xlabs\HwcdnBundle\Adapters\HwcdnAdapter;
class CustomHwcdnAdapter extends HwcdnAdapter {
public function customMethod($param) {
// Add custom logic
return $this->client->customCall($param);
}
}
Event Listeners
Listen to HWCDN events (e.g., HwcdnFileUploaded):
// app/Providers/EventServiceProvider.php
protected $listen = [
\Xlabs\HwcdnBundle\Events\HwcdnFileUploaded::class => [
\App\Listeners\LogUploadedFile::class,
],
];
**Middleware
How can I help you explore Laravel packages today?