1'use strict'; 2// Flags: --expose-internals 3const common = require('../common'); 4const initHooks = require('./init-hooks'); 5const { checkInvocations } = require('./hook-checks'); 6const assert = require('assert'); 7const { async_id_symbol } = require('internal/async_hooks').symbols; 8const http = require('http'); 9 10// Checks that the async resource used in init in case of a reused handle 11// is not reused. Test is based on parallel\test-async-hooks-http-agent.js. 12 13const hooks = initHooks(); 14hooks.enable(); 15 16const reqAsyncIds = []; 17let socket; 18let responses = 0; 19 20// Make sure a single socket is transparently reused for 2 requests. 21const agent = new http.Agent({ 22 keepAlive: true, 23 keepAliveMsecs: Infinity, 24 maxSockets: 1 25}); 26 27const verifyRequest = (idx) => (res) => { 28 reqAsyncIds[idx] = res.socket[async_id_symbol]; 29 assert.ok(reqAsyncIds[idx] > 0, `${reqAsyncIds[idx]} > 0`); 30 if (socket) { 31 // Check that both requests share their socket. 32 assert.strictEqual(res.socket, socket); 33 } else { 34 socket = res.socket; 35 } 36 37 res.on('data', common.mustCallAtLeast(() => {})); 38 res.on('end', common.mustCall(() => { 39 if (++responses === 2) { 40 // Clean up to let the event loop stop. 41 server.close(); 42 agent.destroy(); 43 } 44 })); 45}; 46 47const server = http.createServer(common.mustCall((req, res) => { 48 req.once('data', common.mustCallAtLeast(() => { 49 res.writeHead(200, { 'Content-Type': 'text/plain' }); 50 res.write('foo'); 51 })); 52 req.on('end', common.mustCall(() => { 53 res.end('bar'); 54 })); 55}, 2)).listen(0, common.mustCall(() => { 56 const port = server.address().port; 57 const payload = 'hello world'; 58 59 // First request. 60 const r1 = http.request({ 61 agent, port, method: 'POST' 62 }, common.mustCall(verifyRequest(0))); 63 r1.end(payload); 64 65 // Second request. Sent in parallel with the first one. 66 const r2 = http.request({ 67 agent, port, method: 'POST' 68 }, common.mustCall(verifyRequest(1))); 69 r2.end(payload); 70})); 71 72 73process.on('exit', onExit); 74 75function onExit() { 76 hooks.disable(); 77 hooks.sanityCheck(); 78 const activities = hooks.activities; 79 80 // Verify both invocations 81 const first = activities.filter((x) => x.uid === reqAsyncIds[0])[0]; 82 checkInvocations(first, { init: 1, destroy: 1 }, 'when process exits'); 83 84 const second = activities.filter((x) => x.uid === reqAsyncIds[1])[0]; 85 checkInvocations(second, { init: 1, destroy: 1 }, 'when process exits'); 86 87 // Verify reuse handle has been wrapped 88 assert.strictEqual(first.type, second.type); 89 assert.ok(first.handle !== second.handle, 'Resource reused'); 90 assert.ok(first.handle === second.handle.handle, 91 'Resource not wrapped correctly'); 92} 93