Skip to content

Commit 40ea24a

Browse files
khempeniuspkozlowski-opensource
authored andcommitted
feat(common): add cloudflare loader
Closes #46315
1 parent fbe005e commit 40ea24a

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {Provider, ɵRuntimeError as RuntimeError} from '@angular/core';
10+
11+
import {RuntimeErrorCode} from '../../../errors';
12+
import {PRECONNECT_CHECK_BLOCKLIST} from '../preconnect_link_checker';
13+
import {isValidPath, normalizePath, normalizeSrc} from '../util';
14+
15+
import {IMAGE_LOADER, ImageLoaderConfig} from './image_loader';
16+
17+
/**
18+
* Function that generates a built-in ImageLoader for Cloudflare Image Resizing
19+
* and turns it into an Angular provider. Note: Cloudflare has multiple image
20+
* products - this provider is specifically for Cloudflare Image Resizing;
21+
* it will not work with Cloudflare Images or Cloudflare Polish.
22+
*
23+
* @param path Your domain name
24+
* e.g. https://mysite.com
25+
* @returns Provider that provides an ImageLoader function
26+
*/
27+
export function provideCloudflareLoader(path: string, options: {ensurePreconnect?: boolean} = {
28+
ensurePreconnect: true
29+
}) {
30+
if (ngDevMode && !isValidPath(path)) {
31+
throwInvalidPathError(path);
32+
}
33+
path = normalizePath(path);
34+
35+
const providers: Provider[] = [{
36+
provide: IMAGE_LOADER,
37+
useValue: (config: ImageLoaderConfig) => {
38+
let params = `format=auto`;
39+
if (config.width) {
40+
params += `,width=${config.width.toString()}`;
41+
}
42+
const url = `${path}/cdn-cgi/image/${params}/${normalizeSrc(config.src)}`;
43+
return url;
44+
}
45+
}];
46+
47+
if (ngDevMode && Boolean(options.ensurePreconnect) === true) {
48+
providers.push({provide: PRECONNECT_CHECK_BLOCKLIST, useValue: [path], multi: true});
49+
}
50+
51+
return providers;
52+
}
53+
54+
function throwInvalidPathError(path: unknown): never {
55+
throw new RuntimeError(
56+
RuntimeErrorCode.INVALID_INPUT,
57+
`CloudflareLoader has detected an invalid path: ` +
58+
`expecting a path like https://<ZONE>/cdn-cgi/image/<OPTIONS>/<SOURCE-IMAGE>` +
59+
`but got: \`${path}\``);
60+
}

packages/common/test/image_loaders/image_loader_spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import {IMAGE_LOADER, ImageLoader, PRECONNECT_CHECK_BLOCKLIST} from '@angular/common/src/directives/ng_optimized_image';
10+
import {provideCloudflareLoader} from '@angular/common/src/directives/ng_optimized_image/image_loaders/cloudflare_loader';
1011
import {provideCloudinaryLoader} from '@angular/common/src/directives/ng_optimized_image/image_loaders/cloudinary_loader';
1112
import {provideImageKitLoader} from '@angular/common/src/directives/ng_optimized_image/image_loaders/imagekit_loader';
1213
import {provideImgixLoader} from '@angular/common/src/directives/ng_optimized_image/image_loaders/imgix_loader';
@@ -246,4 +247,21 @@ describe('Built-in image directive loaders', () => {
246247
});
247248
});
248249
});
250+
251+
describe('Cloudflare loader', () => {
252+
function createCloudflareLoader(path: string): ImageLoader {
253+
const injector = createEnvironmentInjector([provideCloudflareLoader(path)]);
254+
return injector.get(IMAGE_LOADER);
255+
}
256+
it('should construct an image loader with the given path', () => {
257+
const loader = createCloudflareLoader('https://mysite.com');
258+
let config = {src: 'img.png'};
259+
expect(loader(config)).toBe('https://mysite.com/cdn-cgi/image/format=auto/img.png');
260+
});
261+
it('should construct an image loader with the given path', () => {
262+
const loader = createCloudflareLoader('https://mysite.com');
263+
const config = {src: 'img.png', width: 100};
264+
expect(loader(config)).toBe('https://mysite.com/cdn-cgi/image/format=auto,width=100/img.png');
265+
});
266+
});
249267
});

0 commit comments

Comments
 (0)