Wednesday, May 5, 2010

Static HTTP Server in 6 Lines of Fab.js

‹prev | My Chain | next›

Tonight, I start the process of moving my <canvas>/fab.js game out of a "play" sandbox into a real code repository. So far, the game consists of moving a character about in one browser screen and watching the results in another browser:



At this point, the entire application consists of three files: game.js (script containing the fab.js backend) and two static HTML files. I create a repository:
cstrom@whitefall:~$ mkdir repos/my_fab_game/
I put game.js directly in that directory and the two static HTML files into an html sub-directory such that:
cstrom@whitefall:~/repos/my_fab_game$ find
.
./html
./html/board.html
./html/view_only.html
./game.js
With that, I need to make game.js aware of the fab.js library—preferably without hard-coding any paths. This is accomplished by putting the library node.js's load path. The easiest way to do this is to create a symbolic link to fab.js in the ~/.node_libraries directory:
cstrom@whitefall:~$ mkdir ~/.node_libraries
cstrom@whitefall:~$ cd .node_libraries/
cstrom@whitefall:~/.node_libraries$ ln -s ../repos/fab
Now, my fab.js script can start with:
with ( require( "fab" ) )
And it will find the fab.js library.

Next up, how to serve those static files?

I had accomplished this during play-time by hard coding the fab.nodejs.fs call to the route. I would prefer something that took the requested URL and pulled the corresponding HTML file from the file system. Sure I could accomplish this in Apache, by why introduce that if I can do it stand alone?

This is the code that I settle on to accomplish just that:

(fab.nodejs.fs)
(
function () {
var out = this;
return function (head) {
out({ body: "html/" + head.url.pathname.substr(1) + ".html" });
if (out) out();
};
}
)
The anonymous upstream function uses the header information to tell fab.nodejs.fs where to find the correct file. This only works if I make a change to fab.nodejs.fs similar to the one I had to make to fab.nodeje.http—putting an upstream listener into fab.nodejs.fs so that my upstream, anonymous function will have access to the URL.

I fork fab.js on github to encapsulate these two changes. I don't know if these changes are needed for others (there are major changes on the way which might address this), but I need it now.

With that, I can run my fab.js app:
cstrom@whitefall:~/repos/my_fab_game$ node game.js 
And request my static files:
cstrom@whitefall:~/repos/my_fab_game$ curl http://localhost:4011/view_only -Ni
HTTP/1.1 200 OK
Connection: keep-alive
Transfer-Encoding: chunked

<html>
<head>
<style type="text/css">
#canvas {
...
That is a good stopping point for tonight. I will pick up tomorrow fixing a bug and re-organizing the <canvas> javascript code.

Day #94

No comments:

Post a Comment