I started looking at a dashcode project the other day. Within a few minutes, I realised that I needed something like URI.pm, in order to resolve URIs into an absolute form. I had a quick look around and there didn’t seem to be anything code out there that does this.
So, I had a quick look at RFC 3986 and noticed that amongst other things it contains pseudo-code for parsing and resolving URLs. I coded it up first in Ruby, which took the pseudo-code almost word for word, and made some tests for it. Then I translated into JavaScript and figured out how to use Test.Simple.
The end result is js-uri, a small URI object. It does what I need at the moment.
// Parsing. var some_uri = new URI("http://www.example.com/foo/bar"); alert(some_uri.authority); // www.example.com alert(some_uri); // http://www.example.com/foo/bar // Resolving. var blah = new URI("blah"); var blah_full = blah.resolve(some_uri); alert(blah_full); // http://www.example.com/foo/blah
There’s quite a bit it doesn’t do yet.
- %-escaping and unescaping.
- Parsing the URL in more detail. It would be useful to pull out the query parameters and host / port for instance.
- For some reason, the tests only work in Firefox. Not sure why.
But hopefully it’s still useful.
In the process of developing the JavaScript, I spent ages tracking down one particular problem. I was trying to introduce new scope to define a couple of private helper functions:
(function () { function merge(base, rel_path) { ... } function remove_dot_segments(path) { ... } URI.prototype.resolve = function (base) { var target = new URI(); // ... return target; } })();
Looks perfectly legit right? It caused syntax errors in every browser I tried. Eventually, JSLint managed to tell me the problem: a missing semicolon after the URI.prototype.resolve
definition. I hate JavaScript for trying to guess where the semicolon should go. Because it can get it so wrong like this.
8 replies on “JavaScript URI Objects”
This is excellent. I’ve half written chunks of this so often in Zimki that I’ve been meaning to write a reusable version myself. Maybe I should modify your version to be useful for that.
Couple of points…firstly, can you make this free software by any chance? I don’t know if you meant to, but there’s no license that I can see attached.
Secondly…when are you going to get a chance to implement parameter handling? Do you want me to have a go?
My pet peeve with JavaScript is that trailing commas (for example, in list declarations) can cause problems. Of course this is runtime dependent; it’s fine in Zimki but I think both IE and Safari can get kvetchy over it.
It wouldn’t be such a problem but years of Perl have conditioned me to leave trailing commas, so that expanding the list never goes wrong.
Hi Dominic,
I have a slightly simplistic implementation of the URI object (though it does the same job) here:
http://remysharp.com/URI.js
Example here:
http://remysharp.com/wp-content/uploads/2007/04/uri.html
My version doesn’t have the resolve function – since I was just seeing if the functionality could be quickly replicated using the DOM. On the same note, I don’t know how this would work within Dashboard – whether the widget has a DOM (though I assume it does).
It does uses the DOM to form the parts of the URI (i.e. if you create URI it will pre-load the other values from the current window.location) – but I’ve also have a query object that you can query individual parts or change and add elements to the query string, i.e. change ?page=1 to ?page=2&subpage=a
Totally aside, not sure if you remember me, but you interviewed me a little over a year ago – I tried to reply to your email to no avail as it kept bouncing.
Mark: It should be BSD licensed. It’s at the top of
URI.js
, but I’ll make it more explicit. I’m going to have a go at parsing the query string properly over the weekend, check back on Monday. Warning: I think I’ll need to go to accessors instead of properties, though.Paul: Yup, it’s a pain in the arse. More annoying is the fact that I can’t get the tests to run in Safari / Opera. Looks like a JSAN problem, but I haven’t gone into it closely.
Remy: Apologies—my google-fu must have missed that. The
resolve()
function was the real reason for writing it. Dashboard does have a proper DOM, but I couldn’t find a way of doing this whilst browsing through my rhino book. But I’d prefer to avoid depending on the DOM, as I will probably end up using this as part of FlowScript.Anybody: If you want to hack on it, let me know your gmail id and I’ll add you to the project as a committer.
Damn, I didn’t put the licence in there at all. I’ll correct that now.
Hey Dom, I guess you lost my email. I started work on the parameter parsing stuff) which I emailed you.
My gmail id is 2shortplanks if you want me to commit it.
Mark: Sorry, I haven’t been near my mail in days. 😦 I’ve added you to the project, please go ahead and commit.
Plus there’s the fact that bogofilter had a shit fit and started blowing up. Again. I hate bogofilter.