Skip to content

Commit 2f2f2dc

Browse files
Add support for URL configuration of domains and sub-domains (#211)
1 parent 07e0fa5 commit 2f2f2dc

File tree

9 files changed

+165
-39
lines changed

9 files changed

+165
-39
lines changed

.github/pull_request_template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
### Pull reuqest for @Cloudianry/Base
1+
### Pull request for @Cloudinary/Base
22

33

44
#### What does this PR solve?

__TESTS__/unit/config/cloudinaryConfig.test.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,10 @@ describe('Tests for CloudinaryConfiguration', () => {
4444
signUrl: true,
4545
longUrlSignature: true,
4646
useRootPath: true,
47-
cdnSubdomain: true,
4847
cname: 'cname',
49-
secureCdnSubdomain: true,
5048
privateCdn: true,
5149
secure: true,
52-
secureDistribution: true
50+
secureDistribution: ''
5351
}
5452
});
5553

@@ -58,12 +56,10 @@ describe('Tests for CloudinaryConfiguration', () => {
5856
expect(conf.url.signUrl).toBe(true);
5957
expect(conf.url.longUrlSignature).toBe(true);
6058
expect(conf.url.useRootPath).toBe(true);
61-
expect(conf.url.cdnSubdomain).toBe(true);
6259
expect(conf.url.cname).toBe('cname');
63-
expect(conf.url.secureCdnSubdomain).toBe(true);
6460
expect(conf.url.privateCdn).toBe(true);
6561
expect(conf.url.secure).toBe(true);
66-
expect(conf.url.secureDistribution).toBe(true);
62+
expect(conf.url.secureDistribution).toBe('');
6763

6864
});
6965

__TESTS__/unit/urlConfig.test.ts

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
import TransformableImage from "../../src/transformation/TransformableImage";
22
import * as Resize from "../../src/actions/resize/Resize";
33
import ICloudinaryConfigurations from "../../src/interfaces/Config/ICloudinaryConfigurations";
4+
import IURLConfig from "../../src/interfaces/Config/IURLConfig";
5+
import CloudinaryConfig from "../../src/config/CloudinaryConfig";
6+
import createCloudinaryURL from "../../src/url/cloudinaryURL";
7+
8+
/**
9+
* @description Create CloudinaryURL based on a URL Configuration, and return the URL
10+
* @param urlConfig
11+
*/
12+
function createURLFromConfig(urlConfig: IURLConfig) {
13+
const conf = new CloudinaryConfig({
14+
cloud: {
15+
cloudName: 'demo'
16+
},
17+
url: urlConfig
18+
});
19+
20+
return createCloudinaryURL(conf, { publicID: 'sample' });
21+
}
422

523
const DEMO_CONFIG = {
624
cloud: {
@@ -9,7 +27,7 @@ const DEMO_CONFIG = {
927
}
1028
};
1129

12-
describe('It tests a combination of Cloudianry URL and Configuration', () => {
30+
describe('It tests a combination of Cloudinary URL and Configuration', () => {
1331
it ('Generates a URL', () => {
1432
const url = new TransformableImage('my_image')
1533
.setConfig(DEMO_CONFIG)
@@ -74,4 +92,58 @@ describe('It tests a combination of Cloudianry URL and Configuration', () => {
7492

7593
expect(url).toBe('https://res.cloudinary.com/MY_CLOUD_NAME/avatar/fetch/c_fill,h_100,w_100/sample');
7694
});
95+
96+
97+
98+
it('Secure by default', () => {
99+
const url = createURLFromConfig({});
100+
expect(url).toContain('https://res.cloudinary.com/demo');
101+
});
102+
103+
it('Supports secure:false', () => {
104+
const url = createURLFromConfig({
105+
secure:false
106+
});
107+
expect(url).toContain('http://res.cloudinary.com/demo');
108+
});
109+
110+
it('Support cname with secure false', () => {
111+
const url = createURLFromConfig({
112+
cname:'hello.com',
113+
secure: false
114+
});
115+
expect(url).toContain('http://hello.com/demo');
116+
});
117+
118+
it('Support secureDistribution with secure true', () => {
119+
const url = createURLFromConfig({
120+
secureDistribution:'foobar.com'
121+
});
122+
expect(url).toContain('https://foobar.com/demo');
123+
});
124+
125+
it('Support private CDN with secure true', () => {
126+
const url = createURLFromConfig({
127+
privateCdn:true
128+
});
129+
expect(url).toContain(`https://demo-res.cloudinary.com/image/upload`);
130+
});
131+
132+
it('Support secureDistribution with secure true', () => {
133+
const url = createURLFromConfig({
134+
secure: true,
135+
privateCdn: true,
136+
secureDistribution: "something.cloudfront.net"
137+
});
138+
expect(url).toContain('https://something.cloudfront.net/image/upload/');
139+
});
77140
});
141+
142+
143+
/**
144+
* http://res.cloudinary.com/{cloudName}
145+
* https://res.cloudinary.com/{cloudName}
146+
* https://{cloudName}-res.cloudinary.com/
147+
* http://{domain}
148+
* https://{domain}
149+
*/

jest.config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
["jest-html-reporters", {
2929
"publicPath" : "./public/progress/",
3030
"filename": "cloudinary-base-progress-report.html",
31-
"pageTitle": "Cloudianry JS 2.0 Progress Report",
31+
"pageTitle": "Cloudinary JS 2.0 Progress Report",
3232
"logoImgPath": "./__DOC_RESOURCES__/cloudinary-logo.png",
3333
"expand": true
3434
}]

src/config/CloudinaryConfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class CloudinaryConfig {
66
public cloud: CloudConfig;
77
public url: URLConfig;
88

9-
constructor(configurations: ICloudinaryConfigurations) {
9+
constructor(configurations: ICloudinaryConfigurations = {}) {
1010
this.cloud = new CloudConfig(configurations.cloud);
1111
this.url = new URLConfig(configurations.url || {});
1212
}

src/config/URLConfig.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ import {ALLOWED_URL_CONFIG} from "../internalConstants";
44
import ICloudConfig from "../interfaces/Config/ICloudConfig";
55

66
class URLConfig extends Config implements IURLConfig {
7-
cdnSubdomain?: boolean;
8-
secureCdnSubdomain?: boolean;
97
cname?: string; // User subdomain (example.cloudinary.com)
10-
secureDistribution?: boolean;
8+
secureDistribution?: string;
119
privateCdn?: boolean;
1210
signUrl?: boolean;
1311
longUrlSignature?: boolean;
@@ -22,7 +20,9 @@ class URLConfig extends Config implements IURLConfig {
2220
constructor(userURLConfig: IURLConfig | unknown) {
2321
super();
2422
const urlConfig = this.filterOutNonSupportedKeys(userURLConfig, ALLOWED_URL_CONFIG);
25-
Object.assign(this, {secure: true}, urlConfig);
23+
Object.assign(this, {
24+
secure: true
25+
}, urlConfig);
2626
}
2727

2828
extend(userURLConfig: ICloudConfig | unknown): URLConfig {
Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
/**
22
* @name ICloudinaryAssetConfigurations
33
* @description
4-
* Defines the configuration needed for URL-related options when creating Cloudianry URL
5-
*
6-
* @prop {boolean} [cdnSubdomain]
7-
* @prop {boolean} [secureCdnSubdomain]
4+
* Defines the configuration needed for URL-related options when creating Cloudinary URL
85
* @prop {string} [cname]
96
* @prop {boolean} [secureDistribution]
107
* @prop {boolean} [privateCdn]
@@ -17,18 +14,51 @@
1714
* @prop {boolean} [analytics]
1815
*/
1916
interface IURLConfig {
20-
cdnSubdomain?: boolean;
21-
secureCdnSubdomain?: boolean;
22-
cname?: string; // User subdomain (example.cloudinary.com)
23-
secureDistribution?: boolean;
17+
/**
18+
* Replace the asset domain when secure is false
19+
* http://{cname}/{cloudName}/image/upload
20+
*/
21+
cname?: string;
22+
23+
/**
24+
* Replace the asset domain when secure is true
25+
* https://{cname}/{cloudName}/image/upload
26+
*/
27+
secureDistribution?: string;
28+
29+
/**
30+
* When Cname or secureDistribution are provided (with secure accordingly),
31+
* privateCdn removes the cloudName from the URL:
32+
*
33+
* https://{cname|secureDistribution}/image/upload
34+
* instead of
35+
* * https://{cname|secureDistribution}/{cloudName}image/upload
36+
*
37+
* When privateCdn is provided without cname or secure distribution,
38+
* it moves the cloudName from the URL to the domain:
39+
*
40+
* https://{cloudName}-res.cloudinary.com/image/upload
41+
* instead of
42+
* https://res.cloudinary.com/{cloudName}/image/upload
43+
*/
2444
privateCdn?: boolean;
45+
46+
/**
47+
* use HTTPS or HTTP
48+
*/
49+
secure?: boolean;
50+
51+
52+
/**
53+
* Whether or not to include the SDK version signature in the URL
54+
*/
55+
analytics?: boolean;
56+
2557
signUrl?: boolean;
2658
longUrlSignature?: boolean;
2759
shorten?: boolean;
2860
useRootPath?: boolean;
29-
secure?: boolean;
3061
forceVersion?: boolean;
31-
analytics?: boolean;
3262
}
3363

3464
export default IURLConfig;

src/internalConstants.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
* @private
88
*/
99
export const ALLOWED_URL_CONFIG = [
10-
'cdnSubdomain',
11-
'secureCdnSubdomain',
1210
'cname',
1311
'secureDistribution',
1412
'privateCdn',

src/url/cloudinaryURL.ts

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import ICloudinaryConfigurations from "../interfaces/Config/ICloudinaryConfigura
1212
* @param {Object} config
1313
* @param {Object} descriptor
1414
* @param {Transformation} transformation
15-
* @return {string} CloudianryURL
15+
* @return {string} CloudinaryURL
1616
*/
1717
function createCloudinaryURL(config: ICloudinaryConfigurations, descriptor?: IDescriptor, transformation?: Transformation): string {
1818
const prefix = getUrlPrefix(config.cloud.cloudName, config.url);
@@ -38,19 +38,49 @@ function createCloudinaryURL(config: ICloudinaryConfigurations, descriptor?: IDe
3838

3939
/**
4040
* Create the URL prefix for Cloudinary resources.
41+
* Available use cases
42+
* http://res.cloudinary.com/{cloudName}
43+
* https://res.cloudinary.com/{cloudName}
44+
* https://{cloudName}-res.cloudinary.com/
45+
* http://{domain}/${cloudName}
46+
* https://{domain}/${cloudName}
47+
* https://{domain}
4148
* @private
49+
*
4250
* @param {string} cloudName
4351
* @param {IURLConfig} urlConfig
4452
*/
45-
function getUrlPrefix(cloudName: string, urlConfig:IURLConfig) {
46-
// defaults
47-
const protocol = urlConfig.secure ? "https://" : "http://";
48-
const cdnPart = "";
49-
const subdomain = "res";
50-
const host = ".cloudinary.com";
51-
const path = `/${cloudName}`;
52-
53-
return [protocol, cdnPart, subdomain, host, path].join("");
53+
function getUrlPrefix(cloudName: string, urlConfig: IURLConfig) {
54+
const secure = urlConfig.secure;
55+
const privateCDN = urlConfig.privateCdn;
56+
const cname = urlConfig.cname;
57+
const secureDistribution = urlConfig.secureDistribution;
58+
59+
if (!secure && !cname) {
60+
return `http://res.cloudinary.com/${cloudName}`;
61+
}
62+
63+
if (secure && !secureDistribution && privateCDN) {
64+
return `https://${cloudName}-res.cloudinary.com`;
65+
}
66+
67+
if (secure && !secureDistribution) {
68+
return `https://res.cloudinary.com/${cloudName}`;
69+
}
70+
71+
if (secure && secureDistribution && privateCDN) {
72+
return `https://${secureDistribution}`;
73+
}
74+
75+
if (secure && secureDistribution) {
76+
return `https://${secureDistribution}/${cloudName}`;
77+
}
78+
79+
if (!secure && cname) {
80+
return `http://${cname}/${cloudName}`;
81+
} else {
82+
return 'ERROR';
83+
}
5484
}
5585

5686
/**
@@ -59,7 +89,7 @@ function getUrlPrefix(cloudName: string, urlConfig:IURLConfig) {
5989
*/
6090
function handleAssetType(descriptor: IDescriptor) {
6191
//default to image
62-
if(!descriptor || !descriptor.assetType) {
92+
if (!descriptor || !descriptor.assetType) {
6393
return 'image';
6494
}
6595

@@ -72,7 +102,7 @@ function handleAssetType(descriptor: IDescriptor) {
72102
*/
73103
function handleStorageType(descriptor: IDescriptor) {
74104
//default to upload
75-
if(!descriptor || !descriptor.storageType) {
105+
if (!descriptor || !descriptor.storageType) {
76106
return 'upload';
77107
}
78108

@@ -83,7 +113,7 @@ function handleStorageType(descriptor: IDescriptor) {
83113
* @private
84114
* @param descriptor
85115
*/
86-
function getUrlVersion(urlConfig:IURLConfig, descriptor: IDescriptor) {
116+
function getUrlVersion(urlConfig: IURLConfig, descriptor: IDescriptor) {
87117
const shouldForceVersion = urlConfig.forceVersion !== false;
88118

89119
if (descriptor.version) {

0 commit comments

Comments
 (0)