11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci// Flags: --expose-internals 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ciconst assert = require('assert'); 51cb0ef41Sopenharmony_ciconst { async_id_symbol } = require('internal/async_hooks').symbols; 61cb0ef41Sopenharmony_ciconst http = require('http'); 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci// Regression test for https://github.com/nodejs/node/issues/13325 91cb0ef41Sopenharmony_ci// Checks that an http.Agent properly asyncReset()s a reused socket handle, and 101cb0ef41Sopenharmony_ci// re-assigns the fresh async id to the reused `net.Socket` instance. 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci// Make sure a single socket is transparently reused for 2 requests. 131cb0ef41Sopenharmony_ciconst agent = new http.Agent({ 141cb0ef41Sopenharmony_ci keepAlive: true, 151cb0ef41Sopenharmony_ci keepAliveMsecs: Infinity, 161cb0ef41Sopenharmony_ci maxSockets: 1 171cb0ef41Sopenharmony_ci}); 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciconst server = http.createServer(common.mustCall((req, res) => { 201cb0ef41Sopenharmony_ci req.once('data', common.mustCallAtLeast(() => { 211cb0ef41Sopenharmony_ci res.writeHead(200, { 'Content-Type': 'text/plain' }); 221cb0ef41Sopenharmony_ci res.write('foo'); 231cb0ef41Sopenharmony_ci })); 241cb0ef41Sopenharmony_ci req.on('end', common.mustCall(() => { 251cb0ef41Sopenharmony_ci res.end('bar'); 261cb0ef41Sopenharmony_ci })); 271cb0ef41Sopenharmony_ci}, 2)).listen(0, common.mustCall(() => { 281cb0ef41Sopenharmony_ci const port = server.address().port; 291cb0ef41Sopenharmony_ci const payload = 'hello world'; 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci // First request. This is useless except for adding a socket to the 321cb0ef41Sopenharmony_ci // agent’s pool for reuse. 331cb0ef41Sopenharmony_ci const r1 = http.request({ 341cb0ef41Sopenharmony_ci agent, port, method: 'POST' 351cb0ef41Sopenharmony_ci }, common.mustCall((res) => { 361cb0ef41Sopenharmony_ci // Remember which socket we used. 371cb0ef41Sopenharmony_ci const socket = res.socket; 381cb0ef41Sopenharmony_ci const asyncIdAtFirstRequest = socket[async_id_symbol]; 391cb0ef41Sopenharmony_ci assert.ok(asyncIdAtFirstRequest > 0, `${asyncIdAtFirstRequest} > 0`); 401cb0ef41Sopenharmony_ci // Check that request and response share their socket. 411cb0ef41Sopenharmony_ci assert.strictEqual(r1.socket, socket); 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci res.on('data', common.mustCallAtLeast()); 441cb0ef41Sopenharmony_ci res.on('end', common.mustCall(() => { 451cb0ef41Sopenharmony_ci // setImmediate() to give the agent time to register the freed socket. 461cb0ef41Sopenharmony_ci setImmediate(common.mustCall(() => { 471cb0ef41Sopenharmony_ci // The socket is free for reuse now. 481cb0ef41Sopenharmony_ci assert.strictEqual(socket[async_id_symbol], -1); 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci // Second request. To re-create the exact conditions from the 511cb0ef41Sopenharmony_ci // referenced issue, we use a POST request without chunked encoding 521cb0ef41Sopenharmony_ci // (hence the Content-Length header) and call .end() after the 531cb0ef41Sopenharmony_ci // response header has already been received. 541cb0ef41Sopenharmony_ci const r2 = http.request({ 551cb0ef41Sopenharmony_ci agent, port, method: 'POST', headers: { 561cb0ef41Sopenharmony_ci 'Content-Length': payload.length 571cb0ef41Sopenharmony_ci } 581cb0ef41Sopenharmony_ci }, common.mustCall((res) => { 591cb0ef41Sopenharmony_ci const asyncId = res.socket[async_id_symbol]; 601cb0ef41Sopenharmony_ci assert.ok(asyncId > 0, `${asyncId} > 0`); 611cb0ef41Sopenharmony_ci assert.strictEqual(r2.socket, socket); 621cb0ef41Sopenharmony_ci // Empty payload, to hit the “right” code path. 631cb0ef41Sopenharmony_ci r2.end(''); 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci res.on('data', common.mustCallAtLeast()); 661cb0ef41Sopenharmony_ci res.on('end', common.mustCall(() => { 671cb0ef41Sopenharmony_ci // Clean up to let the event loop stop. 681cb0ef41Sopenharmony_ci server.close(); 691cb0ef41Sopenharmony_ci agent.destroy(); 701cb0ef41Sopenharmony_ci })); 711cb0ef41Sopenharmony_ci })); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci // Schedule a payload to be written immediately, but do not end the 741cb0ef41Sopenharmony_ci // request just yet. 751cb0ef41Sopenharmony_ci r2.write(payload); 761cb0ef41Sopenharmony_ci })); 771cb0ef41Sopenharmony_ci })); 781cb0ef41Sopenharmony_ci })); 791cb0ef41Sopenharmony_ci r1.end(payload); 801cb0ef41Sopenharmony_ci})); 81