diff --git a/configure/src/core/utils.js b/configure/src/core/utils.js index 12f7d8fbe1..e9fd6684f8 100644 --- a/configure/src/core/utils.js +++ b/configure/src/core/utils.js @@ -6,7 +6,8 @@ export const isNumeric = (value) => { }; export const isUrlAbsolute = (url) => { - const r = new RegExp("^(?:[a-z]+:)?//", "i"); + // RFC 3986 scheme (letters, digits, + - .) so s3://, gs://, etc. count + const r = new RegExp("^(?:[a-z][a-z0-9+.-]*:)?//", "i"); return r.test(url); }; diff --git a/src/essence/Basics/Formulae_/Formulae_.js b/src/essence/Basics/Formulae_/Formulae_.js index 56cbdecab4..ebb77980f6 100644 --- a/src/essence/Basics/Formulae_/Formulae_.js +++ b/src/essence/Basics/Formulae_/Formulae_.js @@ -822,7 +822,8 @@ var Formulae_ = { return 'zero' }, isUrlAbsolute: function (url) { - const r = new RegExp('^(?:[a-z]+:)?//', 'i') + // RFC 3986 scheme (letters, digits, + - .) so s3://, gs://, etc. count + const r = new RegExp('^(?:[a-z][a-z0-9+.-]*:)?//', 'i') return r.test(url) }, csvToJSON: function (csv) { diff --git a/tests/unit/formulae.spec.js b/tests/unit/formulae.spec.js index 8982390408..d529f51d86 100644 --- a/tests/unit/formulae.spec.js +++ b/tests/unit/formulae.spec.js @@ -851,6 +851,15 @@ test.describe('Formulae_ - Validation Utilities', () => { test('detects absolute URLs', () => { expect(F_.isUrlAbsolute('http://example.com')).toBe(true); expect(F_.isUrlAbsolute('https://example.com')).toBe(true); + expect(F_.isUrlAbsolute('//example.com/path')).toBe(true); + }); + + test('detects schemes containing digits or punctuation', () => { + expect(F_.isUrlAbsolute('s3://my-bucket/path/file.tif')).toBe(true); + expect(F_.isUrlAbsolute('gs://my-bucket/file.tif')).toBe(true); + expect(F_.isUrlAbsolute('az://container/file.tif')).toBe(true); + expect(F_.isUrlAbsolute('file:///Missions/cog.tif')).toBe(true); + expect(F_.isUrlAbsolute('svn+ssh://host/repo')).toBe(true); }); test('detects relative URLs', () => {