From d960717ec831f93fa8321fb1045392974272c1f8 Mon Sep 17 00:00:00 2001 From: Hyosik Philip Joo Date: Sat, 30 Mar 2024 20:26:16 +0900 Subject: [PATCH 1/9] feat: Add encodeUri in UriOptions interface --- lib/index.d.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/index.d.ts b/lib/index.d.ts index 3a50bfbc..2aac4b30 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -426,6 +426,12 @@ declare namespace Joi { * Validate the domain component using the options specified in `string.domain()`. */ domain?: DomainOptions; + /** + * Encode URI before validation. + * + * @default false + */ + encodeUri?: boolean; } interface DataUriOptions { From 76f3044d57953a77c7b9356d3ed0ad9b8368f88e Mon Sep 17 00:00:00 2001 From: Hyosik Philip Joo Date: Sat, 30 Mar 2024 20:41:05 +0900 Subject: [PATCH 2/9] feat: Add encodeUri in options list for uri method --- lib/types/string.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/types/string.js b/lib/types/string.js index c86aa391..85ac3e80 100755 --- a/lib/types/string.js +++ b/lib/types/string.js @@ -649,7 +649,7 @@ module.exports = Any.extend({ uri: { method(options = {}) { - Common.assertOptions(options, ['allowRelative', 'allowQuerySquareBrackets', 'domain', 'relativeOnly', 'scheme']); + Common.assertOptions(options, ['allowRelative', 'allowQuerySquareBrackets', 'domain', 'relativeOnly', 'scheme', 'encodeUri']); if (options.domain) { Common.assertOptions(options.domain, ['allowFullyQualified', 'allowUnicode', 'maxDomainSegments', 'minDomainSegments', 'tlds']); From 3aa024311505e6f8fbe3747c49165b3bc093a008 Mon Sep 17 00:00:00 2001 From: Hyosik Philip Joo Date: Sat, 30 Mar 2024 21:16:51 +0900 Subject: [PATCH 3/9] feat: Encode uri with true flags in uri validation --- lib/types/string.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/types/string.js b/lib/types/string.js index 85ac3e80..8ed0617d 100755 --- a/lib/types/string.js +++ b/lib/types/string.js @@ -678,6 +678,10 @@ module.exports = Any.extend({ return value; } + if (helpers.prefs.convert && options.encodeUri) { + return encodeURI(value); + } + if (options.relativeOnly) { return helpers.error('string.uriRelativeOnly'); } From 278cc05d3fe1309075dc4ea67ef30695898c3e6a Mon Sep 17 00:00:00 2001 From: Hyosik Philip Joo Date: Sat, 30 Mar 2024 21:18:21 +0900 Subject: [PATCH 4/9] feat: Add test for uri encoding --- test/types/string.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/types/string.js b/test/types/string.js index 64c65ee6..0a266d78 100755 --- a/test/types/string.js +++ b/test/types/string.js @@ -9012,6 +9012,15 @@ describe('string', () => { ]); }); + it('validates uri after encoding', () => { + + const schema = Joi.string().uri({ encodeUri: true }); + + Helper.validate(schema, { convert: true }, [ + ['https://linkedin.com/in/aïssa/', true, 'https://linkedin.com/in/a%C3%AFssa/'], + ]); + }) + it('errors on unknown options', () => { expect(() => Joi.string().uri({ foo: 'bar', baz: 'qux' })).to.throw('Options contain unknown keys: foo,baz'); From aa164899d4b5761f7df4b35de1bf8af54e882b29 Mon Sep 17 00:00:00 2001 From: Hyosik Philip Joo Date: Sat, 30 Mar 2024 21:24:50 +0900 Subject: [PATCH 5/9] fix: Integrate lint suggestions for style consistency --- test/types/string.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/types/string.js b/test/types/string.js index 0a266d78..79d8578b 100755 --- a/test/types/string.js +++ b/test/types/string.js @@ -9017,9 +9017,9 @@ describe('string', () => { const schema = Joi.string().uri({ encodeUri: true }); Helper.validate(schema, { convert: true }, [ - ['https://linkedin.com/in/aïssa/', true, 'https://linkedin.com/in/a%C3%AFssa/'], + ['https://linkedin.com/in/aïssa/', true, 'https://linkedin.com/in/a%C3%AFssa/'] ]); - }) + }); it('errors on unknown options', () => { From 19f1f309505971cf97befd14ab13f04d0c675a99 Mon Sep 17 00:00:00 2001 From: Hyosik Philip Joo Date: Sat, 30 Mar 2024 21:55:34 +0900 Subject: [PATCH 6/9] fix: Pre-encode value before other cases --- lib/types/string.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/types/string.js b/lib/types/string.js index 8ed0617d..f7c9aefa 100755 --- a/lib/types/string.js +++ b/lib/types/string.js @@ -665,6 +665,10 @@ module.exports = Any.extend({ return helpers.error('string.uri'); } + if (helpers.prefs.convert && options.encodeUri) { + value = encodeURI(value); + } + const match = regex.exec(value); if (match) { const matched = match[1] || match[2]; @@ -678,10 +682,6 @@ module.exports = Any.extend({ return value; } - if (helpers.prefs.convert && options.encodeUri) { - return encodeURI(value); - } - if (options.relativeOnly) { return helpers.error('string.uriRelativeOnly'); } From a5ed7a9460d49aa69bbfb7feb8c7ecde368ccda7 Mon Sep 17 00:00:00 2001 From: Hyosik Philip Joo Date: Mon, 22 Apr 2024 12:49:41 +0900 Subject: [PATCH 7/9] feat: Add custom error message for uriEncoding --- lib/types/string.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/types/string.js b/lib/types/string.js index f7c9aefa..5ddbe6d5 100755 --- a/lib/types/string.js +++ b/lib/types/string.js @@ -690,6 +690,10 @@ module.exports = Any.extend({ return helpers.error('string.uriCustomScheme', { scheme, value }); } + if (options.encodeUri) { + return helpers.error('string.uriEncoding'); + } + return helpers.error('string.uri'); } } @@ -740,6 +744,7 @@ module.exports = Any.extend({ 'string.uri': '{{#label}} must be a valid uri', 'string.uriCustomScheme': '{{#label}} must be a valid uri with a scheme matching the {{#scheme}} pattern', 'string.uriRelativeOnly': '{{#label}} must be a valid relative uri', + 'string.uriEncoding': '{{#label}} must contain only valid characters or "convert" must be allowed', 'string.uppercase': '{{#label}} must only contain uppercase characters' } }); From 9554c80be4803318555054e9f3108a9389229af4 Mon Sep 17 00:00:00 2001 From: Hyosik Philip Joo Date: Mon, 22 Apr 2024 12:50:55 +0900 Subject: [PATCH 8/9] feat: Add case for uriEncoding convert false --- test/types/string.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/test/types/string.js b/test/types/string.js index 79d8578b..ac96dae3 100755 --- a/test/types/string.js +++ b/test/types/string.js @@ -9012,7 +9012,7 @@ describe('string', () => { ]); }); - it('validates uri after encoding', () => { + it('validates uri with accented characters with encoding', () => { const schema = Joi.string().uri({ encodeUri: true }); @@ -9021,6 +9021,20 @@ describe('string', () => { ]); }); + it('validates uri with accented characters without encoding', () => { + + const schema = Joi.string().uri({ encodeUri: true }); + + Helper.validate(schema, { convert: false }, [ + ['https://linkedin.com/in/aïssa/', false, { + message: '"value" must contain only valid characters or "convert" must be allowed', + path: [], + type: 'string.uriEncoding', + context: { value: 'https://linkedin.com/in/aïssa/', label: 'value' } + }] + ]); + }); + it('errors on unknown options', () => { expect(() => Joi.string().uri({ foo: 'bar', baz: 'qux' })).to.throw('Options contain unknown keys: foo,baz'); From 2b6f5e56a2f84022db81f2d2f1f5ea9b8deaddd6 Mon Sep 17 00:00:00 2001 From: Hyosik Philip Joo Date: Mon, 22 Apr 2024 12:55:28 +0900 Subject: [PATCH 9/9] docs: Add description for encodeUri --- API.md | 1 + 1 file changed, 1 insertion(+) diff --git a/API.md b/API.md index f7d6653c..b74d8782 100755 --- a/API.md +++ b/API.md @@ -3085,6 +3085,7 @@ Requires the string value to be a valid [RFC 3986](http://tools.ietf.org/html/rf - `relativeOnly` - Restrict only relative URIs. Defaults to `false`. - `allowQuerySquareBrackets` - Allows unencoded square brackets inside the query string. This is **NOT** RFC 3986 compliant but query strings like `abc[]=123&abc[]=456` are very common these days. Defaults to `false`. - `domain` - Validate the domain component using the options specified in [`string.domain()`](#stringdomainoptions). + - `encodeUri` - Encodes the uri with non-alphabetical characters. Defaults to `false`. ```js // Accept git or git http/https