Last night, I hacked together an integration test for SPDY server push in node-spdy. Today I would like to use that (and the non-push integration test) to drive an implementation that works.
First up, I try including a "push" callback among the server options:
options = {Those options are fed into the
push: function(req, c, createPushStream) {
var push_stream = createPushStream(req, c, "http://example.com/foo");
push_stream.write("push data");
push_stream.end();
},
//...
};
createServer
function in the vows.js topic:vows.describe('SPDY/basic test').addBatch({The request, connect middleware object and createPushStream function passed in feel heavy handed. An arity of three is never a good thing. Still, it is driven by working code:
'spdy.createServer': {
topic: function() {
return spdy.createServer(options);
}
Response.prototype._push = function(filename, url) {So maybe that will be ok...?
var push_stream = createPushStream(this.cframe, this.c, url);
push_stream.write(fs.readFileSync(filename));
// TODO: Combine FIN & write? (once push stream is working)
push_stream.end();
};
At any rate, I implement with:
If the options do not include a push callback, then an empty anonymous function is called:
Response.prototype._pushStuff = function() {
if (this._pushed) return false;
if (this.streamID != 1) return false;
this.pushStuff(this.cframe, this.c, createPushStream);
// this._push("pub/style.css", "https://localhost:8081/style.css");
// this._push("pub/spdy.jpg", "https://localhost:8081/spdy.jpg");
this._pushed = true;
};
var Response = exports.Response = function(cframe, c) {With that, I have both integration tests (push and non-push) passing. Yay!
//...
this.pushStuff = function() {};
//...
};
But that callback with three parameters is bugging me. I would much rather have something that is closer to the now commented out
_push
method:// this._push("pub/style.css", "https://localhost:8081/style.css");Hrm... I wonder if I call the push callback with just the response object, might that work? It is worth a try, if nothing else. In the Response class, I switch up the push callback to:
// this._push("pub/spdy.jpg", "https://localhost:8081/spdy.jpg");
Response.prototype._pushStuff = function() {An arity of one is much nicer. But how would the callback now look? Actually not too bad:
if (this._pushed) return false;
if (this.streamID != 1) return false;
this.pushStuff(this);
this._pushed = true;
};
push: function(pusher) {Oooh. Both the callback and the callback context got simpler. I like that.
pusher.push("pub/style.css", "http://example.com/foo");
},
With the integration tests still passing, I would like to try this out with Chrome for a quick sanity check. I copy
test/spdy-server.js
to test/spdy-push-server.js
and change the ports from 8081 to 8082 (I may want to run them side-by-side):server.listen(8082, function() {I add the appropriate push callback as well and start up the server:
console.log('TLS NPN Server is running on port : %d', 8082);
});
➜ node-spdy git:(push-stream) ✗ node test/spdy-push-server.jsNice. That seems to work. The web page shows when I load it up, but...
TLS NPN Server is running on port : 8082
...checking it out in the SPDY tab of
about:net-internals
, I see:t=1307502498585 [st= 42] SPDY_SESSION_PUSHED_SYN_STREAMBah! Something is not working there.
--> associated_stream = 1
--> flags = 2
--> status: 200
url: https://localhost:8081/style.css
version: http/1.1
--> id = 2
t=1307502498585 [st= 42] SPDY_SESSION_SEND_RST_STREAM
--> status = 3
--> stream_id = 2
Hey wait a second, why is that URL being pushed out with a port of 8081? Heh. That would do it.
After switching everything in
test/spdy-push-server.js
to 8082, I reload and see a right proper SPDY session in the SPDY tab:#####Nice. But...
# Push the CSS
t=1307503216226 [st= 42] SPDY_SESSION_PUSHED_SYN_STREAM
--> associated_stream = 1
--> flags = 2
--> status: 200
url: https://localhost:8082/style.css
version: http/1.1
--> id = 2
# CSS data here...
#####
# Push the background JPEG
t=1307503216236 [st= 52] SPDY_SESSION_PUSHED_SYN_STREAM
--> associated_stream = 1
--> flags = 2
--> status: 200
url: https://localhost:8082/spdy.jpg
version: http/1.1
--> id = 4
# Image data here...
#####
# It's legit!
t=1307503216250 [st= 66] SPDY_STREAM_ADOPTED_PUSH_STREAM
...dang. Now that I think about it, there was another reason to include the request in the push callback—it can be used to conditionally push streams.
I will add that back in tomorrow and also take some time to review my work.
Day #43
No comments:
Post a Comment