Skip to content

Commit be00058

Browse files
legendecastargos
authored andcommitted
inspector: add Network.Initiator in inspector protocol
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: #56805 Refs: #53946 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Kohei Ueno <[email protected]> Reviewed-By: Yagiz Nizipli <[email protected]>
1 parent 63611d0 commit be00058

12 files changed

+92
-15
lines changed

lib/internal/inspector/network_http.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ const convertHeaderObject = (headers = {}) => {
4444
};
4545

4646
/**
47-
* When a client request starts, emit Network.requestWillBeSent event.
47+
* When a client request is created, emit Network.requestWillBeSent event.
4848
* https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-requestWillBeSent
4949
* @param {{ request: import('http').ClientRequest }} event
5050
*/
51-
function onClientRequestStart({ request }) {
51+
function onClientRequestCreated({ request }) {
5252
request[kInspectorRequestId] = getNextRequestId();
5353

5454
const { 0: host, 1: headers } = convertHeaderObject(request.getHeaders());
@@ -115,13 +115,13 @@ function onClientResponseFinish({ request, response }) {
115115
}
116116

117117
function enable() {
118-
dc.subscribe('http.client.request.start', onClientRequestStart);
118+
dc.subscribe('http.client.request.created', onClientRequestCreated);
119119
dc.subscribe('http.client.request.error', onClientRequestError);
120120
dc.subscribe('http.client.response.finish', onClientResponseFinish);
121121
}
122122

123123
function disable() {
124-
dc.unsubscribe('http.client.request.start', onClientRequestStart);
124+
dc.unsubscribe('http.client.request.created', onClientRequestCreated);
125125
dc.unsubscribe('http.client.request.error', onClientRequestError);
126126
dc.unsubscribe('http.client.response.finish', onClientResponseFinish);
127127
}

lib/internal/inspector/network_undici.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,10 @@ function enable() {
129129
}
130130

131131
function disable() {
132-
dc.subscribe('undici:request:create', onClientRequestStart);
133-
dc.subscribe('undici:request:error', onClientRequestError);
134-
dc.subscribe('undici:request:headers', onClientResponseHeaders);
135-
dc.subscribe('undici:request:trailers', onClientResponseFinish);
132+
dc.unsubscribe('undici:request:create', onClientRequestStart);
133+
dc.unsubscribe('undici:request:error', onClientRequestError);
134+
dc.unsubscribe('undici:request:headers', onClientResponseHeaders);
135+
dc.unsubscribe('undici:request:trailers', onClientResponseFinish);
136136
}
137137

138138
module.exports = {

src/inspector/network_agent.cc

+11-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ std::unique_ptr<Network::Response> createResponse(
2929
.build();
3030
}
3131

32-
NetworkAgent::NetworkAgent(NetworkInspector* inspector)
33-
: inspector_(inspector) {
32+
NetworkAgent::NetworkAgent(NetworkInspector* inspector,
33+
v8_inspector::V8Inspector* v8_inspector)
34+
: inspector_(inspector), v8_inspector_(v8_inspector) {
3435
event_notifier_map_["requestWillBeSent"] = &NetworkAgent::requestWillBeSent;
3536
event_notifier_map_["responseReceived"] = &NetworkAgent::responseReceived;
3637
event_notifier_map_["loadingFailed"] = &NetworkAgent::loadingFailed;
@@ -75,6 +76,13 @@ void NetworkAgent::requestWillBeSent(
7576
String method;
7677
request->getString("method", &method);
7778

79+
std::unique_ptr<Network::Initiator> initiator =
80+
Network::Initiator::create()
81+
.setType(Network::Initiator::TypeEnum::Script)
82+
.setStack(
83+
v8_inspector_->captureStackTrace(true)->buildInspectorObject(0))
84+
.build();
85+
7886
ErrorSupport errors;
7987
errors.Push();
8088
errors.SetName("headers");
@@ -86,6 +94,7 @@ void NetworkAgent::requestWillBeSent(
8694

8795
frontend_->requestWillBeSent(request_id,
8896
createRequest(url, method, std::move(headers)),
97+
std::move(initiator),
8998
timestamp,
9099
wall_time);
91100
}

src/inspector/network_agent.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ namespace protocol {
1414

1515
class NetworkAgent : public Network::Backend {
1616
public:
17-
explicit NetworkAgent(NetworkInspector* inspector);
17+
explicit NetworkAgent(NetworkInspector* inspector,
18+
v8_inspector::V8Inspector* v8_inspector);
1819

1920
void Wire(UberDispatcher* dispatcher);
2021

@@ -35,6 +36,7 @@ class NetworkAgent : public Network::Backend {
3536

3637
private:
3738
NetworkInspector* inspector_;
39+
v8_inspector::V8Inspector* v8_inspector_;
3840
std::shared_ptr<Network::Frontend> frontend_;
3941
using EventNotifier =
4042
void (NetworkAgent::*)(std::unique_ptr<protocol::DictionaryValue>);

src/inspector/network_inspector.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
namespace node {
44
namespace inspector {
55

6-
NetworkInspector::NetworkInspector(Environment* env)
6+
NetworkInspector::NetworkInspector(Environment* env,
7+
v8_inspector::V8Inspector* v8_inspector)
78
: enabled_(false), env_(env) {
8-
network_agent_ = std::make_unique<protocol::NetworkAgent>(this);
9+
network_agent_ = std::make_unique<protocol::NetworkAgent>(this, v8_inspector);
910
}
1011
NetworkInspector::~NetworkInspector() {
1112
network_agent_.reset();

src/inspector/network_inspector.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ namespace inspector {
1111

1212
class NetworkInspector {
1313
public:
14-
explicit NetworkInspector(Environment* env);
14+
explicit NetworkInspector(Environment* env,
15+
v8_inspector::V8Inspector* v8_inspector);
1516
~NetworkInspector();
1617

1718
void Wire(protocol::UberDispatcher* dispatcher);

src/inspector/node_inspector.gypi

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
'action_name': 'node_protocol_generated_sources',
9898
'inputs': [
9999
'node_protocol_config.json',
100+
'node_protocol.pdl',
100101
'<(SHARED_INTERMEDIATE_DIR)/src/node_protocol.json',
101102
'<@(node_protocol_files)',
102103
'<(protocol_tool_path)/code_generator.py',

src/inspector/node_protocol.pdl

+29
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ experimental domain NodeWorker
101101
# Partial support for Network domain of ChromeDevTools Protocol.
102102
# https://chromedevtools.github.io/devtools-protocol/tot/Network
103103
experimental domain Network
104+
depends on Runtime
105+
104106
# Resource type as it was perceived by the rendering engine.
105107
type ResourceType extends string
106108
enum
@@ -132,6 +134,31 @@ experimental domain Network
132134
# Monotonically increasing time in seconds since an arbitrary point in the past.
133135
type MonotonicTime extends number
134136

137+
# Information about the request initiator.
138+
type Initiator extends object
139+
properties
140+
# Type of this initiator.
141+
enum type
142+
parser
143+
script
144+
preload
145+
SignedExchange
146+
preflight
147+
other
148+
# Initiator JavaScript stack trace, set for Script only.
149+
# Requires the Debugger domain to be enabled.
150+
optional Runtime.StackTrace stack
151+
# Initiator URL, set for Parser type or for Script type (when script is importing module) or for SignedExchange type.
152+
optional string url
153+
# Initiator line number, set for Parser type or for Script type (when script is importing
154+
# module) (0-based).
155+
optional number lineNumber
156+
# Initiator column number, set for Parser type or for Script type (when script is importing
157+
# module) (0-based).
158+
optional number columnNumber
159+
# Set if another request triggered this request (e.g. preflight).
160+
optional RequestId requestId
161+
135162
# HTTP request data.
136163
type Request extends object
137164
properties
@@ -163,6 +190,8 @@ experimental domain Network
163190
RequestId requestId
164191
# Request data.
165192
Request request
193+
# Request initiator.
194+
Initiator initiator
166195
# Timestamp.
167196
MonotonicTime timestamp
168197
# Timestamp.

src/inspector/node_protocol_config.json

+11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@
55
"output": "node/inspector/protocol",
66
"namespace": ["node", "inspector", "protocol"]
77
},
8+
"imported": {
9+
"path": "../../deps/v8/include/js_protocol.pdl",
10+
"header": "<v8-inspector-protocol.h>",
11+
"namespace": ["v8_inspector", "protocol"],
12+
"options": [
13+
{
14+
"domain": "Runtime",
15+
"imported": ["StackTrace"]
16+
}
17+
]
18+
},
819
"exported": {
920
"package": "include/inspector",
1021
"output": "../../include/inspector",

src/inspector_agent.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel,
241241
}
242242
runtime_agent_ = std::make_unique<protocol::RuntimeAgent>();
243243
runtime_agent_->Wire(node_dispatcher_.get());
244-
network_inspector_ = std::make_unique<NetworkInspector>(env);
244+
network_inspector_ =
245+
std::make_unique<NetworkInspector>(env, inspector.get());
245246
network_inspector_->Wire(node_dispatcher_.get());
246247
}
247248

test/parallel/test-inspector-network-fetch.js

+11
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ const terminate = () => {
6565
inspector.close();
6666
};
6767

68+
function findFrameInInitiator(scriptName, initiator) {
69+
const frame = initiator.stack.callFrames.find((it) => {
70+
return it.url === scriptName;
71+
});
72+
return frame;
73+
}
74+
6875
const testHttpGet = () => new Promise((resolve, reject) => {
6976
session.on('Network.requestWillBeSent', common.mustCall(({ params }) => {
7077
assert.ok(params.requestId.startsWith('node-network-event-'));
@@ -77,6 +84,10 @@ const testHttpGet = () => new Promise((resolve, reject) => {
7784
assert.strictEqual(params.request.headers['x-header1'], 'value1, value2');
7885
assert.strictEqual(typeof params.timestamp, 'number');
7986
assert.strictEqual(typeof params.wallTime, 'number');
87+
88+
assert.strictEqual(typeof params.initiator, 'object');
89+
assert.strictEqual(params.initiator.type, 'script');
90+
assert.ok(findFrameInInitiator(__filename, params.initiator));
8091
}));
8192
session.on('Network.responseReceived', common.mustCall(({ params }) => {
8293
assert.ok(params.requestId.startsWith('node-network-event-'));

test/parallel/test-inspector-network-http.js

+11
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ const terminate = () => {
6464
inspector.close();
6565
};
6666

67+
function findFrameInInitiator(scriptName, initiator) {
68+
const frame = initiator.stack.callFrames.find((it) => {
69+
return it.url === scriptName;
70+
});
71+
return frame;
72+
}
73+
6774
function verifyRequestWillBeSent({ method, params }, expect) {
6875
assert.strictEqual(method, 'Network.requestWillBeSent');
6976

@@ -78,6 +85,10 @@ function verifyRequestWillBeSent({ method, params }, expect) {
7885
assert.strictEqual(typeof params.timestamp, 'number');
7986
assert.strictEqual(typeof params.wallTime, 'number');
8087

88+
assert.strictEqual(typeof params.initiator, 'object');
89+
assert.strictEqual(params.initiator.type, 'script');
90+
assert.ok(findFrameInInitiator(__filename, params.initiator));
91+
8192
return params;
8293
}
8394

0 commit comments

Comments
 (0)