From 82f49560f446bd9652187b94b8ec8f9af70c1d81 Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Wed, 21 Feb 2024 14:38:47 +0530 Subject: [PATCH 01/12] added encoding logic --- libs/url/builder.ts | 11 ++++++++++- package.json | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/libs/url/builder.ts b/libs/url/builder.ts index 5aea385..d275e9d 100644 --- a/libs/url/builder.ts +++ b/libs/url/builder.ts @@ -24,6 +24,15 @@ const SIGNATURE_PARAMETER: string = "ik-s"; const TIMESTAMP_PARAMETER: string = "ik-t"; const DEFAULT_TIMESTAMP: string = "9999999999"; +//used to check if special char is present in string (you'll need to encode it to utf-8 if it does) +const hasMoreThanAscii = (str = '') => { + return str.split('').some((char) => char.charCodeAt(0) > 127); +} + +const encodeStringIfRequired = (str = '') => { + return hasMoreThanAscii(str) ? encodeURI(str) : str; +} + const buildURL = function (opts: FinalUrlOptions): string { //Create correct query parameters var parsedURL: UrlWithStringQuery; @@ -98,7 +107,7 @@ const buildURL = function (opts: FinalUrlOptions): string { var urlSignature = getSignature({ privateKey: opts.privateKey, - url: intermediateURL, + url: encodeStringIfRequired(intermediateURL), urlEndpoint: opts.urlEndpoint, expiryTimestamp: expiryTimestamp, }); diff --git a/package.json b/package.json index dd24015..3754b8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "imagekit", - "version": "5.0.0", + "version": "5.0.1", "description": "Offical NodeJS SDK for ImageKit.io integration", "main": "./dist/index.js", "types": "./dist/index.d.ts", From df3f756011f5c4ee752719b599472863bf02b712 Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Fri, 23 Feb 2024 03:08:03 +0530 Subject: [PATCH 02/12] added test case for diacritic --- tests/url-generation.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/url-generation.js b/tests/url-generation.js index 4664d16..dacbbd7 100644 --- a/tests/url-generation.js +++ b/tests/url-generation.js @@ -59,6 +59,17 @@ describe("URL generation", function () { expect(url).includes(`ik-s=`); }); + it('Signed URL with expireSeconds and é in url', function () { + const url = imagekit.url({ + path: "/test_é_path_alt.jpg", + signed: true, + expireSeconds: 100 + }); + + expect(url).includes(`https://ik.imagekit.io/test_url_endpoint/test_é_path_alt.jpg`); + expect(url).includes(`ik-s=`); + }); + it('should generate the correct url with path param', function () { const url = imagekit.url({ path: "/test_path.jpg", From 80c47a1b46d4187a682e9eb931c4f9d00ced73c1 Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Fri, 23 Feb 2024 03:27:48 +0530 Subject: [PATCH 03/12] added test case for diacritic --- libs/url/builder.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/url/builder.ts b/libs/url/builder.ts index d275e9d..4b38d08 100644 --- a/libs/url/builder.ts +++ b/libs/url/builder.ts @@ -25,11 +25,11 @@ const TIMESTAMP_PARAMETER: string = "ik-t"; const DEFAULT_TIMESTAMP: string = "9999999999"; //used to check if special char is present in string (you'll need to encode it to utf-8 if it does) -const hasMoreThanAscii = (str = '') => { +const hasMoreThanAscii = (str: string) => { return str.split('').some((char) => char.charCodeAt(0) > 127); } -const encodeStringIfRequired = (str = '') => { +const encodeStringIfRequired = (str: string) => { return hasMoreThanAscii(str) ? encodeURI(str) : str; } From 547d11289e45cd67f963d359e90aada2258ef7d1 Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Wed, 28 Feb 2024 01:08:01 +0530 Subject: [PATCH 04/12] added test case for diacritic --- tests/url-generation.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/url-generation.js b/tests/url-generation.js index dacbbd7..45d5182 100644 --- a/tests/url-generation.js +++ b/tests/url-generation.js @@ -68,6 +68,7 @@ describe("URL generation", function () { expect(url).includes(`https://ik.imagekit.io/test_url_endpoint/test_é_path_alt.jpg`); expect(url).includes(`ik-s=`); + expect(url).includes(`ik-t=`); }); it('should generate the correct url with path param', function () { From 07785f423a568018234b20ca44df01d175839c6e Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Thu, 29 Feb 2024 14:22:01 +0530 Subject: [PATCH 05/12] added test case and updated logic --- libs/url/builder.ts | 17 ++++++++++++++++- tests/url-generation.js | 25 ++++++++++++++++++++----- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/libs/url/builder.ts b/libs/url/builder.ts index 4b38d08..b05b917 100644 --- a/libs/url/builder.ts +++ b/libs/url/builder.ts @@ -29,8 +29,22 @@ const hasMoreThanAscii = (str: string) => { return str.split('').some((char) => char.charCodeAt(0) > 127); } +const customEncodeURIComponent = (str: string) => { + const parts = str.includes("?") ? str.split("?")[0] : str; + const segments = parts.split("/"); + const encodedSegments = segments.map((segment) => { + if (segment === "/") return "/"; + if(segment.includes('https:') || segment.includes('http:') || segment.includes('tr:')) + return segment; + return encodeURIComponent(segment); + }); + return str.includes("?") ? `${encodedSegments.join("/")}?${str.split("?")[1]}` : encodedSegments.join("/"); + // return str.includes("?") ? `${encodeURI(parts)}?${str.split("?")[1]}` : encodeURI(parts); +}; + const encodeStringIfRequired = (str: string) => { - return hasMoreThanAscii(str) ? encodeURI(str) : str; + console.log({str}) + return hasMoreThanAscii(str) ? customEncodeURIComponent(str) : str; } const buildURL = function (opts: FinalUrlOptions): string { @@ -170,6 +184,7 @@ function getSignatureTimestamp(seconds: number): string { } function getSignature(opts: any) { + console.log({opts}) if (!opts.privateKey || !opts.url || !opts.urlEndpoint) return ""; var stringToSign = opts.url.replace(urlFormatter.addTrailingSlash(opts.urlEndpoint), "") + opts.expiryTimestamp; return crypto.createHmac("sha1", opts.privateKey).update(stringToSign).digest("hex"); diff --git a/tests/url-generation.js b/tests/url-generation.js index 45d5182..aa240e5 100644 --- a/tests/url-generation.js +++ b/tests/url-generation.js @@ -59,18 +59,33 @@ describe("URL generation", function () { expect(url).includes(`ik-s=`); }); - it('Signed URL with expireSeconds and é in url', function () { + it('Signed URL with é in filename', function () { const url = imagekit.url({ path: "/test_é_path_alt.jpg", signed: true, - expireSeconds: 100 }); + expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_é_path_alt.jpg?ik-s=09a329f06a5106a8b9c43de8fb6a64948fff7c59`); + }); - expect(url).includes(`https://ik.imagekit.io/test_url_endpoint/test_é_path_alt.jpg`); - expect(url).includes(`ik-s=`); - expect(url).includes(`ik-t=`); + it('Signed URL with é in filename and path', function () { + const url = imagekit.url({ + path: "/aéb/test_é_path_alt.jpg", + signed: true, + }); + expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?ik-s=fca91582138ac65694425d52f0710b7ae2c3d7cf`); }); + it('Signed URL with é in filename, path and query', function () { + const url = imagekit.url({ + path: "/aéb/test_é_path_alt.jpg", + signed: true, + transformation: [ { raw: "l-text,i-Imagekité,fs-50,l-end"}] + }); + console.log({url}) + expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekité,fs-50,l-end/aéb/test_é_path_alt.jpg?ik-s=38539311889a0721b46ebe30b5f297773d01d960`); + }); + + it('should generate the correct url with path param', function () { const url = imagekit.url({ path: "/test_path.jpg", From b146d7323c2bfee7db693483774d6752b9d37b32 Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Thu, 29 Feb 2024 14:28:49 +0530 Subject: [PATCH 06/12] added test case and updated logic --- libs/url/builder.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/libs/url/builder.ts b/libs/url/builder.ts index b05b917..9f3f000 100644 --- a/libs/url/builder.ts +++ b/libs/url/builder.ts @@ -39,11 +39,9 @@ const customEncodeURIComponent = (str: string) => { return encodeURIComponent(segment); }); return str.includes("?") ? `${encodedSegments.join("/")}?${str.split("?")[1]}` : encodedSegments.join("/"); - // return str.includes("?") ? `${encodeURI(parts)}?${str.split("?")[1]}` : encodeURI(parts); }; const encodeStringIfRequired = (str: string) => { - console.log({str}) return hasMoreThanAscii(str) ? customEncodeURIComponent(str) : str; } @@ -184,7 +182,6 @@ function getSignatureTimestamp(seconds: number): string { } function getSignature(opts: any) { - console.log({opts}) if (!opts.privateKey || !opts.url || !opts.urlEndpoint) return ""; var stringToSign = opts.url.replace(urlFormatter.addTrailingSlash(opts.urlEndpoint), "") + opts.expiryTimestamp; return crypto.createHmac("sha1", opts.privateKey).update(stringToSign).digest("hex"); From 19041c249aae9a771b40e12a51772ae6bd23cbd6 Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Thu, 29 Feb 2024 14:32:09 +0530 Subject: [PATCH 07/12] added test case and updated logic --- tests/url-generation.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/url-generation.js b/tests/url-generation.js index aa240e5..f29d528 100644 --- a/tests/url-generation.js +++ b/tests/url-generation.js @@ -75,16 +75,28 @@ describe("URL generation", function () { expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?ik-s=fca91582138ac65694425d52f0710b7ae2c3d7cf`); }); - it('Signed URL with é in filename, path and query', function () { + it('Signed URL with é in filename, path and transformation as path', function () { const url = imagekit.url({ path: "/aéb/test_é_path_alt.jpg", signed: true, - transformation: [ { raw: "l-text,i-Imagekité,fs-50,l-end"}] + transformation: [ { raw: "l-text,i-Imagekité,fs-50,l-end"}], + transformationPosition: "path" }); console.log({url}) expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekité,fs-50,l-end/aéb/test_é_path_alt.jpg?ik-s=38539311889a0721b46ebe30b5f297773d01d960`); }); + it('Signed URL with é in filename, path and transformation as query', function () { + const url = imagekit.url({ + path: "/aéb/test_é_path_alt.jpg", + signed: true, + transformation: [ { raw: "l-text,i-Imagekité,fs-50,l-end"}], + transformationPosition: "query" + }); + console.log({url}) + expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?tr=l-text%2Ci-Imagekit%C3%A9%2Cfs-50%2Cl-end&ik-s=0b0107144b34e3b33264c0cec1d29ec98d46cbbb`); + }); + it('should generate the correct url with path param', function () { const url = imagekit.url({ From 730f700f1d8255f6f8dd81c29bedc06982f93247 Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Thu, 29 Feb 2024 14:53:31 +0530 Subject: [PATCH 08/12] added test case and updated logic --- libs/url/builder.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/url/builder.ts b/libs/url/builder.ts index 9f3f000..f1ca443 100644 --- a/libs/url/builder.ts +++ b/libs/url/builder.ts @@ -33,7 +33,6 @@ const customEncodeURIComponent = (str: string) => { const parts = str.includes("?") ? str.split("?")[0] : str; const segments = parts.split("/"); const encodedSegments = segments.map((segment) => { - if (segment === "/") return "/"; if(segment.includes('https:') || segment.includes('http:') || segment.includes('tr:')) return segment; return encodeURIComponent(segment); From 30cfe26cf656289bacfe208c428a4149f2858d5e Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Fri, 1 Mar 2024 01:19:58 +0530 Subject: [PATCH 09/12] improve test case --- libs/url/builder.ts | 14 ++---- tests/url-generation.js | 101 ++++++++++++++++++++++++++++------------ 2 files changed, 75 insertions(+), 40 deletions(-) diff --git a/libs/url/builder.ts b/libs/url/builder.ts index f1ca443..bab2e37 100644 --- a/libs/url/builder.ts +++ b/libs/url/builder.ts @@ -30,17 +30,11 @@ const hasMoreThanAscii = (str: string) => { } const customEncodeURIComponent = (str: string) => { - const parts = str.includes("?") ? str.split("?")[0] : str; - const segments = parts.split("/"); - const encodedSegments = segments.map((segment) => { - if(segment.includes('https:') || segment.includes('http:') || segment.includes('tr:')) - return segment; - return encodeURIComponent(segment); - }); - return str.includes("?") ? `${encodedSegments.join("/")}?${str.split("?")[1]}` : encodedSegments.join("/"); + const url = new URL(str); + return url.toString(); }; -const encodeStringIfRequired = (str: string) => { +export const encodeStringIfRequired = (str: string) => { return hasMoreThanAscii(str) ? customEncodeURIComponent(str) : str; } @@ -180,7 +174,7 @@ function getSignatureTimestamp(seconds: number): string { return String(currentTimestamp + sec); } -function getSignature(opts: any) { +export function getSignature(opts: any) { if (!opts.privateKey || !opts.url || !opts.urlEndpoint) return ""; var stringToSign = opts.url.replace(urlFormatter.addTrailingSlash(opts.urlEndpoint), "") + opts.expiryTimestamp; return crypto.createHmac("sha1", opts.privateKey).update(stringToSign).digest("hex"); diff --git a/tests/url-generation.js b/tests/url-generation.js index f29d528..024e351 100644 --- a/tests/url-generation.js +++ b/tests/url-generation.js @@ -3,6 +3,7 @@ const pkg = require("../package.json"); const expect = chai.expect; const initializationParams = require("./data").initializationParams import ImageKit from "../index"; +import { encodeStringIfRequired, getSignature } from "../libs/url/builder"; var imagekit = new ImageKit(initializationParams); describe("URL generation", function () { @@ -59,42 +60,82 @@ describe("URL generation", function () { expect(url).includes(`ik-s=`); }); - it('Signed URL with é in filename', function () { - const url = imagekit.url({ - path: "/test_é_path_alt.jpg", - signed: true, - }); - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_é_path_alt.jpg?ik-s=09a329f06a5106a8b9c43de8fb6a64948fff7c59`); + it("Signed URL with é in filename", function () { + const encodedUrl = encodeStringIfRequired("https://ik.imagekit.io/test_url_endpoint/test_é_path_alt.jpg"); + expect(encodedUrl).equal("https://ik.imagekit.io/test_url_endpoint/test_%C3%A9_path_alt.jpg"); + const signature = getSignature({ + privateKey: "test_private_key", + url: encodedUrl, + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + expiryTimestamp: "9999999999", + }); + const url = imagekit.url({ + path: "/test_é_path_alt.jpg", + signed: true, + }); + expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_é_path_alt.jpg?ik-s=09a329f06a5106a8b9c43de8fb6a64948fff7c59`); + expect(url).includes(`ik-s=${signature}`); }); - it('Signed URL with é in filename and path', function () { - const url = imagekit.url({ - path: "/aéb/test_é_path_alt.jpg", - signed: true, - }); - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?ik-s=fca91582138ac65694425d52f0710b7ae2c3d7cf`); + it("Signed URL with é in filename and path", function () { + const encodedUrl = encodeStringIfRequired("https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg"); + expect(encodedUrl).equal("https://ik.imagekit.io/test_url_endpoint/a%C3%A9b/test_%C3%A9_path_alt.jpg"); + const signature = getSignature({ + privateKey: "test_private_key", + url: encodedUrl, + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + expiryTimestamp: "9999999999", + }); + const url = imagekit.url({ + path: "/aéb/test_é_path_alt.jpg", + signed: true, + }); + expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?ik-s=fca91582138ac65694425d52f0710b7ae2c3d7cf`); + expect(url).includes(`ik-s=${signature}`); }); - it('Signed URL with é in filename, path and transformation as path', function () { - const url = imagekit.url({ - path: "/aéb/test_é_path_alt.jpg", - signed: true, - transformation: [ { raw: "l-text,i-Imagekité,fs-50,l-end"}], - transformationPosition: "path" - }); - console.log({url}) - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekité,fs-50,l-end/aéb/test_é_path_alt.jpg?ik-s=38539311889a0721b46ebe30b5f297773d01d960`); + it("Signed URL with é in filename, path and transformation as path", function () { + const encodedUrl = encodeStringIfRequired("https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekité,fs-50,l-end/aéb/test_é_path_alt.jpg"); + expect(encodedUrl).equal("https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekit%C3%A9,fs-50,l-end/a%C3%A9b/test_%C3%A9_path_alt.jpg"); + const signature = getSignature({ + privateKey: "test_private_key", + url: encodedUrl, + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + expiryTimestamp: "9999999999", + }); + + const url = imagekit.url({ + path: "/aéb/test_é_path_alt.jpg", + signed: true, + transformation: [{ raw: "l-text,i-Imagekité,fs-50,l-end" }], + transformationPosition: "path", + }); + console.log({ url, signature }); + expect(url).equal( + `https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekité,fs-50,l-end/aéb/test_é_path_alt.jpg?ik-s=d7f5aec0b7a766556dfc280bdf2e3466877d025f` + ); + expect(url).includes(`ik-s=${signature}`); }); - it('Signed URL with é in filename, path and transformation as query', function () { - const url = imagekit.url({ - path: "/aéb/test_é_path_alt.jpg", - signed: true, - transformation: [ { raw: "l-text,i-Imagekité,fs-50,l-end"}], - transformationPosition: "query" - }); - console.log({url}) - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?tr=l-text%2Ci-Imagekit%C3%A9%2Cfs-50%2Cl-end&ik-s=0b0107144b34e3b33264c0cec1d29ec98d46cbbb`); + it("Signed URL with é in filename, path and transformation as query", function () { + const encodedUrl = encodeStringIfRequired("https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?tr=l-text%2Ci-Imagekité%2Cfs-50%2Cl-end"); + expect(encodedUrl).equal("https://ik.imagekit.io/test_url_endpoint/a%C3%A9b/test_%C3%A9_path_alt.jpg?tr=l-text%2Ci-Imagekit%C3%A9%2Cfs-50%2Cl-end"); + const signature = getSignature({ + privateKey: "test_private_key", + url: encodedUrl, + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + expiryTimestamp: "9999999999", + }); + const url = imagekit.url({ + path: "/aéb/test_é_path_alt.jpg", + signed: true, + transformation: [{ raw: "l-text,i-Imagekité,fs-50,l-end" }], + transformationPosition: "query", + }); + expect(url).equal( + `https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?tr=l-text%2Ci-Imagekit%C3%A9%2Cfs-50%2Cl-end&ik-s=0b0107144b34e3b33264c0cec1d29ec98d46cbbb` + ); + expect(url).includes(`ik-s=${signature}`); }); From feea5ab5383b224f72525423c3629cffd96e9a0d Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Fri, 1 Mar 2024 01:28:16 +0530 Subject: [PATCH 10/12] improve test case --- tests/url-generation.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/url-generation.js b/tests/url-generation.js index 024e351..322d957 100644 --- a/tests/url-generation.js +++ b/tests/url-generation.js @@ -110,7 +110,6 @@ describe("URL generation", function () { transformation: [{ raw: "l-text,i-Imagekité,fs-50,l-end" }], transformationPosition: "path", }); - console.log({ url, signature }); expect(url).equal( `https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekité,fs-50,l-end/aéb/test_é_path_alt.jpg?ik-s=d7f5aec0b7a766556dfc280bdf2e3466877d025f` ); From 3ab2d0bac44af87b5b2275d27e523dc615980193 Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Fri, 1 Mar 2024 12:33:32 +0530 Subject: [PATCH 11/12] foramtted the code --- libs/url/builder.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libs/url/builder.ts b/libs/url/builder.ts index bab2e37..0a123c9 100644 --- a/libs/url/builder.ts +++ b/libs/url/builder.ts @@ -29,13 +29,8 @@ const hasMoreThanAscii = (str: string) => { return str.split('').some((char) => char.charCodeAt(0) > 127); } -const customEncodeURIComponent = (str: string) => { - const url = new URL(str); - return url.toString(); -}; - export const encodeStringIfRequired = (str: string) => { - return hasMoreThanAscii(str) ? customEncodeURIComponent(str) : str; + return hasMoreThanAscii(str) ? new URL(str).toString() : str; } const buildURL = function (opts: FinalUrlOptions): string { From 7195b317634bf5b5625e4113223fc5dfda125040 Mon Sep 17 00:00:00 2001 From: ANKUR DWIVEDI Date: Tue, 5 Mar 2024 14:16:43 +0530 Subject: [PATCH 12/12] updated test case --- libs/url/builder.ts | 9 +++++++-- tests/url-generation.js | 32 ++++++++++++++++---------------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/libs/url/builder.ts b/libs/url/builder.ts index 0a123c9..68cb536 100644 --- a/libs/url/builder.ts +++ b/libs/url/builder.ts @@ -29,8 +29,12 @@ const hasMoreThanAscii = (str: string) => { return str.split('').some((char) => char.charCodeAt(0) > 127); } +const customEncodeURI = (str: string) => { + return str.includes("?") ? `${encodeURI(str.split("?")[0])}?${str.split("?")[1]}` : encodeURI(str); +}; + export const encodeStringIfRequired = (str: string) => { - return hasMoreThanAscii(str) ? new URL(str).toString() : str; + return hasMoreThanAscii(str) ? customEncodeURI(str) : str; } const buildURL = function (opts: FinalUrlOptions): string { @@ -107,7 +111,7 @@ const buildURL = function (opts: FinalUrlOptions): string { var urlSignature = getSignature({ privateKey: opts.privateKey, - url: encodeStringIfRequired(intermediateURL), + url: intermediateURL, urlEndpoint: opts.urlEndpoint, expiryTimestamp: expiryTimestamp, }); @@ -172,6 +176,7 @@ function getSignatureTimestamp(seconds: number): string { export function getSignature(opts: any) { if (!opts.privateKey || !opts.url || !opts.urlEndpoint) return ""; var stringToSign = opts.url.replace(urlFormatter.addTrailingSlash(opts.urlEndpoint), "") + opts.expiryTimestamp; + stringToSign = encodeStringIfRequired(stringToSign); return crypto.createHmac("sha1", opts.privateKey).update(stringToSign).digest("hex"); } diff --git a/tests/url-generation.js b/tests/url-generation.js index 322d957..4e946a4 100644 --- a/tests/url-generation.js +++ b/tests/url-generation.js @@ -61,11 +61,12 @@ describe("URL generation", function () { }); it("Signed URL with é in filename", function () { - const encodedUrl = encodeStringIfRequired("https://ik.imagekit.io/test_url_endpoint/test_é_path_alt.jpg"); + const testURL = "https://ik.imagekit.io/test_url_endpoint/test_é_path_alt.jpg"; + const encodedUrl = encodeStringIfRequired(testURL); expect(encodedUrl).equal("https://ik.imagekit.io/test_url_endpoint/test_%C3%A9_path_alt.jpg"); const signature = getSignature({ privateKey: "test_private_key", - url: encodedUrl, + url: testURL, urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", expiryTimestamp: "9999999999", }); @@ -73,16 +74,16 @@ describe("URL generation", function () { path: "/test_é_path_alt.jpg", signed: true, }); - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_é_path_alt.jpg?ik-s=09a329f06a5106a8b9c43de8fb6a64948fff7c59`); - expect(url).includes(`ik-s=${signature}`); + expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_é_path_alt.jpg?ik-s=${signature}`); }); it("Signed URL with é in filename and path", function () { - const encodedUrl = encodeStringIfRequired("https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg"); + const testURL = "https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg"; + const encodedUrl = encodeStringIfRequired(testURL); expect(encodedUrl).equal("https://ik.imagekit.io/test_url_endpoint/a%C3%A9b/test_%C3%A9_path_alt.jpg"); const signature = getSignature({ privateKey: "test_private_key", - url: encodedUrl, + url: testURL, urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", expiryTimestamp: "9999999999", }); @@ -90,16 +91,16 @@ describe("URL generation", function () { path: "/aéb/test_é_path_alt.jpg", signed: true, }); - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?ik-s=fca91582138ac65694425d52f0710b7ae2c3d7cf`); - expect(url).includes(`ik-s=${signature}`); + expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?ik-s=${signature}`); }); it("Signed URL with é in filename, path and transformation as path", function () { - const encodedUrl = encodeStringIfRequired("https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekité,fs-50,l-end/aéb/test_é_path_alt.jpg"); + const testURL = "https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekité,fs-50,l-end/aéb/test_é_path_alt.jpg"; + const encodedUrl = encodeStringIfRequired(testURL); expect(encodedUrl).equal("https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekit%C3%A9,fs-50,l-end/a%C3%A9b/test_%C3%A9_path_alt.jpg"); const signature = getSignature({ privateKey: "test_private_key", - url: encodedUrl, + url: testURL, urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", expiryTimestamp: "9999999999", }); @@ -111,17 +112,17 @@ describe("URL generation", function () { transformationPosition: "path", }); expect(url).equal( - `https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekité,fs-50,l-end/aéb/test_é_path_alt.jpg?ik-s=d7f5aec0b7a766556dfc280bdf2e3466877d025f` + `https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Imagekité,fs-50,l-end/aéb/test_é_path_alt.jpg?ik-s=${signature}` ); - expect(url).includes(`ik-s=${signature}`); }); it("Signed URL with é in filename, path and transformation as query", function () { - const encodedUrl = encodeStringIfRequired("https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?tr=l-text%2Ci-Imagekité%2Cfs-50%2Cl-end"); + const testURL = "https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?tr=l-text%2Ci-Imagekit%C3%A9%2Cfs-50%2Cl-end"; + const encodedUrl = encodeStringIfRequired(testURL); expect(encodedUrl).equal("https://ik.imagekit.io/test_url_endpoint/a%C3%A9b/test_%C3%A9_path_alt.jpg?tr=l-text%2Ci-Imagekit%C3%A9%2Cfs-50%2Cl-end"); const signature = getSignature({ privateKey: "test_private_key", - url: encodedUrl, + url: testURL, urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", expiryTimestamp: "9999999999", }); @@ -132,9 +133,8 @@ describe("URL generation", function () { transformationPosition: "query", }); expect(url).equal( - `https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?tr=l-text%2Ci-Imagekit%C3%A9%2Cfs-50%2Cl-end&ik-s=0b0107144b34e3b33264c0cec1d29ec98d46cbbb` + `https://ik.imagekit.io/test_url_endpoint/aéb/test_é_path_alt.jpg?tr=l-text%2Ci-Imagekit%C3%A9%2Cfs-50%2Cl-end&ik-s=${signature}` ); - expect(url).includes(`ik-s=${signature}`); });