Skip to content

Instantly share code, notes, and snippets.

@panzi
Created February 18, 2012 04:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save panzi/1857344 to your computer and use it in GitHub Desktop.
Save panzi/1857344 to your computer and use it in GitHub Desktop.
Build an absolute url from an relative url and an absolute base url.
/**
* Build an absolute url using an base url.
* The provided base url has to be a valid absolute url. It will not be validated!
* If no base url is given the document location is used.
* Schemes that behave other than http might not work.
* It tries to support file:-urls, but might fail in some cases.
* email:-urls aren't supported at all (don't make sense anyway).
*
* NOTE: Internet Explorer does not support the baseURI property, but it does
* support the base tag, which results in wrong url. You might want to
* fix this by searching for a base tag and using its href attribute.
* If you use jQuery you might want to replace the first line of the
* function with this:
* if (!base) base = document.baseURI || $("html > head > base").last().attr("href") || document.location.href;
*/
function absurl (url, base) {
if (!base) base = document.baseURI || document.location.href;
if (!url) {
return base;
}
else if (/^[a-z][-+\.a-z0-9]*:/i.test(url)) {
// The scheme actually could contain any kind of alphanumerical unicode
// character, but JavaScript regular expressions don't support unicode
// character classes. Maybe /^[^:]+:/ or even /^.*:/ would be sufficient?
return url;
}
else if (url.slice(0,2) === '//') {
return /^[^:]+:/.exec(base)[0]+url;
}
var ch = url.charAt(0);
if (ch === '/') {
if (/^file:/i.test(base)) {
// file scheme has no hostname
return 'file://'+url;
}
else {
return /^[^:]+:\/*[^\/]+/i.exec(base)[0]+url;
}
}
else if (ch === '#') {
// assume "#" only occures at the end indicating the fragment
return base.replace(/#.*$/,'')+url;
}
else if (ch === '?') {
// assume "?" and "#" only occure at the end indicating the query
// and the fragment
return base.replace(/[\?#].*$/,'')+url;
}
else {
var base, path;
if (/^file:/i.test(base)) {
base = "file://";
path = base.replace(/^file:\/{0,2}/i,'');
}
else {
var match = /^([^:]+:\/*[^\/]+)(\/.*?)?(\?.*?)?(#.*)?$/.exec(base);
base = match[1];
path = match[2]||"/";
}
path = path.split("/");
path.pop();
if (path.length === 0) {
// Ensure leading "/". Of course this is only valid on
// unix like filesystems. More magic would be needed to
// support other filesystems.
path.push("");
}
path.push(url);
return base+path.join("/");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment