Skip to content

Commit

Permalink
http: set async_id_symbol to any socket set
Browse files Browse the repository at this point in the history
OutgoingMessage needs a async-hooks enabled socket to work, but
we support also basic streams. This PR init the async-hooks bits
for the passed stream if it is needed.

PR-URL: #14389
Fixes: #14386
Fixes: #14381
  • Loading branch information
mcollina committed Jul 20, 2017
1 parent aa496f4 commit 9977354
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 1 deletion.
17 changes: 16 additions & 1 deletion lib/_http_outgoing.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ const checkIsHttpToken = common._checkIsHttpToken;
const checkInvalidHeaderChar = common._checkInvalidHeaderChar;
const outHeadersKey = require('internal/http').outHeadersKey;
const async_id_symbol = process.binding('async_wrap').async_id_symbol;
const async_hooks = require('async_hooks');
const nextTick = require('internal/process/next_tick').nextTick;
const errors = require('internal/errors');
const kSocket = Symbol('socket');

const CRLF = common.CRLF;
const debug = common.debug;
Expand Down Expand Up @@ -116,7 +118,7 @@ function OutgoingMessage() {
this.finished = false;
this._headerSent = false;

this.socket = null;
this[kSocket] = null;
this.connection = null;
this._header = null;
this[outHeadersKey] = null;
Expand All @@ -125,6 +127,19 @@ function OutgoingMessage() {
}
util.inherits(OutgoingMessage, Stream);

Object.defineProperty(OutgoingMessage.prototype, 'socket', {
get: function() {
return this[kSocket];
},
set: function(socket) {
this[kSocket] = socket;
if (socket && socket[async_id_symbol] === undefined) {
socket[async_id_symbol] = async_hooks.newUid();
async_hooks.emitInit(socket[async_id_symbol], 'not-a-socket',
async_hooks.initTriggerId(), this);
}
}
});

Object.defineProperty(OutgoingMessage.prototype, '_headers', {
get: function() {
Expand Down
32 changes: 32 additions & 0 deletions test/parallel/test-http-outgoing-message-inheritance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

const common = require('../common');
const { OutgoingMessage } = require('http');
const { Writable } = require('stream');
const assert = require('assert');

// check that OutgoingMessage can be used without a proper Socket
// Fixes: https://github.com/nodejs/node/issues/14386
// Fixes: https://github.com/nodejs/node/issues/14381

class Response extends OutgoingMessage {
constructor() {
super({ method: 'GET', httpVersionMajor: 1, httpVersionMinor: 1 });
}

_implicitHeader() {}
}

const res = new Response();
const ws = new Writable({
write: common.mustCall((chunk, encoding, callback) => {
assert(chunk.toString().match(/hello world/));
setImmediate(callback);
})
});

res.socket = ws;
ws._httpMessage = res;
res.connection = ws;

res.end('hello world');
27 changes: 27 additions & 0 deletions test/parallel/test-http-server-response-standalone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use strict';

const common = require('../common');
const { ServerResponse } = require('http');
const { Writable } = require('stream');
const assert = require('assert');

// check that ServerResponse can be used without a proper Socket
// Fixes: https://github.com/nodejs/node/issues/14386
// Fixes: https://github.com/nodejs/node/issues/14381

const res = new ServerResponse({
method: 'GET',
httpVersionMajor: 1,
httpVersionMinor: 1
});

const ws = new Writable({
write: common.mustCall((chunk, encoding, callback) => {
assert(chunk.toString().match(/hello world/));
setImmediate(callback);
})
});

res.assignSocket(ws);

res.end('hello world');

0 comments on commit 9977354

Please sign in to comment.