1'use strict'; 2const common = require('../common'); 3 4// Here we are testing the HTTP server module's flood prevention mechanism. 5// When writeable.write returns false (ie the underlying send() indicated the 6// native buffer is full), the HTTP server cork()s the readable part of the 7// stream. This means that new requests will not be read (however request which 8// have already been read, but are awaiting processing will still be 9// processed). 10 11// Normally when the writable stream emits a 'drain' event, the server then 12// uncorks the readable stream, although we aren't testing that part here. 13 14// The issue being tested exists in Node.js 0.10.20 and is resolved in 0.10.21 15// and newer. 16 17switch (process.argv[2]) { 18 case undefined: 19 return parent(); 20 case 'child': 21 return child(); 22 default: 23 throw new Error(`Unexpected value: ${process.argv[2]}`); 24} 25 26function parent() { 27 const http = require('http'); 28 const bigResponse = Buffer.alloc(10240, 'x'); 29 let backloggedReqs = 0; 30 31 const server = http.createServer(function(req, res) { 32 res.setHeader('content-length', bigResponse.length); 33 if (!res.write(bigResponse)) { 34 if (backloggedReqs === 0) { 35 // Once the native buffer fills (ie write() returns false), the flood 36 // prevention should kick in. 37 // This means the stream should emit no more 'data' events. However we 38 // may still be asked to process more requests if they were read before 39 // the flood-prevention mechanism activated. 40 setImmediate(() => { 41 req.socket.on('data', common.mustNotCall('Unexpected data received')); 42 }); 43 } 44 backloggedReqs++; 45 } 46 res.end(); 47 }); 48 49 server.on('connection', common.mustCall()); 50 51 server.listen(0, function() { 52 const spawn = require('child_process').spawn; 53 const args = [__filename, 'child', this.address().port]; 54 const child = spawn(process.execPath, args, { stdio: 'inherit' }); 55 child.on('close', common.mustCall(function() { 56 server.close(); 57 })); 58 59 server.setTimeout(200, common.mustCallAtLeast(function() { 60 child.kill(); 61 }, 1)); 62 }); 63} 64 65function child() { 66 const net = require('net'); 67 68 const port = +process.argv[3]; 69 const conn = net.connect({ port }); 70 71 let req = `GET / HTTP/1.1\r\nHost: localhost:${port}\r\nAccept: */*\r\n\r\n`; 72 73 req = req.repeat(10240); 74 75 conn.on('connect', write); 76 77 // `drain` should fire once and only once 78 conn.on('drain', common.mustCall(write)); 79 80 function write() { 81 while (false !== conn.write(req, 'ascii')); 82 } 83} 84