Posts Tagged ‘javascript’

Server-side OpenLayers

March 14, 2010

I’ve been interested in server-side JavaScript lately. As a proof of feasibility (to myself) I’ve put together a node.js-based web service that gets geographic objects from PostGIS and provides a GeoJSON representation of these objects.

For this I’ve used node.js, postgres-js and OpenLayers.

node.js is a lib whose goal is “to provide an easy way to build scalable network applications”. node.js relies on an event-driven architecture (through epoll, kqueue, /dev/poll, or select). I’d recommend looking at the jsconf slides to know more about the philosophy and design of node.js.

The “Hello World” node.js web service looks like that:

var sys = require('sys'),
      http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.write('Hello World');
  res.close();
}).listen(8000);
sys.puts('Server running at http://127.0.0.1:8000/');

Thanks to node.js’s nice interface I think the code is pretty much self-explained.

Assuming the above code is included in a file named file.js, starting the web service is done with

$ node file.js

Now we can use postgres-js to read data from a PostGIS table. postgres-js sends SQL queries to PostgreSQL through TCP. postgres-js is a node.js module, so it can be loaded with require() (just like the built-in sys and http modules).

var sys = require('sys'),
    http = require('http'),
    Postgres = require('postgres');

var db = new Postgres.Connection("dbname", "username", "password");

http.createServer(function (req, res) {
    db.query("SELECT name, astext(geom) AS geom FROM table", function (objs) {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.write("it works");
        res.close();
    });
}).listen(8000);
sys.puts('Server running at http://127.0.0.1:8000/');

The last step involves using OpenLayers for deserializing from WKT and serializing to GeoJSON. To use OpenLayers in the node.js application, and load it with the require() function, I packaged OpenLayers as a node.js module. It was easy enough, see the modules doc.

And here’s the final code:

var sys = require('sys'),
    http = require('http'),
    Postgres = require('postgres'),
    OpenLayers = require('openlayers').OpenLayers;

var db = new Postgres.Connection("dbname", "username", "password");

http.createServer(function (req, res) {
    db.query("SELECT name, astext(geom) AS geom FROM table", function (objs) {
        var features = [];
        var wkt = new OpenLayers.Format.WKT();
        for(var i=0,len=objs.length; i<len; i++) {
            features.push(
                new OpenLayers.Feature.Vector(
                    wkt.read(obj[i].geom).geometry, {name: obj[i].name}
                )
            );
        }
        var geojson = new OpenLayers.Format.GeoJSON();
        var output = geojson.write(features);
        res.writeHead(200, {'Content-Type': 'application/json'});
        res.write(output);
        res.close();
    });
}).listen(8000);
sys.puts('Server running at http://127.0.0.1:8000/');

The End. Happy server-side JavaScript to all.