├── src ├── Exceptions │ ├── CloudflareImagesApiException.php │ ├── CloudflareImageNotFound.php │ ├── CloudflareImagesApiUnexpectedError.php │ ├── IncorrectKeyOrAccountProvided.php │ ├── CloudflareSignatureTokenNotProvided.php │ ├── NoImageDeliveryUrlProvided.php │ ├── NoKeyOrAccountProvided.php │ └── CloudflareSignedUrlNotSupportedForCustomIds.php ├── Http │ ├── Entities │ │ ├── ArrayableEntity.php │ │ ├── DirectUploadInfo.php │ │ ├── ImageVariant.php │ │ ├── ImageVariants.php │ │ └── Image.php │ ├── Responses │ │ ├── DetailsResponse.php │ │ ├── ListResponse.php │ │ └── BaseResponse.php │ └── Clients │ │ ├── ImagesVariantsApiClient.php │ │ └── ImagesApiClient.php ├── CloudflareApi.php ├── Facades │ └── CloudflareApi.php ├── CloudflareImagesServiceProvider.php ├── Helpers │ └── SignedUrlGenerator.php └── Testing │ └── Fakes │ ├── ImagesVariantsApiClientFake.php │ └── ImagesApiClientFake.php ├── config └── cloudflare_images.php ├── LICENSE ├── composer.json └── README.md /src/Exceptions/CloudflareImagesApiException.php: -------------------------------------------------------------------------------- 1 | env('CLOUDFLARE_IMAGES_ACCOUNT'), 5 | 'key' => env('CLOUDFLARE_IMAGES_KEY'), 6 | 'delivery_url' => env('CLOUDFLARE_IMAGES_DELIVERY_URL'), // https://imagedelivery.net/ZWd9g1K8vvvVv_Yyyy_XXX 7 | 'default_variation' => env('CLOUDFLARE_IMAGES_DEFAULT_VARIATION', 'public'), // One of defined image variation on Cloudlflare Images Variations 8 | 'signature_token' => env('CLOUDFLARE_IMAGES_SIGNATURE_TOKEN'), 9 | ]; 10 | -------------------------------------------------------------------------------- /src/CloudflareApi.php: -------------------------------------------------------------------------------- 1 | result = $class::fromArray($this->result); 41 | } 42 | 43 | return $this; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Facades/CloudflareApi.php: -------------------------------------------------------------------------------- 1 | andReturn(new ImagesApiClientFake()); 38 | self::shouldReceive('variants')->andReturn(new ImagesVariantsApiClientFake()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/CloudflareImagesServiceProvider.php: -------------------------------------------------------------------------------- 1 | bootPublishes(); 15 | } 16 | 17 | /** 18 | * Register package resources 19 | */ 20 | public function register(): void 21 | { 22 | $this->registerConfig(); 23 | $this->registerFacade(); 24 | } 25 | 26 | /** 27 | * Boot publishable resources 28 | */ 29 | protected function bootPublishes(): void 30 | { 31 | $this->publishes([ 32 | __DIR__ . '/../config/cloudflare_images.php' => $this->app->configPath('cloudflare_images.php'), 33 | ], 'config'); 34 | } 35 | 36 | /** 37 | * Register related config 38 | */ 39 | protected function registerConfig(): void 40 | { 41 | $this->mergeConfigFrom(__DIR__ . '/../config/cloudflare_images.php', 'cloudflare_images'); 42 | } 43 | 44 | /** 45 | * Register related facade 46 | */ 47 | protected function registerFacade(): void 48 | { 49 | $this->app->bind('cloudflareImages', function ($app) { 50 | return new CloudflareApi(); 51 | }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Http/Entities/DirectUploadInfo.php: -------------------------------------------------------------------------------- 1 | id = $id; 28 | $this->uploadURL = $uploadURL; 29 | } 30 | 31 | /** 32 | * Return Photo instance from array 33 | * 34 | * @param array $array 35 | * 36 | * @return self 37 | */ 38 | public static function fromArray(array $array) 39 | { 40 | return new self( 41 | (string) Arr::get($array, 'id'), 42 | (string) Arr::get($array, 'uploadURL'), 43 | ); 44 | } 45 | 46 | /** 47 | * @inheritDoc 48 | */ 49 | final public function toArray(): array 50 | { 51 | return [ 52 | 'id' => $this->id, 53 | 'uploadURL' => $this->uploadURL, 54 | ]; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Http/Entities/ImageVariant.php: -------------------------------------------------------------------------------- 1 | id = $id; 31 | $this->options = $options; 32 | $this->neverRequireSignedURLs = $neverRequireSignedURLs; 33 | } 34 | 35 | /** 36 | * Return Photo instance from array 37 | * 38 | * @param array $array 39 | * 40 | * @return ImageVariant 41 | */ 42 | public static function fromArray(array $array) 43 | { 44 | return new self( 45 | (string) Arr::get($array, 'id'), 46 | (array) Arr::get($array, 'options'), 47 | (bool) Arr::get($array, 'neverRequireSignedURLs'), 48 | ); 49 | } 50 | 51 | /** 52 | * @inheritDoc 53 | */ 54 | final public function toArray(): array 55 | { 56 | return [ 57 | 'id' => $this->id, 58 | 'metadata' => $this->options, 59 | 'requireSignedURLs' => $this->neverRequireSignedURLs, 60 | ]; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dedmytro/laravel-cloudflare-images", 3 | "description": "Cloudflare API client and filesystem for Laravel", 4 | "type": "library", 5 | "license": "MIT", 6 | "keywords": [ 7 | "laravel", 8 | "cloudflare", 9 | "cloudflare api", 10 | "cloudflare images" 11 | ], 12 | "authors": [ 13 | { 14 | "name": "Hodun Dmytro", 15 | "email": "godundmytro@gmail.com" 16 | } 17 | ], 18 | "support": { 19 | "issues": "https://github.com/DeDmytro/laravel-cloudflare-images/issues", 20 | "source": "https://github.com/DeDmytro/laravel-cloudflare-images" 21 | }, 22 | "require": { 23 | "php": "^7.4|^8.0", 24 | "illuminate/support": "^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", 25 | "guzzlehttp/guzzle": "^6.2.1|^7.0" 26 | }, 27 | "require-dev": { 28 | "mockery/mockery": "^1.0", 29 | "orchestra/testbench": "^6.0|^9.0|^10.0", 30 | "phpunit/phpunit": "^10.0|^11.5.3" 31 | }, 32 | "autoload": { 33 | "psr-4": { 34 | "DeDmytro\\CloudflareImages\\": "src" 35 | } 36 | }, 37 | "autoload-dev": { 38 | "psr-4": { 39 | "Tests\\": "tests" 40 | } 41 | }, 42 | "config": { 43 | "preferred-install": "dist", 44 | "sort-packages": true 45 | }, 46 | "minimum-stability": "stable", 47 | "prefer-stable": true, 48 | "extra": { 49 | "laravel": { 50 | "providers": [ 51 | "DeDmytro\\CloudflareImages\\CloudflareImagesServiceProvider" 52 | ], 53 | "aliases": { 54 | "CloudflareImages": "DeDmytro\\CloudflareImages\\Facades\\CloudflareApi" 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Http/Responses/ListResponse.php: -------------------------------------------------------------------------------- 1 | result = array_map(static fn (array $image) => $class::fromArray($image), Arr::get($this->result, $key, [])); 44 | } 45 | 46 | return $this; 47 | } 48 | 49 | /** 50 | * @inheritDoc 51 | */ 52 | final public function toArray(): array 53 | { 54 | return [ 55 | 'success' => $this->success, 56 | 'errors' => $this->errors, 57 | 'messages' => $this->messages, 58 | 'result' => array_map(static fn ($image) => $image->toArray(), $this->result), 59 | ]; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Http/Entities/ImageVariants.php: -------------------------------------------------------------------------------- 1 | variants[$key] = $variant; 21 | } 22 | } 23 | 24 | /** 25 | * Return new instance 26 | * 27 | * @param array $array 28 | * 29 | * @return self 30 | */ 31 | final public static function fromArray(array $array) 32 | { 33 | return new self($array); 34 | } 35 | 36 | /** 37 | * @inheritDoc 38 | */ 39 | final public function toArray(): array 40 | { 41 | return $this->variants; 42 | } 43 | 44 | /** 45 | * Return image variant url by name 46 | * 47 | * @param string $name 48 | * 49 | * @return mixed|string 50 | */ 51 | public function __get(string $name) 52 | { 53 | if (array_key_exists($name, $this->variants)) { 54 | return $this->variants[$name]; 55 | } 56 | 57 | return ''; 58 | } 59 | 60 | /** 61 | * Set/Update variation url by name 62 | * 63 | * @param string $name 64 | * @param $value 65 | */ 66 | public function __set(string $name, $value) 67 | { 68 | $this->variants[$name] = $value; 69 | } 70 | 71 | /** 72 | * Check variation exists when use isset() or empty() on property 73 | * 74 | * @param $name 75 | * 76 | * @return bool 77 | */ 78 | public function __isset($name) 79 | { 80 | return array_key_exists($name, $this->variants); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Http/Entities/Image.php: -------------------------------------------------------------------------------- 1 | id = $id; 36 | $this->filename = $filename; 37 | $this->metadata = $metadata; 38 | $this->requireSignedURLs = $requireSignedURLs; 39 | $this->variants = $variants; 40 | $this->uploaded = Carbon::parse($uploaded); 41 | } 42 | 43 | /** 44 | * Return Image instance from array 45 | * 46 | * @param array $array 47 | * 48 | * @return Image 49 | */ 50 | public static function fromArray(array $array) 51 | { 52 | return new self( 53 | (string) Arr::get($array, 'id'), 54 | (string) Arr::get($array, 'filename'), 55 | (array) Arr::get($array, 'meta'), 56 | (bool) Arr::get($array, 'requireSignedURLs'), 57 | ImageVariants::fromArray((array) Arr::get($array, 'variants')), 58 | Arr::get($array, 'uploaded'), 59 | ); 60 | } 61 | 62 | /** 63 | * @inheritDoc 64 | */ 65 | final public function toArray(): array 66 | { 67 | return [ 68 | 'id' => $this->id, 69 | 'filename' => $this->filename, 70 | 'metadata' => $this->metadata, 71 | 'requireSignedURLs' => $this->requireSignedURLs, 72 | 'variants' => $this->variants->toArray(), 73 | 'uploaded' => $this->uploaded, 74 | ]; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Http/Clients/ImagesVariantsApiClient.php: -------------------------------------------------------------------------------- 1 | httpClient = Http::withToken($key)->baseUrl("https://api.cloudflare.com/client/v4/accounts/$account/images/v1"); 40 | } 41 | 42 | /** 43 | * Return list of images variants 44 | * 45 | * @return ListResponse 46 | */ 47 | public function list(): ListResponse 48 | { 49 | return ListResponse::fromArray($this->httpClient->get('variants')->json())->mapResultInto(ImageVariant::class, 'variants'); 50 | } 51 | 52 | /** 53 | * Return variant by ID 54 | * 55 | * @param string $variantId 56 | * 57 | * @return DetailsResponse 58 | */ 59 | public function get(string $variantId): DetailsResponse 60 | { 61 | return DetailsResponse::fromArray($this->httpClient->get("variants/$variantId")->json())->mapResultInto(ImageVariant::class); 62 | } 63 | 64 | /** 65 | * Delete image by ID 66 | * 67 | * @param string $variantId 68 | * 69 | * @return DetailsResponse 70 | */ 71 | public function delete(string $variantId): DetailsResponse 72 | { 73 | return DetailsResponse::fromArray($this->httpClient->delete("variants/$variantId")->json()); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Helpers/SignedUrlGenerator.php: -------------------------------------------------------------------------------- 1 | signatureToken = config('cloudflare_images.signature_token'); 39 | 40 | $this->imageUrl = $imageUrl; 41 | } 42 | 43 | /** 44 | * @param string $imageUrl 45 | * 46 | * @return self 47 | */ 48 | public static function fromDeliveryUrl(string $imageUrl): self 49 | { 50 | return new self($imageUrl); 51 | } 52 | 53 | /** 54 | * Set the expiration time for the signed URL 55 | * 56 | * @param int $seconds 57 | * 58 | * @return $this 59 | */ 60 | final public function setExpiration(int $seconds): self 61 | { 62 | $this->expiry = $seconds; 63 | 64 | return $this; 65 | } 66 | 67 | /** 68 | * Generate the signed URL 69 | * 70 | * @return string 71 | */ 72 | final public function generate(): string 73 | { 74 | $urlParts = parse_url($this->imageUrl); 75 | $urlPath = $urlParts['path']; 76 | 77 | // Attach the expiration value to the `url` 78 | $expiry = time() + $this->expiry; 79 | $queryParams['exp'] = $expiry; 80 | 81 | // Generate the string to sign (including query parameters) 82 | $stringToSign = $urlPath . '?' . http_build_query($queryParams); 83 | 84 | // Generate the signature 85 | $mac = hash_hmac('sha256', $stringToSign, $this->signatureToken); 86 | 87 | // And attach it to the `url` 88 | $queryParams['sig'] = $mac; 89 | 90 | // Rebuild the URL with the signature 91 | return $urlParts['scheme'] . '://' . $urlParts['host'] . $urlPath . '?' . http_build_query($queryParams); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Http/Responses/BaseResponse.php: -------------------------------------------------------------------------------- 1 | result = $result; 48 | $this->success = $success; 49 | $this->errors = $errors; 50 | $this->messages = $messages; 51 | } 52 | 53 | /** 54 | * Return new instance 55 | * 56 | * @param array $array 57 | * 58 | * @throws IncorrectKeyOrAccountProvided 59 | * @throws CloudflareImagesApiUnexpectedError 60 | * @return static 61 | */ 62 | final public static function fromArray(array $array) 63 | { 64 | try { 65 | return new static( 66 | Arr::get($array, 'result'), 67 | (bool) Arr::get($array, 'success'), 68 | Arr::get($array, 'errors', []), 69 | Arr::get($array, 'messages', []), 70 | ); 71 | } 72 | catch (TypeError $exception) { 73 | $responseCode = Arr::get($array, 'errors.0.code'); 74 | 75 | if (in_array($responseCode, [self::RESPONSE_CODE_AUTHENTICATION_ERROR, self::RESPONSE_CODE_MISSING_AUTHORIZATION_KEYS], true)) { 76 | throw new IncorrectKeyOrAccountProvided(); 77 | } 78 | 79 | throw new CloudflareImagesApiUnexpectedError(Arr::get($array, 'errors.0.message')); 80 | } 81 | } 82 | 83 | /** 84 | * @inheritDoc 85 | */ 86 | public function toArray(): array 87 | { 88 | return [ 89 | 'success' => $this->success, 90 | 'errors' => $this->errors, 91 | 'messages' => $this->messages, 92 | 'result' => $this->result, 93 | ]; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Testing/Fakes/ImagesVariantsApiClientFake.php: -------------------------------------------------------------------------------- 1 | set('cloudflare_images.account', 'fake'); 35 | config()->set('cloudflare_images.key', 'fake'); 36 | config()->set('cloudflare_images.default_variation', 'fake'); 37 | config()->set('cloudflare_images.delivery_url', 'fake'); 38 | 39 | parent::__construct(); 40 | } 41 | 42 | /** 43 | * Return list of images variants 44 | * 45 | * @return ListResponse 46 | */ 47 | public function list(): ListResponse 48 | { 49 | $result = [ 50 | 'result' => ['variants' => [$this->testVariationData(), $this->testVariationData(), $this->testVariationData()]], 51 | 'success' => true, 52 | 'errors' => [], 53 | 'messages' => [], 54 | ]; 55 | 56 | return ListResponse::fromArray($result)->mapResultInto(ImageVariant::class, 'variants'); 57 | } 58 | 59 | /** 60 | * Return test variation data and save id to static 61 | * 62 | * @return array 63 | */ 64 | private function testVariationData(): array 65 | { 66 | $id = Str::random(64); 67 | 68 | static::$createdFakeIds[] = $id; 69 | 70 | return [ 71 | 'id' => $id, 72 | 'options' => [], 73 | 'neverRequireSignedURLs' => true, 74 | ]; 75 | } 76 | 77 | /** 78 | * Return variant by ID 79 | * 80 | * @param string $variantId 81 | * 82 | * @return DetailsResponse 83 | */ 84 | public function get(string $variantId): DetailsResponse 85 | { 86 | $result = $this->testVariationData(); 87 | 88 | return DetailsResponse::fromArray($result)->mapResultInto(ImageVariant::class); 89 | } 90 | 91 | /** 92 | * Delete image by ID 93 | * 94 | * @param string $variantId 95 | * 96 | * @return DetailsResponse 97 | */ 98 | public function delete(string $variantId): DetailsResponse 99 | { 100 | $result = [ 101 | 'result' => [], 102 | 'success' => true, 103 | 'errors' => [], 104 | 'messages' => [], 105 | ]; 106 | 107 | return DetailsResponse::fromArray($result); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Testing/Fakes/ImagesApiClientFake.php: -------------------------------------------------------------------------------- 1 | set('cloudflare_images.account', 'fake'); 31 | config()->set('cloudflare_images.key', 'fake'); 32 | config()->set('cloudflare_images.default_variation', 'fake'); 33 | config()->set('cloudflare_images.delivery_url', 'fake'); 34 | 35 | parent::__construct(); 36 | } 37 | 38 | /** 39 | * Upload file and return details 40 | * 41 | * @param string|\Illuminate\Http\UploadedFile $file 42 | * @param bool $requiredSignedUrl 43 | * @param array $metadata 44 | * 45 | * @return DetailsResponse 46 | */ 47 | public function upload($file, string $filename = '', bool $requiredSignedUrl = false, array $metadata = [], string $customId = null): DetailsResponse 48 | { 49 | $result = [ 50 | 'result' => $this->testImageData(Str::afterLast($file, '/')), 51 | 'success' => true, 52 | 'errors' => [], 53 | 'messages' => [], 54 | ]; 55 | 56 | return DetailsResponse::fromArray($result)->mapResultInto(Image::class); 57 | } 58 | 59 | /** 60 | * Return test image data and save id to static 61 | * 62 | * @param string|null $filename 63 | * 64 | * @return array 65 | */ 66 | private function testImageData(string $filename = null): array 67 | { 68 | $id = Str::random(64); 69 | 70 | static::$createdFakeIds[] = $id; 71 | 72 | return [ 73 | 'id' => $id, 74 | 'filename' => $filename ?? Str::random(64), 75 | 'metadata' => [], 76 | 'requireSignedURLs' => false, 77 | 'variants' => [], 78 | 'uploaded' => now()->toDateTimeString(), 79 | ]; 80 | } 81 | 82 | /** 83 | * Return list of images 84 | * 85 | * @param int $page 86 | * @param int $perPage 87 | * 88 | * @return ListResponse 89 | */ 90 | public function list(int $page = 1, int $perPage = 50): ListResponse 91 | { 92 | $result = [ 93 | 'result' => array_map(function ($item) { 94 | return $this->testImageData(); 95 | }, range(1, $perPage)), 96 | 'success' => true, 97 | 'errors' => [], 98 | 'messages' => [], 99 | ]; 100 | 101 | return ListResponse::fromArray($result)->mapResultInto(Image::class, 'images'); 102 | } 103 | 104 | /** 105 | * Return image details by ID 106 | * 107 | * @param string $imageId 108 | * 109 | * @throws \Throwable 110 | * @return DetailsResponse 111 | */ 112 | public function get(string $imageId): DetailsResponse 113 | { 114 | $result = [ 115 | 'result' => $this->testImageData(), 116 | 'success' => true, 117 | 'errors' => [], 118 | 'messages' => [], 119 | ]; 120 | 121 | return DetailsResponse::fromArray($result)->mapResultInto(Image::class); 122 | } 123 | 124 | /** 125 | * Delete image by ID 126 | * 127 | * @param string $imageId 128 | * 129 | * @throws \Throwable 130 | * @return DetailsResponse 131 | */ 132 | public function delete(string $imageId): DetailsResponse 133 | { 134 | $result = [ 135 | 'result' => [], 136 | 'success' => true, 137 | 'errors' => [], 138 | 'messages' => [], 139 | ]; 140 | 141 | return DetailsResponse::fromArray($result); 142 | } 143 | 144 | /** 145 | * Check image exists by ID 146 | * 147 | * @param string $imageId 148 | * 149 | * @throws \Throwable 150 | * @return bool 151 | */ 152 | public function exists(string $imageId): bool 153 | { 154 | return in_array($imageId, static::$createdFakeIds, true); 155 | } 156 | 157 | /** 158 | * Return direct upload information 159 | * Direct upload allows uploading files from frontend without sharing the application api key 160 | * 161 | * @link https://developers.cloudflare.com/images/cloudflare-images/upload-images/direct-creator-upload 162 | * @return DetailsResponse 163 | */ 164 | public function directUploadUrl(): DetailsResponse 165 | { 166 | $result = [ 167 | 'result' => [ 168 | 'id' => Str::random(), 169 | 'uploadURL' => 'https://api.cloudflarefake.com/', 170 | ], 171 | 'success' => true, 172 | 'errors' => [], 173 | 'messages' => [], 174 | ]; 175 | 176 | return DetailsResponse::fromArray($result)->mapResultInto(DirectUploadInfo::class); 177 | } 178 | 179 | /** 180 | * Return image public url by image id and variation 181 | * 182 | * @param string $imageId 183 | * @param string|null $variation 184 | * 185 | * @throws \Throwable 186 | * @return string 187 | */ 188 | public function url(string $imageId, ?string $variation = null): string 189 | { 190 | return Str::random(64); 191 | } 192 | 193 | /** 194 | * Return signed image for private url by image id and variation 195 | * 196 | * @param string $imageId 197 | * @param string|null $variation 198 | * @param int $expirationSeconds * 199 | * 200 | * @throws \Throwable 201 | * @return string 202 | */ 203 | public function signedUrl(string $imageId, ?string $variation = null, int $expirationSeconds = 3600): string 204 | { 205 | return SignedUrlGenerator::fromDeliveryUrl($this->url($imageId, $variation))->setExpiration($expirationSeconds)->generate(); 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cloudflare Images 2 | 3 | Provides access to Cloudflare Images API for Laravel projects 4 | 5 | [![Stable Version][badge_stable]][link_packagist] 6 | [![Unstable Version][badge_unstable]][link_packagist] 7 | [![Total Downloads][badge_downloads]][link_packagist] 8 | [![License][badge_license]][link_license] 9 | 10 | ## Table of contents 11 | 12 | * [Installation](#installation) 13 | * [Configuration](#configuration) 14 | * [Using](#using) 15 | 16 | ## Installation 17 | 18 | To get the latest version of `Laravel CloudflareImages`, simply require the project using [Composer](https://getcomposer.org): 19 | 20 | ```bash 21 | $ composer require dedmytro/laravel-cloudflare-images 22 | ``` 23 | 24 | Or manually update `require` block of `composer.json` and run `composer update`. 25 | 26 | ```json 27 | { 28 | "require": { 29 | "dedmytro/laravel-cloudflare-images": "^0.2" 30 | } 31 | } 32 | ``` 33 | 34 | ## Configuration 35 | 36 | Add environment variables to your .env file: 37 | 38 | ```dotenv 39 | CLOUDFLARE_IMAGES_ACCOUNT='your-account-id' 40 | CLOUDFLARE_IMAGES_KEY='your-api-key' 41 | CLOUDFLARE_IMAGES_DELIVERY_URL='https://imagedelivery.net/ZWd9g1K8vvvVv_Yyyy_XXX' 42 | CLOUDFLARE_IMAGES_DEFAULT_VARIATION='your-default-variation' 43 | CLOUDFLARE_IMAGES_SIGNATURE_TOKEN='your-signature-token' 44 | ``` 45 | 46 | or publish config and set up vars there 47 | 48 | ```php 49 | return [ 50 | 'account'=> env('CLOUDFLARE_IMAGES_ACCOUNT'), 51 | 'key'=> env('CLOUDFLARE_IMAGES_KEY'), 52 | 'delivery_url' => env('CLOUDFLARE_IMAGES_DELIVERY_URL'), 53 | 'default_variation' => env('CLOUDFLARE_IMAGES_DEFAULT_VARIATION'), 54 | 'signature_token' => env('CLOUDFLARE_IMAGES_SIGNATURE_TOKEN') 55 | ]; 56 | ``` 57 | 58 | `CLOUDFLARE_IMAGES_KEY` - is an `API Token`. To create a new one go to [User Api Tokens](https://dash.cloudflare.com/profile/api-tokens) on Cloudflare dashboard 59 | 60 | `CLOUDFLARE_IMAGES_ACCOUNT` - is an `Account ID` on the Overview page 61 | 62 | `CLOUDFLARE_IMAGES_DELIVERY_URL` - is an `Image Delivery URL` on the Overview page 63 | 64 | `CLOUDFLARE_IMAGES_DEFAULT_VARIATION` - is a variation on the Variants page 65 | 66 | `CLOUDFLARE_IMAGES_SIGNATURE_TOKEN` - is a token from the Images -> Keys page 67 | 68 | 69 | ## Using 70 | 71 | ### Direct upload 72 | 73 | The Direct upload is feature of Cloudflare Images to upload image directly from frontend but without sharing your api key. Once you get this url you can use 74 | inside your html 75 | 76 | `