From 992af3b3ee708622e36c303d070490a521692b7a Mon Sep 17 00:00:00 2001 From: mister-ben Date: Fri, 3 May 2024 14:06:05 +0200 Subject: [PATCH] refactor: use URL API (#8716) * refactor: use URL API * add relative test * remove old jsdoc comment * Corrected test description --- src/js/utils/url.js | 101 +++--------------------------------- test/unit/utils/url.test.js | 12 ++--- 2 files changed, 10 insertions(+), 103 deletions(-) diff --git a/src/js/utils/url.js b/src/js/utils/url.js index 2d288550ae..2967bfde02 100644 --- a/src/js/utils/url.js +++ b/src/js/utils/url.js @@ -5,80 +5,18 @@ import document from 'global/document'; import window from 'global/window'; -/** - * @typedef {Object} url:URLObject - * - * @property {string} protocol - * The protocol of the url that was parsed. - * - * @property {string} hostname - * The hostname of the url that was parsed. - * - * @property {string} port - * The port of the url that was parsed. - * - * @property {string} pathname - * The pathname of the url that was parsed. - * - * @property {string} search - * The search query of the url that was parsed. - * - * @property {string} hash - * The hash of the url that was parsed. - * - * @property {string} host - * The host of the url that was parsed. - */ - /** * Resolve and parse the elements of a URL. * * @function - * @param {String} url + * @param {string} url * The url to parse * - * @return {url:URLObject} + * @return {URL} * An object of url details */ export const parseUrl = function(url) { - // This entire method can be replace with URL once we are able to drop IE11 - - const props = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash', 'host']; - - // add the url to an anchor and let the browser parse the URL - const a = document.createElement('a'); - - a.href = url; - - // Copy the specific URL properties to a new object - // This is also needed for IE because the anchor loses its - // properties when it's removed from the dom - const details = {}; - - for (let i = 0; i < props.length; i++) { - details[props[i]] = a[props[i]]; - } - - // IE adds the port to the host property unlike everyone else. If - // a port identifier is added for standard ports, strip it. - if (details.protocol === 'http:') { - details.host = details.host.replace(/:80$/, ''); - } - - if (details.protocol === 'https:') { - details.host = details.host.replace(/:443$/, ''); - } - - if (!details.protocol) { - details.protocol = window.location.protocol; - } - - /* istanbul ignore if */ - if (!details.host) { - details.host = window.location.host; - } - - return details; + return new URL(url, document.baseURI); }; /** @@ -90,21 +28,9 @@ export const parseUrl = function(url) { * * @return {string} * Absolute URL - * - * @see http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue */ export const getAbsoluteURL = function(url) { - // Check if absolute URL - if (!url.match(/^https?:\/\//)) { - // Add the url to an anchor and let the browser parse it to convert to an absolute url - const a = document.createElement('a'); - - a.href = url; - - url = a.href; - } - - return url; + return (new URL(url, document.baseURI)).href; }; /** @@ -139,27 +65,12 @@ export const getFileExtension = function(path) { * @param {string} url * The url to check. * - * @param {Object} [winLoc] + * @param {URL} [winLoc] * the domain to check the url against, defaults to window.location * - * @param {string} [winLoc.protocol] - * The window location protocol defaults to window.location.protocol - * - * @param {string} [winLoc.host] - * The window location host defaults to window.location.host - * * @return {boolean} * Whether it is a cross domain request or not. */ export const isCrossOrigin = function(url, winLoc = window.location) { - const urlInfo = parseUrl(url); - - // IE8 protocol relative urls will return ':' for protocol - const srcProtocol = urlInfo.protocol === ':' ? winLoc.protocol : urlInfo.protocol; - - // Check if url is for another domain/origin - // IE8 doesn't know location.origin, so we won't rely on it here - const crossOrigin = (srcProtocol + urlInfo.host) !== (winLoc.protocol + winLoc.host); - - return crossOrigin; + return parseUrl(url).origin !== winLoc.origin; }; diff --git a/test/unit/utils/url.test.js b/test/unit/utils/url.test.js index f72cfd394c..19449fcfa9 100644 --- a/test/unit/utils/url.test.js +++ b/test/unit/utils/url.test.js @@ -41,9 +41,8 @@ QUnit.test('should strip port from hosts using http or https', function(assert) }); QUnit.test('should get an absolute URL', function(assert) { - // Errors on compiled tests that don't use unit.html. Need a better solution. - // assert.ok(Url.getAbsoluteURL('unit.html') === window.location.href); - assert.ok(Url.getAbsoluteURL('http://asdf.com') === 'http://asdf.com'); + assert.ok(Url.getAbsoluteURL(window.location.pathname + window.location.search) === window.location.href); + assert.ok(Url.getAbsoluteURL('http://asdf.com') === 'http://asdf.com/'); assert.ok(Url.getAbsoluteURL('https://asdf.com/index.html') === 'https://asdf.com/index.html'); }); @@ -81,12 +80,9 @@ QUnit.test('isCrossOrigin can identify cross origin urls', function(assert) { // we cannot test that relative urls work on https, though assert.ok(!Url.isCrossOrigin('example.vtt'), 'relative url is not cross origin'); - const location = { - protocol: 'https:', - host: 'google.com' - }; + const location = new URL('https:/google.com'); - assert.ok(!Url.isCrossOrigin('https://google.com/example.vtt', location), 'http://google.com from https://google.com is not cross origin'); + assert.ok(!Url.isCrossOrigin('https://google.com/example.vtt', location), 'https://google.com from https://google.com is not cross origin'); assert.ok(Url.isCrossOrigin('http://google.com/example.vtt', location), 'http://google.com from https://google.com is cross origin'); assert.ok(Url.isCrossOrigin('http://example.com/example.vtt', location), 'http://example.com from https://google.com is cross origin'); assert.ok(Url.isCrossOrigin('https://example.com/example.vtt', location), 'https://example.com from https://google.com is cross origin');