I am slowly coming to the conclusion that this may not be the best time to issue a 1.1 edition of SPDY Book. Much of the new hotness that is node-spdy is in limbo until the unstable 0.7 node.js becomes stable 0.8. I almost have a handle on that except for express.js, the pleasant HTTP resource-oriented application server. The current 2.0 series will work with edge node-spdy, but not 0.7/0.8 node.js. For 0.8 node.js, the 3.0 alpha of express.js is imminent—only it does not play well with node-spdy.
All of these moving parts have me thinking that a more modest SPDY Book update might be the better part of valor. But I am not quite ready to give up. First, I would like to have a go at getting edge node-spdy and edge express.js working together.
The latest node-spdy does a rather elegant thing when creating SPDY-sized servers—it accepts an optional class argument that can be used to decorate server-like objects. This is specifically used to create express.js instances as I found last night:
var app = spdy.createServer(express.HTTPSServer, options);The problem presented by edge express.js is that there is no
express.HTTPSServer class anymore. In particular, the new express.application is more of a mixin than a proper class. The answer (hopefully) is that node-spdy also works with HTTP server objects, which is what the
express() function ought to return in 3.0. I have my forks of express.js and connect.js (for middleware) checked out locally. I have to modify the package.json for each to be compatible with 0.7:{
"name": "express",
"description": "Sinatra inspired web development framework",
// ...
"engines": { "node":">= 0.5.0 < 0.9.0" }
}With that, I can install globally and use the resultant generator to get started on an express3 application:➜ tmp npm install -g ~/repos/express/ ~/repos/connect ➜ tmp express express3-spdy-test ➜ tmp cd express3-spdy-test ➜ express3-spdy-test npm install ~/repos/express ~/repos/connect ~/repos/node-spdy ➜ express3-spdy-test npm install jadeI also copy the SSL keys from my 2.0 test application:
➜ express3-spdy-test mkdir keys ➜ express3-spdy-test cp ../express-spdy-test/keys/* keys ➜ express3-spdy-test ls keys spdy-cert.pem spdy-csr.pem spdy-key.pemI can start up the generated express 3.0 app:
➜ express3-spdy-test node app Express server listening on port 3000Pointing the browser at that site, I get the expected default homepage:
Next, I need an SSL version of the site. For that I change the
http.createServer() to the https equivalent in the application app.js file:// ...
var options = {
key: fs.readFileSync(__dirname + '/keys/spdy-key.pem'),
cert: fs.readFileSync(__dirname + '/keys/spdy-cert.pem'),
ca: fs.readFileSync(__dirname + '/keys/spdy-csr.pem')
};
https.createServer(options, app).listen(3000);After restarting, I can now access the default express.js site over SSL:Now for the moment of truth: switching to node-spdy. I add
spdy to the list of required packages and replace the https.createServer with the node-spdy equivalent:var express = require('express')
, routes = require('./routes')
, http = require('http')
, https = require('https')
, spdy = require('spdy')
, fs = require('fs');
var app = express();
app.configure(function(){ /* ... */ });
app.get('/', routes.index);
var options = {
key: fs.readFileSync(__dirname + '/keys/spdy-key.pem'),
cert: fs.readFileSync(__dirname + '/keys/spdy-cert.pem'),
ca: fs.readFileSync(__dirname + '/keys/spdy-csr.pem')
};
//https.createServer(options, app).listen(3000);
spdy.createServer(https.Server, options, app).listen(3000);After starting the server, I can again access the homepage over SSL, but this time, when I check the SPDY tab in Chrome's chrome://net-internals, I have SPDY!SPDY_SESSION_SYN_STREAM
--> flags = 1
--> accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
accept-charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
accept-encoding: gzip,deflate,sdch
accept-language: en-US,en;q=0.8
cache-control: no-cache
cookie: [value was stripped]
host: localhost:3000
method: GET
pragma: no-cache
scheme: https
url: /
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.8 (KHTML, like Gecko) Chrome/20.0.1105.0 Safari/536.8
version: HTTP/1.1
--> id = 1
SPDY_SESSION_RECV_SETTING
--> flags = 1
--> id = 4
--> value = 100
SPDY_SESSION_SYN_REPLY
--> flags = 0
--> content-length: 277
content-type: text/html; charset=utf-8
status: 200 OK
version: HTTP/1.1
x-powered-by: Express
--> id = 1
...Aw, man! That is nice. I was really worried that the new express.js would be incompatible, but clearly my worries were completely unfounded. Not only does it work, but it is really easy to configure and get running. Once again, kudos to Fedor Indunty for the very slick implementation.Despite the ease with which I got all of this up and running, I am still in a bit of a bind with regards to including edge stuff like this in the updated book or sticking with express-spdy, which is clearly no longer needed. The former is a moving target and the latter is likely to be obsolete days after I put out the next edition of The SPDY Book. I think this suggests that minimal changes for now might be the best course of action, but I will sleep on it before making a decision.
If nothing else, the future of SPDY on node.js looks quite nice.
Day #361




I followed your same steps, except in Windows, with node v0.7.8, but when I visit the URL in Chrome, net-internals doesn't list it as SPDY. What steps can I do to debug why Chrome isn't detecting it as SPDY session? Or isn't utilizing SPDY...
ReplyDeleteHrm... I suppose the next step is snooping the SSL handshake to see if the server really is advertising SPDY. Something like wireshark should do: http://japhr.blogspot.com/2012/04/express-spdy-on-old-openssl.html
DeleteSince I couldn't wireshark local, I installed node on my mac and worked between it and vm of windows on it. Only this time SPDY worked, so I'll have to do the same against my other physical machine to see deviations. Do you know with node-spdy, is it possible to run the server with out SSL? I would like to be able to capture the traffic and analyze with Wireshark without dealing with SSL encryption...
DeleteThanks for the suggestions!
It is not possible to run node-spdy without SSL. There was a fork a while back that had a go at enabling this, but it was never merged in and would not work well with all of the changes in version 1.0 and later.
DeleteI wonder if it's possible that node-spdy does not work under windows...?