How To Join Relative URLs in JavaScript
The ECMAScript URL
Web API mentioned by @ning is a good place to start: especially as it is available in vanilla JS implementations (Node, etc.) and doesn't require you to use a library that does something the implementation nowq already accomplishes. Consulting the MDN documentation, more specifically the examples, is a great place to start.
Borrowing (somewhat) directly from their documentation:
let m = 'https://developer.mozilla.org';
// ... omitted
let d = new URL('/en-US/docs', m);
If you were to do the above, then console.log
the .toString of the constructed URL
object, your output would be: 'https://developer.mozilla.org/en-US/docs'
.
Importantly, if you consult the Syntax section of the documentation, you will note that the second argument is optional and the second argument (as seen in the above example) represents the base URL (though only in the case of two arguments being supplied).
If both argument values are absolute URLs, Web API honors the first and discards the second.
If you are working with Node.js, I would encourage you to look at the native path module for doing work on relative paths, again over using a library. The main motivation here is that spinning up your own algorithm (probably just a call to path
here and there) is potentially better than introducing a library that will pull in several other dependencies that may introduce vulnerabilities and unnecessary bloat to your application (or just be too heavy weight for what you need).
However, if you are working on the front end, you won't have path
available to you and - as mentioned in @cburgmer's answer comments - Web API's URL
doesn't support the relative path case mentioned. In this case, you may need to look for a library to accomplish this for you; however, again, given the other answers, I'd consider trying out a home-spun approach.
To their credit, URI.js
currently only integrates one non-dev. dependency and doesn't have a huge footprint.
Using URI.js (urijs - npm): absoluteTo()
:
function joinUrl(baseUrl, url) {
var theUrl = new URI(url);
if (theUrl.is("relative")) {
theUrl = theUrl.absoluteTo(baseUrl);
}
return theUrl.toString();
}
The following function decomposes the URL then resolves it.
function concatAndResolveUrl(url, concat) {
var url1 = url.split('/');
var url2 = concat.split('/');
var url3 = [ ];
for (var i = 0, l = url1.length; i < l; i ++) {
if (url1[i] == '..') {
url3.pop();
} else if (url1[i] == '.') {
continue;
} else {
url3.push(url1[i]);
}
}
for (var i = 0, l = url2.length; i < l; i ++) {
if (url2[i] == '..') {
url3.pop();
} else if (url2[i] == '.') {
continue;
} else {
url3.push(url2[i]);
}
}
return url3.join('/');
}
8 years later, many browsers (except for Internet Explorer) support the URL constructor (URL(url [, base])
).
> new URL('../address', 'http://www.adress.com/more/evenmore/').href
"http://www.adress.com/more/address"
> new URL('../../address', 'http://www.adress.com/more/evenmore/').href
"http://www.adress.com/address"