Skip to content

Commit 0d0fa7b

Browse files
jhorbulykandrew-coleman
authored andcommitted
Add URL/URI Helper Functions (#357)
* Add URL/URI Helper Functions * Catch URIErrors from URL helper functions.
1 parent 00d36d0 commit 0d0fa7b

File tree

15 files changed

+231
-2
lines changed

15 files changed

+231
-2
lines changed

docs/string-functions.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,3 +293,39 @@ Converts base 64 encoded bytes to a string, using a UTF-8 Unicode codepage.
293293
__Examples__
294294

295295
- `$base64decode("bXl1c2VyOm15cGFzcw==")` => `"myuser:mypass"`
296+
297+
## `$encodeUrlComponent()`
298+
__Signature:__ `$encodeUrlComponent(str)`
299+
300+
Encodes a Uniform Resource Locator (URL) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.
301+
302+
__Examples__
303+
304+
- `$encodeUrlComponent("?x=test")` => `"%3Fx%3Dtest"`
305+
306+
## `$encodeUrl()`
307+
__Signature:__ `$encodeUrl(str)`
308+
309+
Encodes a Uniform Resource Locator (URL) by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.
310+
311+
__Examples__
312+
313+
- `$encodeUrl("https://mozilla.org/?x=шеллы")` => `"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"`
314+
315+
## `$decodeUrlComponent()`
316+
__Signature:__ `$decodeUrlComponent(str)`
317+
318+
Decodes a Uniform Resource Locator (URL) component previously created by encodeUrlComponent.
319+
320+
__Examples__
321+
322+
- `$decodeUrlComponent("%3Fx%3Dtest")` => `"?x=test"`
323+
324+
## `$decodeUrl()`
325+
__Signature:__ `$decodeUrl(str)`
326+
327+
Decodes a Uniform Resource Locator (URL) previously created by encodeUrl.
328+
329+
__Examples__
330+
331+
- `$decodeUrl("https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B")` => `"https://mozilla.org/?x=шеллы"`

src/functions.js

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,110 @@ const functions = (() => {
580580
return atob(str);
581581
}
582582

583+
/**
584+
* Encode a string into a component for a url
585+
* @param {String} str - String to encode
586+
* @returns {string} Encoded string
587+
*/
588+
function encodeUrlComponent(str) {
589+
// undefined inputs always return undefined
590+
if (typeof str === 'undefined') {
591+
return undefined;
592+
}
593+
594+
// Catch URIErrors when URI sequence is malformed
595+
var returnVal;
596+
try {
597+
returnVal = encodeURIComponent(str);
598+
} catch (e) {
599+
throw {
600+
code: "D3140",
601+
stack: (new Error()).stack,
602+
value: str,
603+
functionName: "encodeUrlComponent"
604+
};
605+
}
606+
return returnVal;
607+
}
608+
609+
/**
610+
* Encode a string into a url
611+
* @param {String} str - String to encode
612+
* @returns {string} Encoded string
613+
*/
614+
function encodeUrl(str) {
615+
// undefined inputs always return undefined
616+
if (typeof str === 'undefined') {
617+
return undefined;
618+
}
619+
620+
// Catch URIErrors when URI sequence is malformed
621+
var returnVal;
622+
try {
623+
returnVal = encodeURI(str);
624+
} catch (e) {
625+
throw {
626+
code: "D3140",
627+
stack: (new Error()).stack,
628+
value: str,
629+
functionName: "encodeUrl"
630+
};
631+
}
632+
return returnVal;
633+
}
634+
635+
/**
636+
* Decode a string from a component for a url
637+
* @param {String} str - String to decode
638+
* @returns {string} Decoded string
639+
*/
640+
function decodeUrlComponent(str) {
641+
// undefined inputs always return undefined
642+
if (typeof str === 'undefined') {
643+
return undefined;
644+
}
645+
646+
// Catch URIErrors when URI sequence is malformed
647+
var returnVal;
648+
try {
649+
returnVal = decodeURIComponent(str);
650+
} catch (e) {
651+
throw {
652+
code: "D3140",
653+
stack: (new Error()).stack,
654+
value: str,
655+
functionName: "decodeUrlComponent"
656+
};
657+
}
658+
return returnVal;
659+
}
660+
661+
/**
662+
* Decode a string from a url
663+
* @param {String} str - String to decode
664+
* @returns {string} Decoded string
665+
*/
666+
function decodeUrl(str) {
667+
// undefined inputs always return undefined
668+
if (typeof str === 'undefined') {
669+
return undefined;
670+
}
671+
672+
// Catch URIErrors when URI sequence is malformed
673+
var returnVal;
674+
try {
675+
returnVal = decodeURI(str);
676+
} catch (e) {
677+
throw {
678+
code: "D3140",
679+
stack: (new Error()).stack,
680+
value: str,
681+
functionName: "decodeUrl"
682+
};
683+
}
684+
return returnVal;
685+
}
686+
583687
/**
584688
* Split a string into an array of substrings
585689
* @param {String} str - string
@@ -1844,7 +1948,7 @@ const functions = (() => {
18441948
boolean, not,
18451949
map, zip, filter, single, foldLeft, sift,
18461950
keys, lookup, append, exists, spread, merge, reverse, each, error, sort, shuffle,
1847-
base64encode, base64decode
1951+
base64encode, base64decode, encodeUrlComponent, encodeUrl, decodeUrlComponent, decodeUrl
18481952
};
18491953
})();
18501954

src/jsonata.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1705,6 +1705,10 @@ var jsonata = (function() {
17051705
staticFrame.bind('shuffle', defineFunction(fn.shuffle, '<a:a>'));
17061706
staticFrame.bind('base64encode', defineFunction(fn.base64encode, '<s-:s>'));
17071707
staticFrame.bind('base64decode', defineFunction(fn.base64decode, '<s-:s>'));
1708+
staticFrame.bind('encodeUrlComponent', defineFunction(fn.encodeUrlComponent, '<s-:s>'));
1709+
staticFrame.bind('encodeUrl', defineFunction(fn.encodeUrl, '<s-:s>'));
1710+
staticFrame.bind('decodeUrlComponent', defineFunction(fn.decodeUrlComponent, '<s-:s>'));
1711+
staticFrame.bind('decodeUrl', defineFunction(fn.decodeUrl, '<s-:s>'));
17081712
staticFrame.bind('eval', defineFunction(functionEval, '<sx?:x>'));
17091713
staticFrame.bind('toMillis', defineFunction(datetime.toMillis, '<s-s?:n>'));
17101714
staticFrame.bind('fromMillis', defineFunction(datetime.fromMillis, '<n-s?s?:s>'));
@@ -1814,7 +1818,8 @@ var jsonata = (function() {
18141818
"D3136": "The date/time picture string is missing specifiers required to parse the timestamp",
18151819
"D3137": "{{{message}}}",
18161820
"D3138": "The $single() function expected exactly 1 matching result. Instead it matched more.",
1817-
"D3139": "The $single() function expected exactly 1 matching result. Instead it matched 0."
1821+
"D3139": "The $single() function expected exactly 1 matching result. Instead it matched 0.",
1822+
"D3140": "Malformed URL passed to ${{{functionName}}}(): {{value}}"
18181823
};
18191824

18201825
/**
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"expr": "$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")",
3+
"dataset": "dataset5",
4+
"bindings": {},
5+
"result": "https://mozilla.org/?x=шеллы"
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"expr": "$decodeUrl(blah)",
3+
"dataset": "dataset5",
4+
"bindings": {},
5+
"undefinedResult": true
6+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"expr": "$decodeUrl('%E0%A4%A')",
3+
"dataset": "dataset5",
4+
"bindings": {},
5+
"error": {
6+
"code": "D3140",
7+
"message": "Malformed URL passed to $decodeUrl(): \"%E0%A4%A\""
8+
}
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"expr": "$decodeUrlComponent(\"%3Fx%3Dtest\")",
3+
"dataset": "dataset5",
4+
"bindings": {},
5+
"result": "?x=test"
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"expr": "$decodeUrlComponent(blah)",
3+
"dataset": "dataset5",
4+
"bindings": {},
5+
"undefinedResult": true
6+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"expr": "$decodeUrlComponent('%E0%A4%A')",
3+
"dataset": "dataset5",
4+
"bindings": {},
5+
"error": {
6+
"code": "D3140",
7+
"message": "Malformed URL passed to $decodeUrlComponent(): \"%E0%A4%A\""
8+
}
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"expr": "$encodeUrl(\"https://mozilla.org/?x=шеллы\")",
3+
"dataset": "dataset5",
4+
"bindings": {},
5+
"result": "https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"
6+
}

0 commit comments

Comments
 (0)