11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ci// Here we are testing the HTTP server module's flood prevention mechanism. 51cb0ef41Sopenharmony_ci// When writeable.write returns false (ie the underlying send() indicated the 61cb0ef41Sopenharmony_ci// native buffer is full), the HTTP server cork()s the readable part of the 71cb0ef41Sopenharmony_ci// stream. This means that new requests will not be read (however request which 81cb0ef41Sopenharmony_ci// have already been read, but are awaiting processing will still be 91cb0ef41Sopenharmony_ci// processed). 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci// Normally when the writable stream emits a 'drain' event, the server then 121cb0ef41Sopenharmony_ci// uncorks the readable stream, although we aren't testing that part here. 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ci// The issue being tested exists in Node.js 0.10.20 and is resolved in 0.10.21 151cb0ef41Sopenharmony_ci// and newer. 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ciswitch (process.argv[2]) { 181cb0ef41Sopenharmony_ci case undefined: 191cb0ef41Sopenharmony_ci return parent(); 201cb0ef41Sopenharmony_ci case 'child': 211cb0ef41Sopenharmony_ci return child(); 221cb0ef41Sopenharmony_ci default: 231cb0ef41Sopenharmony_ci throw new Error(`Unexpected value: ${process.argv[2]}`); 241cb0ef41Sopenharmony_ci} 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cifunction parent() { 271cb0ef41Sopenharmony_ci const http = require('http'); 281cb0ef41Sopenharmony_ci const bigResponse = Buffer.alloc(10240, 'x'); 291cb0ef41Sopenharmony_ci let backloggedReqs = 0; 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci const server = http.createServer(function(req, res) { 321cb0ef41Sopenharmony_ci res.setHeader('content-length', bigResponse.length); 331cb0ef41Sopenharmony_ci if (!res.write(bigResponse)) { 341cb0ef41Sopenharmony_ci if (backloggedReqs === 0) { 351cb0ef41Sopenharmony_ci // Once the native buffer fills (ie write() returns false), the flood 361cb0ef41Sopenharmony_ci // prevention should kick in. 371cb0ef41Sopenharmony_ci // This means the stream should emit no more 'data' events. However we 381cb0ef41Sopenharmony_ci // may still be asked to process more requests if they were read before 391cb0ef41Sopenharmony_ci // the flood-prevention mechanism activated. 401cb0ef41Sopenharmony_ci setImmediate(() => { 411cb0ef41Sopenharmony_ci req.socket.on('data', common.mustNotCall('Unexpected data received')); 421cb0ef41Sopenharmony_ci }); 431cb0ef41Sopenharmony_ci } 441cb0ef41Sopenharmony_ci backloggedReqs++; 451cb0ef41Sopenharmony_ci } 461cb0ef41Sopenharmony_ci res.end(); 471cb0ef41Sopenharmony_ci }); 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci server.on('connection', common.mustCall()); 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci server.listen(0, function() { 521cb0ef41Sopenharmony_ci const spawn = require('child_process').spawn; 531cb0ef41Sopenharmony_ci const args = [__filename, 'child', this.address().port]; 541cb0ef41Sopenharmony_ci const child = spawn(process.execPath, args, { stdio: 'inherit' }); 551cb0ef41Sopenharmony_ci child.on('close', common.mustCall(function() { 561cb0ef41Sopenharmony_ci server.close(); 571cb0ef41Sopenharmony_ci })); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci server.setTimeout(200, common.mustCallAtLeast(function() { 601cb0ef41Sopenharmony_ci child.kill(); 611cb0ef41Sopenharmony_ci }, 1)); 621cb0ef41Sopenharmony_ci }); 631cb0ef41Sopenharmony_ci} 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_cifunction child() { 661cb0ef41Sopenharmony_ci const net = require('net'); 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci const port = +process.argv[3]; 691cb0ef41Sopenharmony_ci const conn = net.connect({ port }); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci let req = `GET / HTTP/1.1\r\nHost: localhost:${port}\r\nAccept: */*\r\n\r\n`; 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci req = req.repeat(10240); 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci conn.on('connect', write); 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci // `drain` should fire once and only once 781cb0ef41Sopenharmony_ci conn.on('drain', common.mustCall(write)); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci function write() { 811cb0ef41Sopenharmony_ci while (false !== conn.write(req, 'ascii')); 821cb0ef41Sopenharmony_ci } 831cb0ef41Sopenharmony_ci} 84