Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion lib/ServerResponse.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,19 @@ function ServerResponse(socket) {
this._socket = socket;
this.sendDate = true;
var self = this;
// Pass on internal socket events up to listeners on the Response object
// (which is what's exposed in the connect's http pipeline)
this._socket.on('finish', function () { self.emit('finish'); });
this._socket.on('close', function (had_error) { self.emit('close', had_error); });
// Socket will raise 'header' event when headers have been committed. This is
// consistent with how 'connect' library patches ServerResponse.
this._socket.on('header', function () {
// Additionally it patches the .headerSent property, so we don't set it directly but via ._header
// (see 'patch.js' in 'connect' module lib folder).
self.headersSent = self._header = true;
// _headers is also assumed on the response object by 'connect' module
self._headers = self._socket._requestContext.headers;
});
};

util.inherits(ServerResponse, events.EventEmitter);
Expand All @@ -21,7 +33,12 @@ ServerResponse.prototype.destroy = function (error) {
};

ServerResponse.prototype.write = function(chunk, encoding, isEnd) {
this._socket._requestContext.responseStarted = true;
// ensure statusCode property is set on the Response object (as
// per node's documentation), and allow middleware to set it
if (!this._socket._requestContext.responseStarted) {
this._socket._requestContext.responseStarted = true;
this._socket._requestContext.statusCode = this.statusCode = this.statusCode || this._socket._requestContext.statusCode;
}
return this._socket.write(chunk, encoding, isEnd);
};

Expand Down
7 changes: 7 additions & 0 deletions lib/Socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,12 @@ Socket.prototype._queue_body_chunk = function (chunk, encoding, isEnd)
};

Socket.prototype._on_written = function () {
// When all chunks have been sent, and we are at the end (isLastChunk is true),
// then this is the last callback from the native module, and we should emit
// a 'finish' event for whoever is listening (e.g. connect.logger middleware).
if (!this._requestContext.chunks && this._requestContext.isLastChunk)
this.emit('finish');

if (this._requestContext.drainEventPending && !this._requestContext.chunks) {
delete this._requestContext.drainEventPending;
if (!this._closed) {
Expand Down Expand Up @@ -373,6 +379,7 @@ Socket.prototype._initiate_send_next = function () {
// Initiate sending HTTP response headers and body, if any.

this._requestContext.headersWritten = true;
this.emit('header');

try {
this._requestContext.asyncPending('res', httpsys.httpsys_write_headers(this._requestContext));
Expand Down
86 changes: 86 additions & 0 deletions test/111_connect_stack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
var http = require('../lib/httpsys.js').http()
, https = require('../lib/httpsys.js').https()
, fs = require('fs')
, assert = require('assert')
, connect = require('connect');

var port = process.env.PORT || 3102;
var server;

describe('111_connect_stack.js: connect stack integration', function () {

afterEach(function (done) {
if (server) {
server.close(function () {
done();
server = undefined;
});
}
else {
done();
}
});

it('works with connect.logger', function (done) {
var log = '';
server = http.createServer(connect()
.use(connect.logger({
stream: {
write: function(data) { log += data; }
}
}))
.use(function(req, res, next) {
res.setHeader('content-type', 'text/plain');
if (req.url === '/test') {
res.statusCode = 304;
res.end();
} else {
res.statusCode = 200;
res.setHeader('content-length', 14);
res.end('This is a test');
}
})
);

server.listen(port);

log = '';
sendAndCheck('/', 'hello', function(res, body) {
assert.equal(res.statusCode, 200);
assert.equal(res.headers['content-type'], 'text/plain');
assert.equal(body, 'This is a test');
assert(log.indexOf('\"GET / HTTP/1.1\" 200 14') >= 0, 'Expecting proper log message: ' + log);

log = '';
sendAndCheck('/test', '', function(res, body) {
assert.equal(res.statusCode, 304);
assert.equal(res.headers['content-type'], 'text/plain');
assert.equal(body, '');
assert(log.indexOf('\"GET /test HTTP/1.1\" 304 -') >= 0, 'Expecting proper log message: ' + log);

done();
});
});
});

});

function sendAndCheck(reqPath, reqBody, resCallback) {
var options = {
hostname: 'localhost',
port: port,
path: reqPath,
method: 'GET'
};

var request = http.request(options, function (res) {
var body = '';
res.on('data', function (chunk) { body += chunk; });
res.on('end', function () {
resCallback(res, body);
});
});

request.on('error', assert.ifError);
request.end();
}