Skip to content

Commit 6214348

Browse files
authored
Merge pull request #21 from imagekit-developer/error_handling
Network error handling and SDK initilizaton error handling
2 parents 10ea634 + 4ca2120 commit 6214348

File tree

8 files changed

+146
-24
lines changed

8 files changed

+146
-24
lines changed

src/constants/errorMessages.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
export default {
2-
"MANDATORY_INITIALIZATION_MISSING" : { message : "Missing publicKey or privateKey or urlEndpoint during ImageKit initialization", help : "" },
3-
"INVALID_TRANSFORMATION_POSITION" : { message : "Invalid transformationPosition parameter", help : "" },
4-
"PRIVATE_KEY_CLIENT_SIDE" : { message : "privateKey should not be passed on the client side", help : "" },
5-
"MISSING_UPLOAD_DATA" : { message : "Missing data for upload", help : "" },
6-
"MISSING_UPLOAD_FILE_PARAMETER" : { message : "Missing file parameter for upload", help : "" },
7-
"MISSING_UPLOAD_FILENAME_PARAMETER" : { message : "Missing fileName parameter for upload", help : "" },
8-
"MISSING_AUTHENTICATION_ENDPOINT" : { message : "Missing authentication endpoint for upload", help : "" }
2+
"MANDATORY_INITIALIZATION_MISSING": { message: "Missing urlEndpoint during SDK initialization", help: "" },
3+
"INVALID_TRANSFORMATION_POSITION": { message: "Invalid transformationPosition parameter", help: "" },
4+
"PRIVATE_KEY_CLIENT_SIDE": { message: "privateKey should not be passed on the client side", help: "" },
5+
"MISSING_UPLOAD_DATA": { message: "Missing data for upload", help: "" },
6+
"MISSING_UPLOAD_FILE_PARAMETER": { message: "Missing file parameter for upload", help: "" },
7+
"MISSING_UPLOAD_FILENAME_PARAMETER": { message: "Missing fileName parameter for upload", help: "" },
8+
"MISSING_AUTHENTICATION_ENDPOINT": { message: "Missing authentication endpoint for upload", help: "" },
9+
"AUTH_ENDPOINT_TIMEOUT": { message: "The authenticationEndpoint you provided timed out in 60 seconds", help: "" },
10+
"AUTH_ENDPOINT_NETWORK_ERROR": { message: "Request to authenticationEndpoint failed due to network error", help: "" },
11+
"UPLOAD_ENDPOINT_NETWORK_ERROR": { message: "Request to ImageKit upload endpoint failed due to network error", help: "" },
912
}

src/index.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ const ImageKit = function(opts) {
1919
};
2020

2121
if (!mandatoryParametersAvailable(this.options)) {
22-
throw new Error(errorMessages.MANDATORY_INITIALIZATION_MISSING);
22+
throw(errorMessages.MANDATORY_INITIALIZATION_MISSING);
2323
}
2424

2525
if (privateKeyPassed(this.options)) {
26-
throw new Error(errorMessages.PRIVATE_KEY_CLIENT_SIDE);
26+
throw(errorMessages.PRIVATE_KEY_CLIENT_SIDE);
2727
}
2828

2929
if (!transformationUtils.validParameters(this.options)) {
30-
throw new Error(errorMessages.INVALID_TRANSFORMATION_POSITION);
30+
throw(errorMessages.INVALID_TRANSFORMATION_POSITION);
3131
}
3232

3333
/*
@@ -40,8 +40,12 @@ const ImageKit = function(opts) {
4040
/*
4141
Upload API
4242
*/
43-
this.upload = function (uploadOptions, callback) {
44-
return upload(uploadOptions, this.options, callback);
43+
this.upload = function (uploadOptions, callback, options) {
44+
var mergedOptions = {
45+
...this.options,
46+
...options
47+
};
48+
return upload(uploadOptions, mergedOptions, callback);
4549
};
4650
};
4751

src/upload/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import errorMessages from "../constants/errorMessages"
22
import respond from "../utils/respond";
33
import { request } from "../utils/request";
44

5-
export const upload = (uploadOptions, defaultOptions, callback) => {
5+
export const upload = (uploadOptions, options, callback) => {
66
if (!uploadOptions) {
77
respond(true, errorMessages.INVALID_UPLOAD_OPTIONS, callback);
88
return;
@@ -18,7 +18,7 @@ export const upload = (uploadOptions, defaultOptions, callback) => {
1818
return;
1919
}
2020

21-
if (!defaultOptions.authenticationEndpoint) {
21+
if (!options.authenticationEndpoint) {
2222
respond(true, errorMessages.MISSING_AUTHENTICATION_ENDPOINT, callback);
2323
return;
2424
}
@@ -27,7 +27,7 @@ export const upload = (uploadOptions, defaultOptions, callback) => {
2727
for (var i in uploadOptions) {
2828
formData.append(i, uploadOptions[i]);
2929
}
30-
formData.append("publicKey", defaultOptions.publicKey)
30+
formData.append("publicKey", options.publicKey)
3131

32-
request(formData, defaultOptions, callback);
32+
request(formData, options, callback);
3333
};

src/url/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,5 @@ export const url = (urlOpts, defaultOptions) => {
2424
function validOptions(opts) {
2525
if (!opts.urlEndpoint) return false;
2626

27-
if (!transformationUtils.validParameters(opts)) return false;
28-
2927
return true;
3028
}

src/utils/request.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
export const request = (formData, defaultOptions, callback) => {
2-
generateSignatureToken(defaultOptions, function (err, signaturObj) {
1+
import respond from "../utils/respond";
2+
import errorMessages from "../constants/errorMessages"
3+
4+
export const request = (formData, options, callback) => {
5+
generateSignatureToken(options, function (err, signaturObj) {
36
if (err) {
47
if (typeof callback != "function") return;
5-
callback(err);
8+
callback(err, null);
69
return;
710
} else {
811
formData.append("signature", signaturObj.signature || "");
@@ -21,14 +24,19 @@ export const request = (formData, defaultOptions, callback) => {
2124
});
2225
}
2326

24-
export const generateSignatureToken = (defaultOptions, callback) => {
27+
export const generateSignatureToken = (options, callback) => {
2528
var xhr = new XMLHttpRequest();
2629
xhr.timeout = 60000;
27-
xhr.open('GET', defaultOptions.authenticationEndpoint);
30+
xhr.open('GET', options.authenticationEndpoint);
2831
xhr.ontimeout = function (e) {
2932
if (typeof callback != "function") return;
30-
callback("The authenticationEndpoint you provided timed out in 60 seconds");
33+
respond(true, errorMessages.AUTH_ENDPOINT_TIMEOUT, callback);
34+
return;
3135
};
36+
xhr.onerror = function() {
37+
respond(true, errorMessages.AUTH_ENDPOINT_NETWORK_ERROR, callback);
38+
return;
39+
}
3240
xhr.onload = function () {
3341
if (xhr.status === 200) {
3442
try {
@@ -62,6 +70,10 @@ export const generateSignatureToken = (defaultOptions, callback) => {
6270
export const uploadFile = (formData, callback) => {
6371
var uploadFileXHR = new XMLHttpRequest();
6472
uploadFileXHR.open('POST', 'https://upload.imagekit.io/api/v1/files/upload');
73+
uploadFileXHR.onerror = function() {
74+
respond(true, errorMessages.UPLOAD_ENDPOINT_NETWORK_ERROR, callback);
75+
return;
76+
}
6577
uploadFileXHR.onload = function () {
6678
if (uploadFileXHR.status === 200) {
6779
if (typeof callback != "function") return;

test/initialization.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ const ImageKit = require(".."); // This will automatically pick main module (cjs
77
describe("Initialization checks", function () {
88
var imagekit = new ImageKit(initializationParams);
99

10+
it('should throw error', function () {
11+
try {
12+
new ImageKit({});
13+
} catch(err) {
14+
expect(err.message).to.be.equal('Missing urlEndpoint during SDK initialization');
15+
}
16+
});
17+
1018
it('should have options object', function () {
1119
expect(imagekit.options).to.be.an('object');
1220
});

test/upload.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,44 @@ describe("File upload", function () {
103103
sinon.assert.calledWith(callback, { help: "", message: "Missing file parameter for upload" }, null);
104104
});
105105

106+
it('Auth endpoint network error handling', function () {
107+
const fileOptions = {
108+
fileName: "test_file_name",
109+
file: "test_file"
110+
};
111+
112+
var callback = sinon.spy();
113+
114+
imagekit.upload(fileOptions, callback, {
115+
authenticationEndpoint : "https://does-not-exist-sdfsdf/aut"
116+
});
117+
118+
expect(server.requests.length).to.be.equal(1);
119+
120+
// Simulate network error on authentication endpoint
121+
server.requests[0].error();
122+
sinon.assert.calledWith(callback, { message: "Request to authenticationEndpoint failed due to network error", help: "" }, null);
123+
});
124+
125+
it('Upload endpoint network error handling', function () {
126+
const fileOptions = {
127+
fileName: "test_file_name",
128+
file: "test_file"
129+
};
130+
131+
var callback = sinon.spy();
132+
133+
imagekit.upload(fileOptions, callback);
134+
135+
expect(server.requests.length).to.be.equal(1);
136+
successSignature();
137+
expect(server.requests.length).to.be.equal(2);
138+
139+
// Simulate network error on upload API
140+
server.requests[1].error();
141+
sinon.assert.calledWith(callback, { message: "Request to ImageKit upload endpoint failed due to network error", help: "" }, null);
142+
});
143+
106144
it('Boolean handling', function () {
107145
const fileOptions = {
108146
fileName: "test_file_name",
@@ -325,6 +363,54 @@ describe("File upload", function () {
325363
expect(callback.calledOnce).to.be.true;
326364
sinon.assert.calledWith(callback, null, uploadSuccessResponseObj);
327365
});
366+
367+
it('Overriding public key and authentication endpoint', function () {
368+
var newAuthEndpoint = "http://test/auth-override";
369+
var newPublicKey = "override_public_key";
370+
371+
const fileOptions = {
372+
fileName: "test_file_name",
373+
file: "https://ik.imagekit.io/remote-url.jpg"
374+
};
375+
376+
var callback = sinon.spy();
377+
378+
imagekit.upload(fileOptions, callback, {
379+
authenticationEndpoint: newAuthEndpoint,
380+
publicKey: newPublicKey
381+
});
382+
383+
expect(server.requests.length).to.be.equal(1);
384+
server.respondWith("GET", newAuthEndpoint,
385+
[
386+
200,
387+
{ "Content-Type": "application/json" },
388+
JSON.stringify({
389+
signature: "override_test_signature",
390+
expire: 123123,
391+
token: "override_test_token"
392+
})
393+
]);
394+
server.respond();
395+
expect(server.requests.length).to.be.equal(2);
396+
successUploadResponse();
397+
398+
var arg = server.requests[1].requestBody;
399+
expect(arg.get('file')).to.be.equal("https://ik.imagekit.io/remote-url.jpg");
400+
expect(arg.get('fileName')).to.be.equal("test_file_name");
401+
expect(arg.get('token')).to.be.equal("override_test_token");
402+
expect(arg.get('expire')).to.be.equal("123123");
403+
expect(arg.get('signature')).to.be.equal("override_test_signature");
404+
expect(arg.get('publicKey')).to.be.equal('override_public_key');
405+
expect(arg.get('tags')).to.be.equal(undefined);
406+
expect(arg.get('isPrivateFile')).to.be.equal(undefined);
407+
expect(arg.get('useUniqueFileName')).to.be.equal(undefined);
408+
expect(arg.get('customCoordinates')).to.be.equal(undefined);
409+
expect(arg.get('responseFields')).to.be.equal(undefined);
410+
411+
expect(callback.calledOnce).to.be.true;
412+
sinon.assert.calledWith(callback, null, uploadSuccessResponseObj);
413+
});
328414
});
329415

330416

test/url-generation.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ describe("URL generation", function () {
2525
expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg?ik-sdk-version=javascript-${pkg.version}`);
2626
});
2727

28+
it('Undefined parameters with path', function () {
29+
const url = imagekit.url({
30+
path: "/test_path_alt.jpg",
31+
transformation: undefined,
32+
transformationPosition: undefined,
33+
src: undefined,
34+
});
35+
36+
expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg?ik-sdk-version=javascript-${pkg.version}`);
37+
});
38+
2839
it('should generate the correct url with path param', function () {
2940
const url = imagekit.url({
3041
path: "/test_path.jpg",

0 commit comments

Comments
 (0)