Skip to content

Commit e846860

Browse files
cola119targos
authored andcommitted
inspector: support Network.loadingFailed event
PR-URL: #54246 Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
1 parent e77ab7d commit e846860

8 files changed

+109
-0
lines changed

doc/api/inspector.md

+16
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,22 @@ This feature is only available with the `--experimental-network-inspection` flag
557557
Broadcasts the `Network.loadingFinished` event to connected frontends. This event indicates that
558558
HTTP request has finished loading.
559559

560+
### `inspector.Network.loadingFailed([params])`
561+
562+
<!-- YAML
563+
added:
564+
- REPLACEME
565+
-->
566+
567+
> Stability: 1 - Experimental
568+
569+
* `params` {Object}
570+
571+
This feature is only available with the `--experimental-network-inspection` flag enabled.
572+
573+
Broadcasts the `Network.loadingFailed` event to connected frontends. This event indicates that
574+
HTTP request has failed to load.
575+
560576
## Support of breakpoints
561577

562578
The Chrome DevTools Protocol [`Debugger` domain][] allows an

lib/inspector.js

+1
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ const Network = {
201201
requestWillBeSent: (params) => broadcastToFrontend('Network.requestWillBeSent', params),
202202
responseReceived: (params) => broadcastToFrontend('Network.responseReceived', params),
203203
loadingFinished: (params) => broadcastToFrontend('Network.loadingFinished', params),
204+
loadingFailed: (params) => broadcastToFrontend('Network.loadingFailed', params),
204205
};
205206

206207
module.exports = {

lib/internal/inspector_network_tracking.js

+15
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ function onClientRequestStart({ request }) {
4949
});
5050
}
5151

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+
5265
function onClientResponseFinish({ request, response }) {
5366
if (typeof request._inspectorRequestId !== 'string') {
5467
return;
@@ -80,11 +93,13 @@ function enable() {
8093
Network = require('inspector').Network;
8194
}
8295
dc.subscribe('http.client.request.start', onClientRequestStart);
96+
dc.subscribe('http.client.request.error', onClientRequestError);
8397
dc.subscribe('http.client.response.finish', onClientResponseFinish);
8498
}
8599

86100
function disable() {
87101
dc.unsubscribe('http.client.request.start', onClientRequestStart);
102+
dc.unsubscribe('http.client.request.error', onClientRequestError);
88103
dc.unsubscribe('http.client.response.finish', onClientResponseFinish);
89104
}
90105

src/inspector/network_agent.cc

+15
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ NetworkAgent::NetworkAgent(NetworkInspector* inspector)
3333
: inspector_(inspector) {
3434
event_notifier_map_["requestWillBeSent"] = &NetworkAgent::requestWillBeSent;
3535
event_notifier_map_["responseReceived"] = &NetworkAgent::responseReceived;
36+
event_notifier_map_["loadingFailed"] = &NetworkAgent::loadingFailed;
3637
event_notifier_map_["loadingFinished"] = &NetworkAgent::loadingFinished;
3738
}
3839

@@ -117,6 +118,20 @@ void NetworkAgent::responseReceived(
117118
createResponse(url, status, statusText, std::move(headers)));
118119
}
119120

121+
void NetworkAgent::loadingFailed(
122+
std::unique_ptr<protocol::DictionaryValue> params) {
123+
String request_id;
124+
params->getString("requestId", &request_id);
125+
double timestamp;
126+
params->getDouble("timestamp", &timestamp);
127+
String type;
128+
params->getString("type", &type);
129+
String error_text;
130+
params->getString("errorText", &error_text);
131+
132+
frontend_->loadingFailed(request_id, timestamp, type, error_text);
133+
}
134+
120135
void NetworkAgent::loadingFinished(
121136
std::unique_ptr<protocol::DictionaryValue> params) {
122137
String request_id;

src/inspector/network_agent.h

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ class NetworkAgent : public Network::Backend {
2929

3030
void responseReceived(std::unique_ptr<protocol::DictionaryValue> params);
3131

32+
void loadingFailed(std::unique_ptr<protocol::DictionaryValue> params);
33+
3234
void loadingFinished(std::unique_ptr<protocol::DictionaryValue> params);
3335

3436
private:

src/inspector/node_protocol.pdl

+11
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,17 @@ experimental domain Network
180180
# Response data.
181181
Response response
182182

183+
event loadingFailed
184+
parameters
185+
# Request identifier.
186+
RequestId requestId
187+
# Timestamp.
188+
MonotonicTime timestamp
189+
# Resource type.
190+
ResourceType type
191+
# Error message.
192+
string errorText
193+
183194
event loadingFinished
184195
parameters
185196
# Request identifier.

test/parallel/test-inspector-emit-protocol-event.js

+9
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ const EXPECTED_EVENTS = {
6262
timestamp: 1000,
6363
}
6464
},
65+
{
66+
name: 'loadingFailed',
67+
params: {
68+
requestId: 'request-id-1',
69+
timestamp: 1000,
70+
type: 'Document',
71+
errorText: 'Failed to load resource'
72+
}
73+
},
6574
]
6675
};
6776

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

+40
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const common = require('../common');
55
common.skipIfInspectorDisabled();
66

77
const assert = require('node:assert');
8+
const { addresses } = require('../common/internet');
89
const fixtures = require('../common/fixtures');
910
const http = require('node:http');
1011
const https = require('node:https');
@@ -144,11 +145,50 @@ const testHttpsGet = () => new Promise((resolve, reject) => {
144145
}, common.mustCall());
145146
});
146147

148+
const testHttpError = () => new Promise((resolve, reject) => {
149+
session.on('Network.requestWillBeSent', common.mustCall());
150+
session.on('Network.loadingFailed', common.mustCall(({ params }) => {
151+
assert.ok(params.requestId.startsWith('node-network-event-'));
152+
assert.strictEqual(typeof params.timestamp, 'number');
153+
assert.strictEqual(params.type, 'Other');
154+
assert.strictEqual(typeof params.errorText, 'string');
155+
resolve();
156+
}));
157+
session.on('Network.responseReceived', common.mustNotCall());
158+
session.on('Network.loadingFinished', common.mustNotCall());
159+
160+
http.get({
161+
host: addresses.INVALID_HOST,
162+
}, common.mustNotCall()).on('error', common.mustCall());
163+
});
164+
165+
166+
const testHttpsError = () => new Promise((resolve, reject) => {
167+
session.on('Network.requestWillBeSent', common.mustCall());
168+
session.on('Network.loadingFailed', common.mustCall(({ params }) => {
169+
assert.ok(params.requestId.startsWith('node-network-event-'));
170+
assert.strictEqual(typeof params.timestamp, 'number');
171+
assert.strictEqual(params.type, 'Other');
172+
assert.strictEqual(typeof params.errorText, 'string');
173+
resolve();
174+
}));
175+
session.on('Network.responseReceived', common.mustNotCall());
176+
session.on('Network.loadingFinished', common.mustNotCall());
177+
178+
https.get({
179+
host: addresses.INVALID_HOST,
180+
}, common.mustNotCall()).on('error', common.mustCall());
181+
});
182+
147183
const testNetworkInspection = async () => {
148184
await testHttpGet();
149185
session.removeAllListeners();
150186
await testHttpsGet();
151187
session.removeAllListeners();
188+
await testHttpError();
189+
session.removeAllListeners();
190+
await testHttpsError();
191+
session.removeAllListeners();
152192
};
153193

154194
httpServer.listen(0, () => {

0 commit comments

Comments
 (0)