GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — inspector: report loadingFinished until the response data is consumed · nodejs/node@f185e8a

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • lib/internal
    • inspector_network_tracking.js
    • inspector
      • network.js
      • network_http.js
  • src
    • node_builtins.cc
  • test/parallel
    • test-inspector-network-domain.js
    • test-inspector-network-http.js
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎lib/internal/inspector/network.js‎

Copy file name to clipboard
+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
3+
const {
4+
NumberMAX_SAFE_INTEGER,
5+
Symbol,
6+
} = primordials;
7+
8+
const { now } = require('internal/perf/utils');
9+
const kInspectorRequestId = Symbol('kInspectorRequestId');
10+
11+
/**
12+
* Return a monotonically increasing time in seconds since an arbitrary point in the past.
13+
* @returns {number}
14+
*/
15+
function getMonotonicTime() {
16+
return now() / 1000;
17+
}
18+
19+
let requestId = 0;
20+
function getNextRequestId() {
21+
if (requestId === NumberMAX_SAFE_INTEGER) {
22+
requestId = 0;
23+
}
24+
return `node-network-event-${++requestId}`;
25+
};
26+
27+
module.exports = {
28+
kInspectorRequestId,
29+
getMonotonicTime,
30+
getNextRequestId,
31+
};
Collapse file

‎lib/internal/inspector/network_http.js‎

Copy file name to clipboard
+132Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
'use strict';
2+
3+
const {
4+
ArrayIsArray,
5+
DateNow,
6+
ObjectEntries,
7+
String,
8+
Symbol,
9+
} = primordials;
10+
11+
const {
12+
kInspectorRequestId,
13+
getMonotonicTime,
14+
getNextRequestId,
15+
} = require('internal/inspector/network');
16+
const dc = require('diagnostics_channel');
17+
const { Network } = require('inspector');
18+
19+
const kResourceType = 'Other';
20+
const kRequestUrl = Symbol('kRequestUrl');
21+
22+
// Convert a Headers object (Map<string, number | string | string[]>) to a plain object (Map<string, string>)
23+
const convertHeaderObject = (headers = {}) => {
24+
// The 'host' header that contains the host and port of the URL.
25+
let host;
26+
const dict = {};
27+
for (const { 0: key, 1: value } of ObjectEntries(headers)) {
28+
if (key.toLowerCase() === 'host') {
29+
host = value;
30+
}
31+
if (typeof value === 'string') {
32+
dict[key] = value;
33+
} else if (ArrayIsArray(value)) {
34+
if (key.toLowerCase() === 'cookie') dict[key] = value.join('; ');
35+
// ChromeDevTools frontend treats 'set-cookie' as a special case
36+
// https://github.com/ChromeDevTools/devtools-frontend/blob/4275917f84266ef40613db3c1784a25f902ea74e/front_end/core/sdk/NetworkRequest.ts#L1368
37+
else if (key.toLowerCase() === 'set-cookie') dict[key] = value.join('\n');
38+
else dict[key] = value.join(', ');
39+
} else {
40+
dict[key] = String(value);
41+
}
42+
}
43+
return [host, dict];
44+
};
45+
46+
/**
47+
* When a client request starts, emit Network.requestWillBeSent event.
48+
* https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-requestWillBeSent
49+
* @param {{ request: import('http').ClientRequest }} event
50+
*/
51+
function onClientRequestStart({ request }) {
52+
request[kInspectorRequestId] = getNextRequestId();
53+
54+
const { 0: host, 1: headers } = convertHeaderObject(request.getHeaders());
55+
const url = `${request.protocol}//${host}${request.path}`;
56+
request[kRequestUrl] = url;
57+
58+
Network.requestWillBeSent({
59+
requestId: request[kInspectorRequestId],
60+
timestamp: getMonotonicTime(),
61+
wallTime: DateNow(),
62+
request: {
63+
url,
64+
method: request.method,
65+
headers,
66+
},
67+
});
68+
}
69+
70+
/**
71+
* When a client request errors, emit Network.loadingFailed event.
72+
* https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-loadingFailed
73+
* @param {{ request: import('http').ClientRequest, error: any }} event
74+
*/
75+
function onClientRequestError({ request, error }) {
76+
if (typeof request[kInspectorRequestId] !== 'string') {
77+
return;
78+
}
79+
Network.loadingFailed({
80+
requestId: request[kInspectorRequestId],
81+
timestamp: getMonotonicTime(),
82+
type: kResourceType,
83+
errorText: error.message,
84+
});
85+
}
86+
87+
/**
88+
* When response headers are received, emit Network.responseReceived event.
89+
* https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-responseReceived
90+
* @param {{ request: import('http').ClientRequest, error: any }} event
91+
*/
92+
function onClientResponseFinish({ request, response }) {
93+
if (typeof request[kInspectorRequestId] !== 'string') {
94+
return;
95+
}
96+
Network.responseReceived({
97+
requestId: request[kInspectorRequestId],
98+
timestamp: getMonotonicTime(),
99+
type: kResourceType,
100+
response: {
101+
url: request[kRequestUrl],
102+
status: response.statusCode,
103+
statusText: response.statusMessage ?? '',
104+
headers: convertHeaderObject(response.headers)[1],
105+
},
106+
});
107+
108+
// Wait until the response body is consumed by user code.
109+
response.once('end', () => {
110+
Network.loadingFinished({
111+
requestId: request[kInspectorRequestId],
112+
timestamp: getMonotonicTime(),
113+
});
114+
});
115+
}
116+
117+
function enable() {
118+
dc.subscribe('http.client.request.start', onClientRequestStart);
119+
dc.subscribe('http.client.request.error', onClientRequestError);
120+
dc.subscribe('http.client.response.finish', onClientResponseFinish);
121+
}
122+
123+
function disable() {
124+
dc.unsubscribe('http.client.request.start', onClientRequestStart);
125+
dc.unsubscribe('http.client.request.error', onClientRequestError);
126+
dc.unsubscribe('http.client.response.finish', onClientResponseFinish);
127+
}
128+
129+
module.exports = {
130+
enable,
131+
disable,
132+
};
Collapse file

‎lib/internal/inspector_network_tracking.js‎

Copy file name to clipboardExpand all lines: lib/internal/inspector_network_tracking.js
+6-93Lines changed: 6 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,15 @@
11
'use strict';
22

3-
const {
4-
ArrayIsArray,
5-
DateNow,
6-
ObjectEntries,
7-
String,
8-
} = primordials;
9-
10-
let dc;
11-
let Network;
12-
13-
let requestId = 0;
14-
const getNextRequestId = () => `node-network-event-${++requestId}`;
15-
16-
// Convert a Headers object (Map<string, number | string | string[]>) to a plain object (Map<string, string>)
17-
const headerObjectToDictionary = (headers = {}) => {
18-
const dict = {};
19-
for (const { 0: key, 1: value } of ObjectEntries(headers)) {
20-
if (typeof value === 'string') {
21-
dict[key] = value;
22-
} else if (ArrayIsArray(value)) {
23-
if (key.toLowerCase() === 'cookie') dict[key] = value.join('; ');
24-
// ChromeDevTools frontend treats 'set-cookie' as a special case
25-
// https://github.com/ChromeDevTools/devtools-frontend/blob/4275917f84266ef40613db3c1784a25f902ea74e/front_end/core/sdk/NetworkRequest.ts#L1368
26-
else if (key.toLowerCase() === 'set-cookie') dict[key] = value.join('\n');
27-
else dict[key] = value.join(', ');
28-
} else {
29-
dict[key] = String(value);
30-
}
31-
}
32-
return dict;
33-
};
34-
35-
function onClientRequestStart({ request }) {
36-
const url = `${request.protocol}//${request.host}${request.path}`;
37-
const wallTime = DateNow();
38-
const timestamp = wallTime / 1000;
39-
request._inspectorRequestId = getNextRequestId();
40-
Network.requestWillBeSent({
41-
requestId: request._inspectorRequestId,
42-
timestamp,
43-
wallTime,
44-
request: {
45-
url,
46-
method: request.method,
47-
headers: headerObjectToDictionary(request.getHeaders()),
48-
},
49-
});
50-
}
51-
52-
function onClientRequestError({ request, error }) {
53-
if (typeof request._inspectorRequestId !== 'string') {
54-
return;
55-
}
56-
const timestamp = DateNow() / 1000;
57-
Network.loadingFailed({
58-
requestId: request._inspectorRequestId,
59-
timestamp,
60-
type: 'Other',
61-
errorText: error.message,
62-
});
63-
}
64-
65-
function onClientResponseFinish({ request, response }) {
66-
if (typeof request._inspectorRequestId !== 'string') {
67-
return;
68-
}
69-
const url = `${request.protocol}//${request.host}${request.path}`;
70-
const timestamp = DateNow() / 1000;
71-
Network.responseReceived({
72-
requestId: request._inspectorRequestId,
73-
timestamp,
74-
type: 'Other',
75-
response: {
76-
url,
77-
status: response.statusCode,
78-
statusText: response.statusMessage ?? '',
79-
headers: headerObjectToDictionary(response.headers),
80-
},
81-
});
82-
Network.loadingFinished({
83-
requestId: request._inspectorRequestId,
84-
timestamp,
85-
});
86-
}
87-
883
function enable() {
89-
dc ??= require('diagnostics_channel');
90-
Network ??= require('inspector').Network;
91-
dc.subscribe('http.client.request.start', onClientRequestStart);
92-
dc.subscribe('http.client.request.error', onClientRequestError);
93-
dc.subscribe('http.client.response.finish', onClientResponseFinish);
4+
require('internal/inspector/network_http').enable();
5+
// TODO: add undici request/websocket tracking.
6+
// https://github.com/nodejs/node/issues/53946
947
}
958

969
function disable() {
97-
dc.unsubscribe('http.client.request.start', onClientRequestStart);
98-
dc.unsubscribe('http.client.request.error', onClientRequestError);
99-
dc.unsubscribe('http.client.response.finish', onClientResponseFinish);
10+
require('internal/inspector/network_http').disable();
11+
// TODO: add undici request/websocket tracking.
12+
// https://github.com/nodejs/node/issues/53946
10013
}
10114

10215
module.exports = {
Collapse file

‎src/node_builtins.cc‎

Copy file name to clipboardExpand all lines: src/node_builtins.cc
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ BuiltinLoader::BuiltinCategories BuiltinLoader::GetBuiltinCategories() const {
119119
builtin_categories.cannot_be_required = std::set<std::string> {
120120
#if !HAVE_INSPECTOR
121121
"inspector", "inspector/promises", "internal/util/inspector",
122+
"internal/inspector/network", "internal/inspector/network_http",
123+
"internal/inspector_async_hook", "internal/inspector_network_tracking",
122124
#endif // !HAVE_INSPECTOR
123125

124126
#if !NODE_USE_V8_PLATFORM || !defined(NODE_HAVE_I18N_SUPPORT)

0 commit comments

Comments
0 (0)
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.