Friday, September 10, 2010

Fab.js and POST Data

‹prev | My Chain | next›

First up today, I write a v0.5 fab.js app that reads from downstream (e.g. from the browser). I struggled last night, but Jed has pushed my in the right direction.

Oh, all right, he told me how to do it.

I continue working with the following application:
// Don't crash on errors
process.on('uncaughtException', function (err) {
console.log('[uncaughtException] ' + err.stack);
});

with ( require('fab') )

( fab )

// Listen on the FAB port
( listen, 0xFAB )

(prepend_hello)
(read_from_downstream)
(prepend_hello)
()

();
The prepend_hello (fab) apps do just that: prepend the text " hello " before whatever the previous app streams back. The read_from_downstream app should read whatever the downstream (the web client) sends / POSTs, and send it back.

So let's get started with the app:
function read_from_downstream(write) {
return write( function read(write, obj, body) {
body(function(chunk){
console.log("chunk: " + chunk);
}
);
return write;
});
}
To get access to POST data, I need to read from the body() stream. That requires a callback. For starters, I just use an anonymous function that logs the chunks of data being read.

After starting up the server, I POST to the server with curl:
cstrom@whitefall:~$ curl http://localhost:4011/ -d Bar 
hello hello
The output is as expected (" hello " prepended on itself)—the read_from_downstream app is just returning the write stream, which connects the streams above and below it together. Of more interest is the server output:
cstrom@whitefall:~/tmp$ ./test.js
chunk: Bar
chunk: undefined
The anonymous callback supplied to the body stream returns my POST data and then undefined. I need to keep that undefined in mind because calling write(undefined) is not the same as calling write().

Now to write the POST data in the response stream. Since I am using a callback to access the body stream, I need to accumulate all of the chunks in that callback before sending back in the response stream. That is the purpose to the fab.stream app—anything written to the stream will go into a queue to be released when write() is invoked. Thus, the app becomes:
function read_from_downstream(write) {
return write( function read(write, obj, body) {
return fab.stream(function(stream) {
body(function(chunk){
console.log("chunk: " + chunk);
chunk ? stream(write(chunk)) : stream(write());
});
});
});
}
If I have done everything correctly, my stack:
  (prepend_hello)
(read_from_downstream)
(prepend_hello)
()
Should prepend " hello " onto nothing, then prepend the POST data to that, then prepend " hello " onto that. And, that is just what I see in curl:
cstrom@whitefall:~$ curl http://localhost:4011/ -d Bar 
hello Bar hello
cstrom@whitefall:~$ curl http://localhost:4011/ -d Foo
hello Foo hello
With a minor success under my belt, I call it a night. I need to learn from the past week that pushing past simple success makes for a tired Chris. Up tomorrow: I will play with some of the new (fab) HTML apps.


Day #222

No comments:

Post a Comment