Last active
November 11, 2015 16:54
-
-
Save Trott/cfe8d6d0219e1e06d416 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var assert = require('assert'); | |
// Here we are testing the HTTP server module's flood prevention mechanism. | |
// When writeable.write returns false (ie the underlying send() indicated the | |
// native buffer is full), the HTTP server cork()s the readable part of the | |
// stream. This means that new requests will not be read (however request which | |
// have already been read, but are awaiting processing will still be | |
// processed). | |
// Normally when the writable stream emits a 'drain' event, the server then | |
// uncorks the readable stream, although we arent testing that part here. | |
switch (process.argv[2]) { | |
case undefined: | |
return parent(); | |
case 'child': | |
return child(); | |
default: | |
throw new Error('Unexpected value: ${process.argv[2]}'); | |
} | |
function parent() { | |
var http = require('http'); | |
var bigResponse = new Buffer(10240); | |
bigResponse.fill('x'); | |
var childClosed = false; | |
var requests = 0; | |
var connections = 0; | |
var backloggedReqs = 0; | |
var child; | |
var server = http.createServer(function(req, res) { | |
requests++; | |
res.setHeader('content-length', bigResponse.length); | |
if (!res.write(bigResponse)) { | |
if (backloggedReqs > 50) { | |
return child.kill('SIGTERM'); | |
} | |
if (backloggedReqs === 0) { | |
// Once the native buffer fills (ie write() returns false), the flood | |
// prevention should kick in. | |
// This means the stream should emit no more 'data' events. However we | |
// may still be asked to process more requests if they were read before | |
// the flood-prevention mechanism activated. | |
setImmediate(function () { | |
req.socket.on('data', function () {assert.fail(null, null, 'Unexpected data received')}); | |
}); | |
} | |
backloggedReqs++; | |
} | |
res.end(); | |
}); | |
server.on('connection', function(conn) { | |
connections++; | |
}); | |
server.listen(1337, function() { | |
var spawn = require('child_process').spawn; | |
var args = [__filename, 'child']; | |
child = spawn(process.execPath, args, { stdio: 'inherit' }); | |
child.on('close', function() { | |
childClosed = true; | |
server.close(); | |
}); | |
}); | |
process.on('exit', function() { | |
assert(childClosed); | |
assert.equal(connections, 1); | |
}); | |
} | |
function child() { | |
var net = require('net'); | |
var conn = net.connect({ port: 1337 }); | |
var req = 'GET / HTTP/1.1\r\nHost: localhost:' + | |
1337 + '\r\nAccept: */*\r\n\r\n'; | |
req = new Array(10241).join(req); | |
conn.on('connect', function() { | |
write(); | |
}); | |
conn.on('drain', write); | |
function write() { | |
while (false !== conn.write(req, 'ascii')); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment