Description
The new URL()
constructor currently requires at least one of its arguments to be an absolute URL.
new URL('./page.html', 'https://site.com/help/'); // OK
new URL('./page.html', '/help/'); // Uncaught TypeError: URL constructor: /public_html/ is not a valid URL.
That requirement is painful because determining which absolute URL to use as a base can be difficult or impossible in many circumstances. In a regular browser context, document.baseURI
should be used. In Web Workers, self.location
should be used. In Deno, window.location
should be used but only if the --location
command line option was used. In Node, there is no absolute URL to use. Trying to write isomorphic code that satisfies this requirement is quite error prone.
Additionally, in many cases it would be useful to parse and resolve relative URLs against each other without knowing an absolute base URL ahead of time.
// Desired output - these currently do not work
new URL('/to', '/from').toString(); // '/to'
new URL('/to', '//from.com/').toString(); // '//from.com/to'
The lack of support for use cases involving only relative URLs is causing me to remove WHATWG URL from Ky, a popular HTTP request library, in favor of our own string replacement. See: sindresorhus/ky#271
Desired API and whether to update the existing new URL()
API or create a new API?
From my perspective, updating the new URL()
constructor so it can handle a relative URL in the baseUrl
argument would be ideal, i.e. remove the requirement for an absolute base in favor of simply parsing any missing URL parts as empty strings (as is currently done when a URL lacks a query, for example). But I understand that changing new URL()
at this point may be difficult and it may be more practical to instead create a new API; perhaps new PartialURL()
or split out the validation, parsing, and resolution algorithms into individual methods.
For my purposes, I need to at least be able to parse and serialize a relative URL, without having to provide an absolute base URL. A method that resolves two relative URLs against each other and returns the resulting relative URL would also be useful, e.g. URL.resolve('./from/index.html', './to') -> ./from/to
.