Skip to content

Commit 5656be6

Browse files
committed
inspector: add initial support for network inspection
1 parent 4c730ae commit 5656be6

10 files changed

+491
-1
lines changed

lib/internal/process/pre_execution.js

+47
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const {
44
ArrayPrototypeForEach,
55
Date,
6+
DateNow,
67
DatePrototypeGetDate,
78
DatePrototypeGetFullYear,
89
DatePrototypeGetHours,
@@ -98,6 +99,7 @@ function prepareExecution(options) {
9899
const mainEntry = patchProcessObject(expandArgv1);
99100
setupTraceCategoryState();
100101
setupInspectorHooks();
102+
setupNetworkInspection();
101103
setupNavigator();
102104
setupWarningHandler();
103105
setupWebStorage();
@@ -438,6 +440,51 @@ function setupInspectorHooks() {
438440
}
439441
}
440442

443+
function setupNetworkInspection() {
444+
if (!internalBinding('config').hasInspector) {
445+
return;
446+
}
447+
const dc = require('diagnostics_channel');
448+
const {
449+
dataReceived,
450+
loadingFinished,
451+
requestWillBeSent,
452+
responseReceived,
453+
} = internalBinding('inspector');
454+
455+
let requestId = 0;
456+
const getNextRequestId = () => `node-network-event-${++requestId}`;
457+
458+
dc.subscribe('http.client.request.start', ({ request }) => {
459+
const url = `${request.protocol}//${request.host}${request.path}`;
460+
const wallTime = DateNow();
461+
const timestamp = wallTime / 1000;
462+
request._inspectorRequestId = getNextRequestId();
463+
requestWillBeSent(request._inspectorRequestId, url, request.method, timestamp, wallTime);
464+
});
465+
dc.subscribe('http.client.response.finish', ({ request, response }) => {
466+
responseReceived(request._inspectorRequestId, DateNow() / 1000);
467+
let responseString = '';
468+
const onData = (chunk) => {
469+
dataReceived(request._inspectorRequestId, DateNow() / 1000, chunk.length);
470+
responseString += chunk.toString();
471+
};
472+
response.on('data', onData);
473+
response.on('end', () => {
474+
loadingFinished(request._inspectorRequestId, responseString, DateNow() / 1000, responseString.length);
475+
response.removeListener('data', onData);
476+
});
477+
});
478+
479+
dc.subscribe('undici:request:create', ({ request }) => {
480+
const url = `${request.origin}${request.path}`;
481+
const wallTime = DateNow();
482+
const timestamp = wallTime / 1000;
483+
request._inspectorRequestId = getNextRequestId();
484+
requestWillBeSent(request._inspectorRequestId, url, request.method, timestamp, wallTime);
485+
});
486+
}
487+
441488
// In general deprecations are initialized wherever the APIs are implemented,
442489
// this is used to deprecate APIs implemented in C++ where the deprecation
443490
// utilities are not easily accessible.

src/inspector/network_agent.cc

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include "network_agent.h"
2+
3+
#include "inspector_agent.h"
4+
5+
namespace node {
6+
namespace inspector {
7+
namespace protocol {
8+
9+
std::unique_ptr<Network::Request> Request(const String& url,
10+
const String& method) {
11+
return Network::Request::create().setUrl(url).setMethod(method).build();
12+
}
13+
14+
NetworkAgent::NetworkAgent() {}
15+
16+
void NetworkAgent::Wire(UberDispatcher* dispatcher) {
17+
frontend_ = std::make_unique<Network::Frontend>(dispatcher->channel());
18+
Network::Dispatcher::wire(dispatcher, this);
19+
}
20+
21+
DispatchResponse NetworkAgent::getResponseBody(const String& in_requestId,
22+
String* out_body) {
23+
auto it = request_id_to_response_.find(in_requestId);
24+
if (it != request_id_to_response_.end()) {
25+
*out_body = it->second;
26+
request_id_to_response_.erase(it);
27+
}
28+
return DispatchResponse::OK();
29+
}
30+
31+
void NetworkAgent::requestWillBeSent(const String& request_id,
32+
const String& url,
33+
const String& method,
34+
double timestamp,
35+
double wall_time) {
36+
frontend_->requestWillBeSent(
37+
request_id, Request(url, method), timestamp, wall_time);
38+
}
39+
40+
void NetworkAgent::responseReceived(const String& request_id,
41+
double timestamp) {
42+
frontend_->responseReceived(request_id, timestamp);
43+
}
44+
45+
void NetworkAgent::dataReceived(const String& request_id,
46+
double timestamp,
47+
int data_length) {
48+
frontend_->dataReceived(request_id, timestamp, data_length);
49+
}
50+
51+
void NetworkAgent::loadingFinished(const String& request_id,
52+
const String& response,
53+
double timestamp,
54+
int encoded_data_length) {
55+
request_id_to_response_[request_id] = response;
56+
frontend_->loadingFinished(request_id, timestamp, encoded_data_length);
57+
}
58+
59+
} // namespace protocol
60+
} // namespace inspector
61+
} // namespace node

src/inspector/network_agent.h

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#ifndef SRC_INSPECTOR_NETWORK_AGENT_H_
2+
#define SRC_INSPECTOR_NETWORK_AGENT_H_
3+
4+
#include "node/inspector/protocol/Network.h"
5+
#include "v8.h"
6+
7+
#include <unordered_map>
8+
9+
namespace node {
10+
11+
namespace inspector {
12+
namespace protocol {
13+
14+
class NetworkAgent : public Network::Backend {
15+
public:
16+
NetworkAgent();
17+
18+
void Wire(UberDispatcher* dispatcher);
19+
20+
DispatchResponse getResponseBody(const String& in_requestId,
21+
String* out_body) override;
22+
23+
void requestWillBeSent(const String& request_id,
24+
const String& url,
25+
const String& method,
26+
double timestamp,
27+
double wall_time);
28+
29+
void responseReceived(const String& request_id, double timestamp);
30+
31+
void dataReceived(const String& request_id,
32+
double timestamp,
33+
int data_length);
34+
35+
void loadingFinished(const String& request_id,
36+
const String& response,
37+
double timestamp,
38+
int encoded_data_length);
39+
40+
private:
41+
std::shared_ptr<Network::Frontend> frontend_;
42+
std::unordered_map<String, String> request_id_to_response_;
43+
};
44+
45+
} // namespace protocol
46+
} // namespace inspector
47+
} // namespace node
48+
49+
#endif // SRC_INSPECTOR_NETWORK_AGENT_H_

src/inspector/node_inspector.gypi

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
'src/inspector/tracing_agent.h',
2424
'src/inspector/worker_agent.cc',
2525
'src/inspector/worker_agent.h',
26+
'src/inspector/network_agent.cc',
27+
'src/inspector/network_agent.h',
2628
'src/inspector/worker_inspector.cc',
2729
'src/inspector/worker_inspector.h',
2830
],
@@ -36,6 +38,8 @@
3638
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/NodeTracing.h',
3739
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/NodeRuntime.cpp',
3840
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/NodeRuntime.h',
41+
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Network.cpp',
42+
'<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Network.h',
3943
],
4044
'node_protocol_files': [
4145
'<(protocol_tool_path)/lib/Allocator_h.template',

src/inspector/node_protocol.pdl

+65
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,71 @@ experimental domain NodeWorker
9898
SessionID sessionId
9999
string message
100100

101+
# Partial support for Network domain of ChromeDevTools Protocol.
102+
# https://chromedevtools.github.io/devtools-protocol/tot/Network
103+
experimental domain Network
104+
# Unique request identifier.
105+
type RequestId extends string
106+
107+
# UTC time in seconds, counted from January 1, 1970.
108+
type TimeSinceEpoch extends number
109+
110+
# Monotonically increasing time in seconds since an arbitrary point in the past.
111+
type MonotonicTime extends number
112+
113+
# HTTP request data.
114+
type Request extends object
115+
properties
116+
string url
117+
string method
118+
119+
# Returns content served for the given request.
120+
command getResponseBody
121+
parameters
122+
# Identifier of the network request to get content for.
123+
RequestId requestId
124+
returns
125+
# Response body.
126+
string body
127+
128+
# Fired when page is about to send HTTP request.
129+
event requestWillBeSent
130+
parameters
131+
# Request identifier.
132+
RequestId requestId
133+
# Request data.
134+
Request request
135+
# Timestamp.
136+
MonotonicTime timestamp
137+
# Timestamp.
138+
TimeSinceEpoch wallTime
139+
140+
# Fired when HTTP response is available.
141+
event responseReceived
142+
parameters
143+
# Request identifier.
144+
RequestId requestId
145+
# Timestamp.
146+
MonotonicTime timestamp
147+
148+
event dataReceived
149+
parameters
150+
# Request identifier.
151+
RequestId requestId
152+
# Timestamp.
153+
MonotonicTime timestamp
154+
# Data chunk length.
155+
integer dataLength
156+
157+
event loadingFinished
158+
parameters
159+
# Request identifier.
160+
RequestId requestId
161+
# Timestamp.
162+
MonotonicTime timestamp
163+
# Total number of bytes received for this request.
164+
number encodedDataLength
165+
101166
# Support for inspecting node process state.
102167
experimental domain NodeRuntime
103168
# Enable the NodeRuntime events except by `NodeRuntime.waitingForDisconnect`.

src/inspector/node_string.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ String StringViewToUtf8(v8_inspector::StringView view) {
8484
String fromDouble(double d) {
8585
std::ostringstream stream;
8686
stream.imbue(std::locale::classic()); // Ignore current locale
87-
stream << d;
87+
stream << std::fixed << d;
8888
return stream.str();
8989
}
9090

0 commit comments

Comments
 (0)