mirror of
https://github.com/nodejs/node.git
synced 2025-04-28 21:46:48 +00:00

Some checks failed
Coverage Linux (without intl) / coverage-linux-without-intl (push) Waiting to run
Coverage Linux / coverage-linux (push) Waiting to run
Coverage Windows / coverage-windows (push) Waiting to run
Test and upload documentation to artifacts / build-docs (push) Waiting to run
Linters / lint-addon-docs (push) Waiting to run
Linters / lint-cpp (push) Waiting to run
Linters / format-cpp (push) Waiting to run
Linters / lint-js-and-md (push) Waiting to run
Linters / lint-py (push) Waiting to run
Linters / lint-yaml (push) Waiting to run
Linters / lint-sh (push) Waiting to run
Linters / lint-codeowners (push) Waiting to run
Linters / lint-pr-url (push) Waiting to run
Linters / lint-readme (push) Waiting to run
Notify on Push / Notify on Force Push on `main` (push) Waiting to run
Notify on Push / Notify on Push on `main` that lacks metadata (push) Waiting to run
Scorecard supply-chain security / Scorecard analysis (push) Waiting to run
V8 patch update / v8-update (push) Has been cancelled
OpenSSL update / openssl-update (push) Has been cancelled
Timezone update / timezone_update (push) Has been cancelled
Add initiator stack trace in inspector network events, reflecting the location where the script created the request. The `http.client.request.created` event is closer to where user code creates the http request, and correctly reflects which script initiated the request. PR-URL: https://github.com/nodejs/node/pull/56805 Refs: https://github.com/nodejs/node/issues/53946 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Kohei Ueno <kohei.ueno119@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
208 lines
7.8 KiB
JavaScript
208 lines
7.8 KiB
JavaScript
// Flags: --inspect=0 --experimental-network-inspection
|
|
'use strict';
|
|
const common = require('../common');
|
|
|
|
common.skipIfInspectorDisabled();
|
|
|
|
const assert = require('node:assert');
|
|
const { addresses } = require('../common/internet');
|
|
const fixtures = require('../common/fixtures');
|
|
const http = require('node:http');
|
|
const https = require('node:https');
|
|
const inspector = require('node:inspector/promises');
|
|
|
|
// Disable certificate validation for the global fetch.
|
|
const undici = require('../../deps/undici/src/index.js');
|
|
undici.setGlobalDispatcher(new undici.Agent({
|
|
connect: {
|
|
rejectUnauthorized: false,
|
|
},
|
|
}));
|
|
|
|
const session = new inspector.Session();
|
|
session.connect();
|
|
|
|
const requestHeaders = [
|
|
['accept-language', 'en-US'],
|
|
['cookie', 'k1=v1'],
|
|
['cookie', 'k2=v2'],
|
|
['age', 1000],
|
|
['x-header1', 'value1'],
|
|
['x-header1', 'value2'],
|
|
];
|
|
|
|
const setResponseHeaders = (res) => {
|
|
res.setHeader('server', 'node');
|
|
res.setHeader('etag', 12345);
|
|
res.setHeader('Set-Cookie', ['key1=value1', 'key2=value2']);
|
|
res.setHeader('x-header2', ['value1', 'value2']);
|
|
};
|
|
|
|
const handleRequest = (req, res) => {
|
|
const path = req.url;
|
|
switch (path) {
|
|
case '/hello-world':
|
|
setResponseHeaders(res);
|
|
res.writeHead(200);
|
|
res.end('hello world\n');
|
|
break;
|
|
default:
|
|
assert(false, `Unexpected path: ${path}`);
|
|
}
|
|
};
|
|
|
|
const httpServer = http.createServer(handleRequest);
|
|
|
|
const httpsServer = https.createServer({
|
|
key: fixtures.readKey('agent1-key.pem'),
|
|
cert: fixtures.readKey('agent1-cert.pem')
|
|
}, handleRequest);
|
|
|
|
const terminate = () => {
|
|
session.disconnect();
|
|
httpServer.close();
|
|
httpsServer.close();
|
|
inspector.close();
|
|
};
|
|
|
|
function findFrameInInitiator(scriptName, initiator) {
|
|
const frame = initiator.stack.callFrames.find((it) => {
|
|
return it.url === scriptName;
|
|
});
|
|
return frame;
|
|
}
|
|
|
|
const testHttpGet = () => new Promise((resolve, reject) => {
|
|
session.on('Network.requestWillBeSent', common.mustCall(({ params }) => {
|
|
assert.ok(params.requestId.startsWith('node-network-event-'));
|
|
assert.strictEqual(params.request.url, `http://127.0.0.1:${httpServer.address().port}/hello-world`);
|
|
assert.strictEqual(params.request.method, 'GET');
|
|
assert.strictEqual(typeof params.request.headers, 'object');
|
|
assert.strictEqual(params.request.headers['accept-language'], 'en-US');
|
|
assert.strictEqual(params.request.headers.cookie, 'k1=v1; k2=v2');
|
|
assert.strictEqual(params.request.headers.age, '1000');
|
|
assert.strictEqual(params.request.headers['x-header1'], 'value1, value2');
|
|
assert.strictEqual(typeof params.timestamp, 'number');
|
|
assert.strictEqual(typeof params.wallTime, 'number');
|
|
|
|
assert.strictEqual(typeof params.initiator, 'object');
|
|
assert.strictEqual(params.initiator.type, 'script');
|
|
assert.ok(findFrameInInitiator(__filename, params.initiator));
|
|
}));
|
|
session.on('Network.responseReceived', common.mustCall(({ params }) => {
|
|
assert.ok(params.requestId.startsWith('node-network-event-'));
|
|
assert.strictEqual(typeof params.timestamp, 'number');
|
|
assert.strictEqual(params.type, 'Fetch');
|
|
assert.strictEqual(params.response.status, 200);
|
|
assert.strictEqual(params.response.statusText, 'OK');
|
|
assert.strictEqual(params.response.url, `http://127.0.0.1:${httpServer.address().port}/hello-world`);
|
|
assert.strictEqual(typeof params.response.headers, 'object');
|
|
assert.strictEqual(params.response.headers.server, 'node');
|
|
assert.strictEqual(params.response.headers.etag, '12345');
|
|
assert.strictEqual(params.response.headers['Set-Cookie'], 'key1=value1\nkey2=value2');
|
|
assert.strictEqual(params.response.headers['x-header2'], 'value1, value2');
|
|
}));
|
|
session.on('Network.loadingFinished', common.mustCall(({ params }) => {
|
|
assert.ok(params.requestId.startsWith('node-network-event-'));
|
|
assert.strictEqual(typeof params.timestamp, 'number');
|
|
resolve();
|
|
}));
|
|
|
|
fetch(`http://127.0.0.1:${httpServer.address().port}/hello-world`, {
|
|
headers: requestHeaders,
|
|
}).then(common.mustCall());
|
|
});
|
|
|
|
const testHttpsGet = () => new Promise((resolve, reject) => {
|
|
session.on('Network.requestWillBeSent', common.mustCall(({ params }) => {
|
|
assert.ok(params.requestId.startsWith('node-network-event-'));
|
|
assert.strictEqual(params.request.url, `https://127.0.0.1:${httpsServer.address().port}/hello-world`);
|
|
assert.strictEqual(params.request.method, 'GET');
|
|
assert.strictEqual(typeof params.request.headers, 'object');
|
|
assert.strictEqual(params.request.headers['accept-language'], 'en-US');
|
|
assert.strictEqual(params.request.headers.cookie, 'k1=v1; k2=v2');
|
|
assert.strictEqual(params.request.headers.age, '1000');
|
|
assert.strictEqual(params.request.headers['x-header1'], 'value1, value2');
|
|
assert.strictEqual(typeof params.timestamp, 'number');
|
|
assert.strictEqual(typeof params.wallTime, 'number');
|
|
}));
|
|
session.on('Network.responseReceived', common.mustCall(({ params }) => {
|
|
assert.ok(params.requestId.startsWith('node-network-event-'));
|
|
assert.strictEqual(typeof params.timestamp, 'number');
|
|
assert.strictEqual(params.type, 'Fetch');
|
|
assert.strictEqual(params.response.status, 200);
|
|
assert.strictEqual(params.response.statusText, 'OK');
|
|
assert.strictEqual(params.response.url, `https://127.0.0.1:${httpsServer.address().port}/hello-world`);
|
|
assert.strictEqual(typeof params.response.headers, 'object');
|
|
assert.strictEqual(params.response.headers.server, 'node');
|
|
assert.strictEqual(params.response.headers.etag, '12345');
|
|
assert.strictEqual(params.response.headers['Set-Cookie'], 'key1=value1\nkey2=value2');
|
|
assert.strictEqual(params.response.headers['x-header2'], 'value1, value2');
|
|
}));
|
|
session.on('Network.loadingFinished', common.mustCall(({ params }) => {
|
|
assert.ok(params.requestId.startsWith('node-network-event-'));
|
|
assert.strictEqual(typeof params.timestamp, 'number');
|
|
resolve();
|
|
}));
|
|
|
|
fetch(`https://127.0.0.1:${httpsServer.address().port}/hello-world`, {
|
|
headers: requestHeaders,
|
|
}).then(common.mustCall());
|
|
});
|
|
|
|
const testHttpError = () => new Promise((resolve, reject) => {
|
|
session.on('Network.requestWillBeSent', common.mustCall());
|
|
session.on('Network.loadingFailed', common.mustCall(({ params }) => {
|
|
assert.ok(params.requestId.startsWith('node-network-event-'));
|
|
assert.strictEqual(typeof params.timestamp, 'number');
|
|
assert.strictEqual(params.type, 'Fetch');
|
|
assert.strictEqual(typeof params.errorText, 'string');
|
|
resolve();
|
|
}));
|
|
session.on('Network.responseReceived', common.mustNotCall());
|
|
session.on('Network.loadingFinished', common.mustNotCall());
|
|
|
|
fetch(`http://${addresses.INVALID_HOST}`).catch(common.mustCall());
|
|
});
|
|
|
|
|
|
const testHttpsError = () => new Promise((resolve, reject) => {
|
|
session.on('Network.requestWillBeSent', common.mustCall());
|
|
session.on('Network.loadingFailed', common.mustCall(({ params }) => {
|
|
assert.ok(params.requestId.startsWith('node-network-event-'));
|
|
assert.strictEqual(typeof params.timestamp, 'number');
|
|
assert.strictEqual(params.type, 'Fetch');
|
|
assert.strictEqual(typeof params.errorText, 'string');
|
|
resolve();
|
|
}));
|
|
session.on('Network.responseReceived', common.mustNotCall());
|
|
session.on('Network.loadingFinished', common.mustNotCall());
|
|
|
|
fetch(`https://${addresses.INVALID_HOST}`).catch(common.mustCall());
|
|
});
|
|
|
|
const testNetworkInspection = async () => {
|
|
await testHttpGet();
|
|
session.removeAllListeners();
|
|
await testHttpsGet();
|
|
session.removeAllListeners();
|
|
await testHttpError();
|
|
session.removeAllListeners();
|
|
await testHttpsError();
|
|
session.removeAllListeners();
|
|
};
|
|
|
|
httpServer.listen(0, () => {
|
|
httpsServer.listen(0, async () => {
|
|
try {
|
|
await session.post('Network.enable');
|
|
await testNetworkInspection();
|
|
await session.post('Network.disable');
|
|
} catch (e) {
|
|
assert.fail(e);
|
|
} finally {
|
|
terminate();
|
|
}
|
|
});
|
|
});
|