views:

270

answers:

1

Is there a method/function to get the canonical / transformed URL, respecting any base.href setting of the page?

I can get the base URL via (in jQuery) using $("base").attr("href") and I could use string methods to parse the URL meant to being made relative to this, but

  • $("base").attr("href") has no host, path etc attributes (like window.location has)
  • manually putting this together is rather tedious

E.g., given a base.href of "http://example.com/foo/" and a relative URL "/bar.js", the result should be: "http://example.com/bar.js"

If base.href is not present, the URL should be made relative to window.location. This should handle non-existing base.href (using location as base in this case).

Is there a standard method available for this already?

(I'm looking for this, since jQuery.getScript fails when using a relative URL like "/foo.js" and BASE tag is being used (FF3.6 makes an OPTIONS request, and nginx cannot handle this). When using the full URL (base.href.host + "/foo.js", it works).)

+1  A: 

Does this do the trick?

function resolveUrl(url){
    if (!url) {
        throw new Error("url is undefined or empty");
    }
    var reParent = /[\-\w]+\/\.\.\//, // matches a foo/../ expression 
 reDoubleSlash = /([^:])\/\//g; // matches // anywhere but in the protocol
    // replace all // except the one in proto with /
    url = url.replace(reDoubleSlash, "$1/");
    var base = (document.getElementsByTagName('BASE')[0] && document.getElementsByTagName('BASE')[0].href) || "";

    // If the url is a valid url we do nothing
    if (!url.match(/^(http||https):\/\//)) {
        // If this is a relative path
        var path = (url.substring(0, 1) === "/") ? base : location.pathname;
        if (path.substring(path.length - 1) !== "/") {
            path = path.substring(0, path.lastIndexOf("/") + 1);
        }
        if (!url.match(/^(http||https):\/\//)) {
            url = location.protocol + "//" + location.host + path + url;
        }
    }

    // reduce all 'xyz/../' to just '' 
    while (reParent.test(url)) {
        url = url.replace(reParent, "");
    }
    return url;
}

It is modified from some code I had around, so it hasn't been tested

Sean Kinsey
Yes, that would probably do the trick.However, it will not work for "//example.com" (reDoubleSlash) at least, and I was looking for a "batteries included" type of solution.Would be good enough, if jQuery would provide such a function, and it probably does already, but I could not find it.
blueyed