11cb0ef41Sopenharmony_ci// Flags: --expose-internals 21cb0ef41Sopenharmony_ci'use strict'; 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ciconst assert = require('assert'); 51cb0ef41Sopenharmony_ciconst http = require('http'); 61cb0ef41Sopenharmony_ciconst net = require('net'); 71cb0ef41Sopenharmony_ciconst MAX = +(process.argv[2] || 16 * 1024); // Command line option, or 16KB. 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciconst { getOptionValue } = require('internal/options'); 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ciconsole.log('pid is', process.pid); 121cb0ef41Sopenharmony_ciconsole.log('max header size is', getOptionValue('--max-http-header-size')); 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ci// Verify that we cannot receive more than 16KB of headers. 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_cifunction once(cb) { 171cb0ef41Sopenharmony_ci let called = false; 181cb0ef41Sopenharmony_ci return () => { 191cb0ef41Sopenharmony_ci if (!called) { 201cb0ef41Sopenharmony_ci called = true; 211cb0ef41Sopenharmony_ci cb(); 221cb0ef41Sopenharmony_ci } 231cb0ef41Sopenharmony_ci }; 241cb0ef41Sopenharmony_ci} 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cifunction finished(client, callback) { 271cb0ef41Sopenharmony_ci ['abort', 'error', 'end'].forEach((e) => { 281cb0ef41Sopenharmony_ci client.on(e, once(() => setImmediate(callback))); 291cb0ef41Sopenharmony_ci }); 301cb0ef41Sopenharmony_ci} 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_cifunction fillHeaders(headers, currentSize, valid = false) { 331cb0ef41Sopenharmony_ci // `llhttp` counts actual header name/value sizes, excluding the whitespace 341cb0ef41Sopenharmony_ci // and stripped chars. 351cb0ef41Sopenharmony_ci // OK, Content-Length, 0, X-CRASH, aaa... 361cb0ef41Sopenharmony_ci headers += 'a'.repeat(MAX - currentSize); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci // Generate valid headers 391cb0ef41Sopenharmony_ci if (valid) { 401cb0ef41Sopenharmony_ci headers = headers.slice(0, -1); 411cb0ef41Sopenharmony_ci } 421cb0ef41Sopenharmony_ci return headers + '\r\n\r\n'; 431cb0ef41Sopenharmony_ci} 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_cifunction writeHeaders(socket, headers) { 461cb0ef41Sopenharmony_ci const array = []; 471cb0ef41Sopenharmony_ci const chunkSize = 100; 481cb0ef41Sopenharmony_ci let last = 0; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci for (let i = 0; i < headers.length / chunkSize; i++) { 511cb0ef41Sopenharmony_ci const current = (i + 1) * chunkSize; 521cb0ef41Sopenharmony_ci array.push(headers.slice(last, current)); 531cb0ef41Sopenharmony_ci last = current; 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci // Safety check we are chunking correctly 571cb0ef41Sopenharmony_ci assert.strictEqual(array.join(''), headers); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci next(); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci function next() { 621cb0ef41Sopenharmony_ci if (socket.destroyed) { 631cb0ef41Sopenharmony_ci console.log('socket was destroyed early, data left to write:', 641cb0ef41Sopenharmony_ci array.join('').length); 651cb0ef41Sopenharmony_ci return; 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci const chunk = array.shift(); 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci if (chunk) { 711cb0ef41Sopenharmony_ci console.log('writing chunk of size', chunk.length); 721cb0ef41Sopenharmony_ci socket.write(chunk, next); 731cb0ef41Sopenharmony_ci } else { 741cb0ef41Sopenharmony_ci socket.end(); 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci } 771cb0ef41Sopenharmony_ci} 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_cifunction test1() { 801cb0ef41Sopenharmony_ci console.log('test1'); 811cb0ef41Sopenharmony_ci let headers = 821cb0ef41Sopenharmony_ci 'HTTP/1.1 200 OK\r\n' + 831cb0ef41Sopenharmony_ci 'Content-Length: 0\r\n' + 841cb0ef41Sopenharmony_ci 'X-CRASH: '; 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci // OK, Content-Length, 0, X-CRASH, aaa... 871cb0ef41Sopenharmony_ci const currentSize = 2 + 14 + 1 + 7; 881cb0ef41Sopenharmony_ci headers = fillHeaders(headers, currentSize); 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci const server = net.createServer((sock) => { 911cb0ef41Sopenharmony_ci sock.once('data', () => { 921cb0ef41Sopenharmony_ci writeHeaders(sock, headers); 931cb0ef41Sopenharmony_ci sock.resume(); 941cb0ef41Sopenharmony_ci }); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci // The socket might error but that's ok 971cb0ef41Sopenharmony_ci sock.on('error', () => {}); 981cb0ef41Sopenharmony_ci }); 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci server.listen(0, common.mustCall(() => { 1011cb0ef41Sopenharmony_ci const port = server.address().port; 1021cb0ef41Sopenharmony_ci const client = http.get({ port: port }, common.mustNotCall()); 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci client.on('error', common.mustCall((err) => { 1051cb0ef41Sopenharmony_ci assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW'); 1061cb0ef41Sopenharmony_ci server.close(test2); 1071cb0ef41Sopenharmony_ci })); 1081cb0ef41Sopenharmony_ci })); 1091cb0ef41Sopenharmony_ci} 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ciconst test2 = common.mustCall(() => { 1121cb0ef41Sopenharmony_ci console.log('test2'); 1131cb0ef41Sopenharmony_ci let headers = 1141cb0ef41Sopenharmony_ci 'GET / HTTP/1.1\r\n' + 1151cb0ef41Sopenharmony_ci 'Host: localhost\r\n' + 1161cb0ef41Sopenharmony_ci 'Agent: nod2\r\n' + 1171cb0ef41Sopenharmony_ci 'X-CRASH: '; 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci // /, Host, localhost, Agent, node, X-CRASH, a... 1201cb0ef41Sopenharmony_ci const currentSize = 1 + 4 + 9 + 5 + 4 + 7; 1211cb0ef41Sopenharmony_ci headers = fillHeaders(headers, currentSize); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci const server = http.createServer(common.mustNotCall()); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci server.once('clientError', common.mustCall((err) => { 1261cb0ef41Sopenharmony_ci assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW'); 1271cb0ef41Sopenharmony_ci })); 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci server.listen(0, common.mustCall(() => { 1301cb0ef41Sopenharmony_ci const client = net.connect(server.address().port); 1311cb0ef41Sopenharmony_ci client.on('connect', () => { 1321cb0ef41Sopenharmony_ci writeHeaders(client, headers); 1331cb0ef41Sopenharmony_ci client.resume(); 1341cb0ef41Sopenharmony_ci }); 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci finished(client, common.mustCall(() => { 1371cb0ef41Sopenharmony_ci server.close(test3); 1381cb0ef41Sopenharmony_ci })); 1391cb0ef41Sopenharmony_ci })); 1401cb0ef41Sopenharmony_ci}); 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ciconst test3 = common.mustCall(() => { 1431cb0ef41Sopenharmony_ci console.log('test3'); 1441cb0ef41Sopenharmony_ci let headers = 1451cb0ef41Sopenharmony_ci 'GET / HTTP/1.1\r\n' + 1461cb0ef41Sopenharmony_ci 'Host: localhost\r\n' + 1471cb0ef41Sopenharmony_ci 'Agent: nod3\r\n' + 1481cb0ef41Sopenharmony_ci 'X-CRASH: '; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci // /, Host, localhost, Agent, node, X-CRASH, a... 1511cb0ef41Sopenharmony_ci const currentSize = 1 + 4 + 9 + 5 + 4 + 7; 1521cb0ef41Sopenharmony_ci headers = fillHeaders(headers, currentSize, true); 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci console.log('writing', headers.length); 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci const server = http.createServer(common.mustCall((req, res) => { 1571cb0ef41Sopenharmony_ci res.end('hello from test3 server'); 1581cb0ef41Sopenharmony_ci server.close(); 1591cb0ef41Sopenharmony_ci })); 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci server.on('clientError', (err) => { 1621cb0ef41Sopenharmony_ci console.log(err.code); 1631cb0ef41Sopenharmony_ci if (err.code === 'HPE_HEADER_OVERFLOW') { 1641cb0ef41Sopenharmony_ci console.log(err.rawPacket.toString('hex')); 1651cb0ef41Sopenharmony_ci } 1661cb0ef41Sopenharmony_ci }); 1671cb0ef41Sopenharmony_ci server.on('clientError', common.mustNotCall()); 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci server.listen(0, common.mustCall(() => { 1701cb0ef41Sopenharmony_ci const client = net.connect(server.address().port); 1711cb0ef41Sopenharmony_ci client.on('connect', () => { 1721cb0ef41Sopenharmony_ci writeHeaders(client, headers); 1731cb0ef41Sopenharmony_ci client.resume(); 1741cb0ef41Sopenharmony_ci }); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci client.pipe(process.stdout); 1771cb0ef41Sopenharmony_ci })); 1781cb0ef41Sopenharmony_ci}); 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_citest1(); 181