Permalink
Browse files

Support deferred server push.

It is often desirable to push large data sets *after* the original response has been sent.  This change should allow for that.  I have tried to maintain backwards compatibility with the old push API.

Also included is the last-modified header, which Chrome requires for certain resource (CSS).
  • Loading branch information...
1 parent e27e897 commit b8187d8ab54d5bcfc85e8c41fe669cd562d0d363 @eee-c eee-c committed Jul 30, 2011
Showing with 55 additions and 5 deletions.
  1. +2 −1 lib/spdy/push_stream.js
  2. +52 −3 lib/spdy/response.js
  3. +1 −1 package.json
View
@@ -24,7 +24,8 @@ var PushStream = exports.PushStream = function(associated_cframe, c, url) {
this._headers = {
status: 200,
version: "http/1.1",
- url: url
+ url: url,
+ "last-modified": (new Date).toGMTString()
};
if (/\.html?$/.test(url))
View
@@ -78,6 +78,37 @@ Response.prototype._flushHead = function() {
return this.c.write(cframe);
};
+Response.prototype.pushLater = function(resources) {
+ var that = this;
+
+ this.deferred_streams = [];
+
+ // Send headers for each post-response server push stream, but DO
+ // NOT sent data yet
+ resources.forEach(function(push_contents) {
+ var filename = push_contents[0]
+ , url = push_contents[1]
+ , data = fs.readFileSync(filename)
+ , push_stream = createPushStream(that.cframe, that.c, url);
+
+ push_stream._flushHead();
+ push_stream._written = true;
+ that.deferred_streams.push([push_stream, data]);
+ });
+};
+
+Response.prototype._pushLaterData = function(resources) {
+ if (typeof(this.deferred_streams) == 'undefined') return;
+
+ this.deferred_streams.forEach(function(stream_and_data) {
+ var stream = stream_and_data[0]
+ , data = stream_and_data[1];
+
+ stream.write(data);
+ stream.end();
+ });
+};
+
/**
* Write any data (Internal)
*/
@@ -92,12 +123,25 @@ Response.prototype._write = function(data, encoding, fin) {
data = new Buffer(0);
}
+ // Write the data frame
var dframe = createDataFrame(this.getStreamCompressor(), {
streamID: this.streamID,
- flags: fin ? enums.DATA_FLAG_FIN : enums.DATA_FLAG_COMPRESSED,
+ flags: 0
}, Buffer.isBuffer(data) ? data : new Buffer(data, encoding));
- return this.c.write(dframe);
+ this.c.write(dframe);
+
+ // Write the data FIN if this if fin
+ if (fin) {
+ var dfin = createDataFrame(this.getStreamCompressor(), {
+ streamID: this.streamID,
+ flags: enums.DATA_FLAG_FIN
+ }, new Buffer(0));
+ this.c.write(dfin);
+ }
+
+ // Push any deferred data streams
+ this._pushLaterData();
};
@@ -180,10 +224,15 @@ Response.prototype.setPush = function(fn) {
};
Response.prototype._push_stream = function() {
- this._push(this);
+ return this._push(this);
};
Response.prototype.push_file = function(filename, url) {
+ console.log("[warn] Response#push_file has been deprecate. Please switch to pushFile instead.");
+ return this.pushFile(filename, url);
+};
+
+Response.prototype.pushFile = function(filename, url) {
this.push(fs.readFileSync(filename), url);
};
View
@@ -1,7 +1,7 @@
{
"name": "spdy",
"description": "Implementation of the SPDY protocol on node.js.",
- "version": "0.1.1",
+ "version": "0.1.2",
"author": "Fedor Indutny <fedor.indutny@gmail.com>",

0 comments on commit b8187d8

Please sign in to comment.