Tuesday, June 21, 2011

SPDY: express-spdy

‹prev | My Chain | next›

After seeming success with connect-spdy last night, I am ready to try the same with express-spdy. First up, initialize an NPM package:
➜  express-spdy git:(master) ✗ npm init
Package name: (express-spdy)
Description: SPDY-ize express.js sites.
Package version: (0.0.0)
Project homepage: (none) https://github.com/eee-c/express-spdy
Project git repository: (none) https://github.com/eee-c/express-spdy
Author name: Chris Strom
Author email: (none) chris@eeecomputes.com
Author url: (none) http://eeecomputes.com
Main module/entry point: (none) index.js
Test command: (none)
What versions of node does it run on? (~v0.5.0-pre)
About to write to /home/cstrom/repos/express-spdy/package.json

{
"author": "Chris Strom (http://eeecomputes.com)",
"name": "express-spdy",
"description": "SPDY-ize express.js sites.",
"version": "0.0.0",
"homepage": "https://github.com/eee-c/express-spdy",
"repository": {
"type": "git",
"url": "git://github.com/eee-c/express-spdy.git"
},
"main": "index.js",
"engines": {
"node": "~v0.5.0-pre"
},
"dependencies": {},
"devDependencies": {}
}

Is this ok? (yes)
Similar to what I had to do with connect-spdy, I write the core express-spdy to use a SPDY server if options are passed in, otherwise I assume that a normal HTTP server from express proper is desired:
var express = require('express')
, expressCreateServer = express.createServer
, SPDYServer = require('./spdy');

var exports = module.exports = express;

exports.createServer = function(options){
if ('object' == typeof options) {
return new SPDYServer(options, Array.prototype.slice.call(arguments, 1));
} else {
return expressCreateServer(Array.prototype.slice.call(arguments));
}
};
I resolve some package location changes and do some more clean-up work and.. I think I am ready.

To test things out, I copy my express generated sample app into an express-test directory. I then install express-spdy, connect-spdy, and node-spdy from my local repos:
➜  express-test  npm install ~/repos/node-spdy

> zlibcontext@1.0.7 install /home/cstrom/repos/express-test/node_modules/spdy/node_modules/zlibcontext
> ./configure && make
...
'build' finished successfully (0.661s)
zlibcontext@1.0.7 ./node_modules/spdy/node_modules/zlibcontext
spdy@0.0.1 ./node_modules/spdy

➜ express-test npm install ~/repos/connect-spdy
mime@1.2.2 ./node_modules/connect-spdy/node_modules/connect/node_modules/mime
qs@0.1.0 ./node_modules/connect-spdy/node_modules/connect/node_modules/qs
connect@1.5.1 ./node_modules/connect-spdy/node_modules/connect
connect-spdy@0.0.0 ./node_modules/connect-spdy

➜ express-test npm install ~/repos/express-spdy
express-spdy@0.0.0 ./node_modules/express-spdy
That results in a nice, compact npm ls output:
➜  express-test  npm ls
/home/cstrom/repos/express-test
├─┬ connect-spdy@0.0.0
│ └─┬ connect@1.5.1
│ ├── mime@1.2.2
│ └── qs@0.1.0
├─┬ express@2.3.11
│ ├── connect@1.5.1
│ ├── mime@1.2.2
│ └── qs@0.1.0
├── express-spdy@0.0.0
└─┬ spdy@0.0.1
└── zlibcontext@1.0.7
After installing the jade templating engine (used by the generated sample app), everything works! Not only does the site load in Chrome, but the SPDY tab in about:net-internals reports that I have a legit SPDY session:
...
t=1308705422043 [st=19902] SPDY_SESSION_SYN_REPLY
--> flags = 0
--> connection: keep-alive
content-length: 277
content-type: text/html
status: 200 OK
version: HTTP/1.1
x-powered-by: Express
--> id = 7
...
t=1308705422199 [st=20058] SPDY_SESSION_RECV_DATA
--> flags = 0
--> size = 0
--> stream_id = 11
Even after all of that re-organization, it still works. Crazy.

While I am already tempting fate, I might as well publish this as a legit NPM package.

First up, I need to publish connect-spdy. Running npn publish, however, I find:
➜  connect-spdy git:(master) npm publish
npm ERR! Failed PUT response undefined
npm ERR! Error: Cannot insert data into the registry without authorization
npm ERR! See: npm-adduser(1)
...
That was actually entirely expected. I have previously published an NPM package of my own, but not on this machine. After entering the proper credentials:
➜  connect-spdy git:(master) npm adduser
Username: eee-c
Password:
Email: chris@eeecomputes.com
...the npm publish works:
➜  connect-spdy git:(master) npm publish
npm WARN Sending authorization over insecure channel.
I do the same for express-spdy and am then ready to actually try installing directly from NPM. If I have all of my dependencies correct, I should need to install express-spdy, the jade templating engine and nothing else:
➜  express-test  rm -rf node_modules
➜ express-test npm install express-spdy
...
zlibcontext@1.0.7 ./node_modules/express-spdy/node_modules/spdy/node_modules/zlibcontext
spdy@0.0.1 ./node_modules/express-spdy/node_modules/spdy
mime@1.2.2 ./node_modules/express-spdy/node_modules/connect-spdy/node_modules/connect/node_modules/mime
qs@0.1.0 ./node_modules/express-spdy/node_modules/connect-spdy/node_modules/connect/node_modules/qs
connect@1.5.1 ./node_modules/express-spdy/node_modules/connect-spdy/node_modules/connect
connect-spdy@0.0.1 ./node_modules/express-spdy/node_modules/connect-spdy
mime@1.2.2 ./node_modules/express-spdy/node_modules/express/node_modules/mime
connect@1.5.1 ./node_modules/express-spdy/node_modules/express/node_modules/connect
qs@0.1.0 ./node_modules/express-spdy/node_modules/express/node_modules/qs
express@2.3.11 ./node_modules/express-spdy/node_modules/express
express-spdy@0.0.1 ./node_modules/express-spdy
➜ express-test npm ls
/home/cstrom/repos/express-test
└─┬ express-spdy@0.0.1
├─┬ connect-spdy@0.0.1
│ └─┬ connect@1.5.1
│ ├── mime@1.2.2
│ └── qs@0.1.0
├─┬ express@2.3.11
│ ├── connect@1.5.1
│ ├── mime@1.2.2
│ └── qs@0.1.0
└─┬ spdy@0.0.1
└── zlibcontext@1.0.7
➜ express-test npm install jade
jade@0.12.3 ./node_modules/jade
I then run my test express app and....

...it just works.

I still have a valid SYN_REPLY to the initial SYN_STREAM request all the way to the last DATA frame:
...
t=1308708324275 [st= 47] SPDY_SESSION_SYN_REPLY
--> flags = 0
--> Content-Length: 277
Content-Type: text/html
X-Powered-By: Express
status: 200 OK
version: HTTP/1.1
--> id = 1
...
t=1308708324490 [st=262] SPDY_SESSION_RECV_DATA
--> flags = 0
--> size = 23
--> stream_id = 5
t=1308708324490 [st=262] SPDY_SESSION_RECV_DATA
--> flags = 0
--> size = 0
--> stream_id = 5
I can't believe that worked. But I'll take it as a good stopping point for the night.

I have some instructions available at https://github.com/eee-c/express-spdy. I will get started on that TODO list tomorrow.

Day #55

No comments:

Post a Comment