My master plan for furthering my understanding of fab.js tonight centers around getting a functional
fab.map
in place somewhere.I try various things that may or may not have an resemblance to how
fab.map
expects to be used, but nothing works. I always end up with this from curl
:cstrom@whitefall:~/repos/fab$ curl localhost:4011/all_dbs...and something like this from the fab.js server:
curl: (52) Empty reply from server
cstrom@whitefall:~/repos/fab$ node ./play/all_dbs.jsBacking up a bit, I try some other fab.js apps (contentLength/stringify), but they have similar problems. What have I done here? My script is extremely simple—it contains a call to my CouchDB server and one of the hello-world examples bundled with fab.js:
Error: process.mixin() has been removed.
at EventEmitter.mixin (node.js:11:11)
at listener (/home/cstrom/repos/fab/apps/fab.nodejs.js:39:34)
at listener (/home/cstrom/repos/fab/apps/fab.map.js:9:19)
at IncomingMessage.<anonymous> (/home/cstrom/repos/fab/apps/fab.nodejs.http.js:29:15)
at HTTPParser.onBody (http:95:23)
at Client.ondata (http:601:30)
at IOWatcher.callback (net:307:31)
at node.js:748:9
fab = require( "../" );At least the hello world still works right? Without a pathname argument and with:
require( "http" ).createServer( fab
( fab.nodejs )
// These don't work either
// ( fab.contentLenth )
// ( fab.stringify )
( /^\/all_dbs/ )
// I try various maps here
( fab.nodejs.http("http://localhost:5984/_all_dbs") )
( /^\/hello/ )
( fab.tmpl, "Hello, <%= this[ 0 ] %>!" )
( /^\/(\w+)$/ )
( fab.capture )
( [ "world" ] )
( 404 )
).listen( 0xFAB );
cstrom@whitefall:~/repos/fab$ curl localhost:4011/helloGah! What on earth have I done?!
Hello, world!
cstrom@whitefall:~/repos/fab$ curl localhost:4011/hello/foo
curl: (52) Empty reply from server
OK. Let's take a step back and try the example code itself:
cstrom@whitefall:~/repos/fab$ node ./examples/index.js...and access it with
curl
(it is the seventh hello-world example included in the fab.js source):cstrom@whitefall:~/repos/fab$ curl -i localhost:4011/hello/7/fooAha! It wasn't me. This is what I get for playing around with something that is undergoing major refactoring. No worries, it would not be fun if the code base were stagnant. Speaking of which, I have been doing all of this without pulling the most recent changes (idiot!).
curl: (52) Empty reply from server
After stashing my changes from last night, I pull, then retry the included example:
cstrom@whitefall:~/repos/fab$ curl -i localhost:4011/hello/7/fooNice! I also find that the example in my play code is working. Sadly, the fab.nodejs.http call still fails on the third try:
HTTP/1.1 200 OK
Connection: keep-alive
Transfer-Encoding: chunked
Hello, foo!
cstrom@whitefall:~/repos/fab$ curl localhost:4011/all_dbsNo matter, let's see about fab.map...
["eee","test","seed"]
cstrom@whitefall:~/repos/fab$ curl localhost:4011/all_dbs
["eee","test","seed"]
cstrom@whitefall:~/repos/fab$ curl localhost:4011/all_dbs
curl: (52) Empty reply from server
cstrom@whitefall:~/repos/fab$ curl localhost:4011/all_dbs
curl: (7) couldn't connect to host
The simplest map of which I can think is one that appends text to the body of an upstream app (downstream is toward the requesting client). From the fab.js documentation, fab.map converts an ordinary function into a binary app. Binary, in fab.js terms means it sits between downstream and upstream apps. To do so, it needs access to the upstream app, which fab.js will supply.
This is the simple append text map that I come up with:
fab = require( "../" );The fab.map app supplies my function with a copy of the upstream app. I use that to append to the body of the upstream response and...
require( "http" ).createServer( fab
( fab.nodejs )
( fab.map( function (app) {
app.body += " FOO!!!";
return app;
}))
( /^\/all_dbs/ )
( fab.nodejs.http("http://localhost:5984/_all_dbs") )
( /^\/hello/ )
( fab.tmpl, "Hello, <%= this[ 0 ] %>!" )
( /^\/(\w+)$/ )
( fab.capture )
( [ "world" ] )
( 404 )
).listen( 0xFAB );
strom@whitefall:~/repos/fab$ curl localhost:4011/hello/foo -iYay! I actually mapped the upstream app into something else. I may be just beginning to understand this stuff.
HTTP/1.1 200 OK
Connection: keep-alive
Transfer-Encoding: chunked
Hello, foo! FOO!!!
Day #82
Nice! The structure for testing apps is now in place, and I'm going to start documenting it Sunday.
ReplyDeleteA few things: you should use 'obj' instead of 'app' as the name of the argument in your map function, because what you're getting is a partial HTTP response. Also, you'll need to check if 'obj.body' exists, because the upstream app may pass a response that has no body (only a status, or headers, for example).
In other news, I added a fab.nodejs.listen app that can replace the standard node createServer boilerplate if you'd like. Combined with a safe use of 'with', you can make pretty terse definitions:
http://github.com/jed/fab/blob/master/README.md
Jed
Oooh... shiny :)
ReplyDeleteI had noticed the with-fab stuff in some of the latest code. Very clean looking indeed :)
I think I based the map on contentLength which has the obj.body check. I wondered what that was about, but ignored it for tonight's exercise--I knew I had a body and just wanted a proof of concept. Good to know what's up with that.
Thanks again for all the help (and the awesome framework)!
-Chris