Skip to content

Commit

Permalink
Fix response end delay for non-chunked responses
Browse files Browse the repository at this point in the history
fixes #69
  • Loading branch information
dougwilson committed Aug 6, 2014
1 parent 67b0700 commit 5c503e7
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 29 deletions.
5 changes: 5 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
unreleased
==========

* Fix response end delay for non-chunked responses

1.7.3 / 2014-08-05
==================

Expand Down
72 changes: 43 additions & 29 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,52 @@ function session(options){
return false;
}

ended = true;

var ret;
var sync = true;

if (chunk === undefined) {
chunk = '';
}

ended = true;
function writeend() {
if (sync) {
ret = _end.call(res, chunk, encoding);
sync = false;
return;
}

_end.call(res);
}

function writetop() {
if (!sync) {
return ret;
}

var contentLength = Number(res.getHeader('Content-Length'));

if (!isNaN(contentLength) && contentLength > 0) {
// measure chunk
chunk = !Buffer.isBuffer(chunk)
? new Buffer(chunk, encoding)
: chunk;
encoding = undefined;

if (chunk.length !== 0) {
debug('split response');
ret = _write.call(res, chunk.slice(0, chunk.length - 1));
chunk = chunk.slice(chunk.length - 1, chunk.length);
return ret;
}
}

ret = _write.call(res, chunk, encoding);
sync = false;

return ret;
}

if (shouldDestroy(req)) {
// destroy session
Expand All @@ -205,22 +243,10 @@ function session(options){
}

debug('destroyed');

if (sync) {
ret = _end.call(res, chunk, encoding);
sync = false;
return;
}

_end.call(res);
writeend();
});

if (sync) {
ret = _write.call(res, chunk, encoding);
sync = false;
}

return ret;
return writetop();
}

// no session to save
Expand All @@ -239,22 +265,10 @@ function session(options){
}

debug('saved');

if (sync) {
ret = _end.call(res, chunk, encoding);
sync = false;
return;
}

_end.call(res);
writeend();
});

if (sync) {
ret = _write.call(res, chunk, encoding);
sync = false;
}

return ret;
return writetop();
}

return _end.call(res, chunk, encoding);
Expand Down
114 changes: 114 additions & 0 deletions test/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,120 @@ describe('session()', function(){
.expect(200, 'Hello, world!', done);
})

describe('when response ended', function () {
it('should have saved session', function (done) {
var saved = false
var store = new session.MemoryStore()
var server = createServer({ store: store }, function (req, res) {
req.session.hit = true
res.end('session saved')
})

var _set = store.set
store.set = function set(sid, sess, callback) {
setTimeout(function () {
_set.call(store, sid, sess, function (err) {
saved = true
callback(err)
})
}, 200)
}

request(server)
.get('/')
.expect(200, 'session saved', function (err) {
if (err) return done(err)
saved.should.be.true
done()
})
})

it('should have saved session even with empty response', function (done) {
var saved = false
var store = new session.MemoryStore()
var server = createServer({ store: store }, function (req, res) {
req.session.hit = true
res.setHeader('Content-Length', '0')
res.end()
})

var _set = store.set
store.set = function set(sid, sess, callback) {
setTimeout(function () {
_set.call(store, sid, sess, function (err) {
saved = true
callback(err)
})
}, 200)
}

request(server)
.get('/')
.expect(200, '', function (err) {
if (err) return done(err)
saved.should.be.true
done()
})
})

it('should have saved session even with multi-write', function (done) {
var saved = false
var store = new session.MemoryStore()
var server = createServer({ store: store }, function (req, res) {
req.session.hit = true
res.setHeader('Content-Length', '12')
res.write('hello, ')
res.end('world')
})

var _set = store.set
store.set = function set(sid, sess, callback) {
setTimeout(function () {
_set.call(store, sid, sess, function (err) {
saved = true
callback(err)
})
}, 200)
}

request(server)
.get('/')
.expect(200, 'hello, world', function (err) {
if (err) return done(err)
saved.should.be.true
done()
})
})

it('should have saved session even with non-chunked response', function (done) {
var saved = false
var store = new session.MemoryStore()
var server = createServer({ store: store }, function (req, res) {
req.session.hit = true
res.setHeader('Content-Length', '13')
res.end('session saved')
})

var _set = store.set
store.set = function set(sid, sess, callback) {
setTimeout(function () {
_set.call(store, sid, sess, function (err) {
saved = true
callback(err)
})
}, 200)
}

request(server)
.get('/')
.expect(200, 'session saved', function (err) {
if (err) return done(err)
saved.should.be.true
done()
})
})
})

describe('when sid not in store', function () {
it('should create a new session', function (done) {
var count = 0
Expand Down

0 comments on commit 5c503e7

Please sign in to comment.