Monday, February 25, 2013

New Dart:io hotness!

It's been a very long time since my last post for which I apologize. I hope to get back into Dart blogging again soon. A recent announcement on the dartlang mailing list got me excited. BREAKING CHANGE: New version of dart:io. I've been waiting for this to finally land in bleeding_edge. As a lot of my work is with command line applications. It's great seeing dart:io finally getting some love.

Now there were a few surprises that cropped up with the new version of the library. I'm going to note a couple of them I've come across so far that I've noticed. I won't get into details about ones covered in the mailing list announcement. There are a number of others that were too small to be covered there. One big thing I noticed was the removal of HttpServer.addRequestHandler as that was a quick and dirty way of setting up the basics of routing in the server. Now all requests are sent to HttpServer.listen. Similarly, server isn't started by creating a new HttpServer instance and then running listen on it, rather use a static method, HttpServer.bind on the HttpServer class which returns a Future which provides the server instance.

All of this is because the dart:io is being converted to Futures and Streams. And it is a change for the best, making the libraries consistent across libraries and API's. This has also made for some changes to some of the other classes in dart:io and just some clean up which makes sense as well.

Lets start with our eventHandler. In the past adding a RequestHandler to the HttpServer would take two arguments. An HttpRequest and an HttpResponse. The first being the request to the server and the latter being the response back from the server to the client. However, I cannot think of a situation where these two objects would not be intertwined. Apparently the dart developers felt the same way. Now, the new version of a requestHandler (see above), only accepts an HttpRequest. The corresponding HttpResponse object is a property of the HttpRequest, and can be accessed like so: HttpResponse res = httpRequest.response;

Also in HttpRequest, the uri property is no longer a string but returns a URI object. As such, the path property of HttpRequest has been removed in favour of: httpRequest.uri.path. Similarly, session is no longer a method but rather returns a full session object directly. This means that it no longer accepts an init callback to preform a specialized initialization of the session but I'm not aware of that functionality being used very frequently.

[Edit:]
One aspect that I neglected to mention earlier is that writing to the HttpResponse stream is a little easier now as well. In the past we would need to use httpResponse.outputStream.write(...) whereas now, we write directly to the httpResponse itself. For example:

var res = httpRequest.response;
res.addString(...);
// Alternatively we can also use add(List data)
// or addStream(Stream> data).
Check out the API for HttpResponse.[/Edit]

As an experiment with the new library, in particular with the HttpServer and related functionality, I created a very basic webserver example. This sample is not production usable, or even complete in any way. But I think it does provide a good introduction into how the new libraries are used and how extend the Stream interfaces to implement a very basic routing mechanism into the server. The source is available on github: sample_server. This is the basic premise that I'm now implementing in a project that I'm working on at the moment. With any luck I'll be able to extend the functionality of the server and abstract it away from the core logic I'm working on to be able to release the library for others if they are interested. In the mean time the sample_server should help you to get up and running.

One thing I do have to mention, is it was extremely easy to implement my own stream with the route by extending Stream, and just using a StreamController to provide most of the functionality. Only needed to implement the listen() method which in itself passes it on to the controller anyways. Love it!

Note: Currently this requires a bleeding_edge version, as these changes have not yet been added to the stable build. They were written with version: 0.1.2_r18836 and tested with version: 0.1.2_r18968. Details may change prior to stable release.The latest stable version of the Dart SDK has just been released and supports this API. It can be found in version: 0.4.0_r18915.

1 comment: