Saturday, November 24, 2012

Dirty Dart Web Server

‹prev | My Chain | next›

I am sorely tempted to continue pursuing the almighty millisecond in an effort to improve the performance of dart dirty. Tempted, but I think it best to leave it at good enough. For now.

So instead, I would like to put my persistent HashMap to first use in my Dart Comics sample app. Assuming that all goes well, I will publish dart-dirty in the pub package manager for Dart. Since it is not yet in pub, I start by creating a pubspec.yaml in my application's root directory with a dependency pointing to the github repository:
name: Dart Comics
dependencies:
  dart_dirty:
    git: git://github.com/eee-c/dart-dirty.git
I already have a pubspec.yaml for my client-side scripts in the public/scripts directory of Dart Comics. This pubspec.yaml is for the server app. In the root directory, I run pub install command to get all of my server-side packages installed:
➜  dart-comics git:(app.dart) ✗ pub install
Resolving dependencies...
Dependencies installed!
➜  dart-comics git:(app.dart) ✗ ls packages
dart_dirty  unittest
➜  dart-comics git:(app.dart) ✗ ls -l packages
total 4
lrwxrwxrwx 1 chris chris 82 Nov 24 23:28 dart_dirty -> /home/chris/.pub-cache/git/dart_dirty-82ab8c2ba813bfaf473f9e2cd57eb82cc38140e2/lib
lrwxrwxrwx 1 chris chris 48 Nov 24 23:28 unittest -> /home/chris/local/dart/dart-sdk/pkg/unittest/lib
With that, I am ready to use dart-dirty as the persistent store for my sample app. I update the Dart HTTP server to pull in dart-dirty and to open a dart-dirty dart_comics.db file:
import 'dart:io';
import 'dart:json';

import 'package:dart_dirty/dirty.dart';

main() {
  Dirty db = new Dirty('dart_comics.db');

  app.addRequestHandler( /* ... */ );
  // ...
  app.listen('127.0.0.1', 8000);
}
Implementing the all-comics resource in my Dart backend is relatively straight forward:
main() {
  // ...
  app.addRequestHandler(
    (req) => req.method == 'GET' && req.path == '/comics',
    (req, res) {
      res.headers.contentType = 'application/json';
      res.outputStream.writeString(JSON.stringify(db.values));
      res.outputStream.close();
    }
  );
  // ...
}
The POST handler is a bit trickier:
  app.addRequestHandler(
    (req) => req.method == 'POST' && req.path == '/comics',
    (req, res) {
      var input = new StringInputStream(req.inputStream);
      var post_data = '';

      input.onLine = () {
        var line = input.readLine();
        post_data = post_data.concat(line);
      };

      input.onClosed = () {
        var graphic_novel = JSON.parse(post_data);
        graphic_novel['id'] = db.length + 1;

        db[graphic_novel['id']] = graphic_novel;

        res.statusCode = 201;
        res.headers.contentType = 'application/json';

        res.outputStream.writeString(JSON.stringify(graphic_novel));
        res.outputStream.close();
      };

    }
The typical HTTP response work takes place in the input's onClosed callback. When the POST body is completely read, the onClosed method is called. In there, I can parse the incoming JSON so that it can be stored in the dart-dirty database. I would not mind if server-side Dart had a nice req.body property, but I will not complain too much this early in the evolution of the library.

With that, I can POST and get increasing IDs for the comics that are added to the persistent store:
➜  dart-dirty git:(master) curl -i -d '{"title": "Awesome Comic"}' http://localhost:8000/comics
HTTP/1.1 201 Created
content-type: application/json
transfer-encoding: chunked

{"title":"Awesome Comic","id":2}%
➜  dart-dirty git:(master) curl -i -d '{"title": "Awesome Comic"}' http://localhost:8000/comics
HTTP/1.1 201 Created
content-type: application/json
transfer-encoding: chunked

{"title":"Awesome Comic","id":3}%  
And if I stop and start my web server backend, I find that my comics are indeed restored from the filesystem:
dart-dirty git:(master) curl -i http://localhost:8000/comics                                
HTTP/1.1 200 OK
content-type: application/json
transfer-encoding: chunked

[{"title":"Awesome Comic","id":1},{"title":"Awesome Comic","id":2},{"title":"Awesome Comic","id":3}]% 
It looks as though some of my Hipster MVC library is in need of updating so I will attend to that tomorrow. For now, I am well on my way to having a pure-Dart client and server sample application.


Day #579

No comments:

Post a Comment