Skip to content

Commit 499ab30

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

11 files changed

+473
-2
lines changed

lib/_http_client.js

+35-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
const {
2525
ArrayIsArray,
2626
Boolean,
27+
DateNow,
2728
Error,
2829
FunctionPrototypeCall,
2930
NumberIsFinite,
@@ -70,6 +71,7 @@ const {
7071
isTraceHTTPEnabled,
7172
traceBegin,
7273
traceEnd,
74+
getNextInspectorEventId,
7375
getNextTraceEventId,
7476
} = require('internal/http');
7577
const {
@@ -93,6 +95,14 @@ const {
9395
stopPerf,
9496
} = require('internal/perf/observe');
9597

98+
const {
99+
isEnabled: isInspectorEnabled,
100+
requestWillBeSent,
101+
responseReceived,
102+
dataReceived,
103+
loadingFinished,
104+
} = internalBinding('inspector');
105+
96106
const kClientRequestStatistics = Symbol('ClientRequestStatistics');
97107

98108
const dc = require('diagnostics_channel');
@@ -375,14 +385,15 @@ ObjectSetPrototypeOf(ClientRequest, OutgoingMessage);
375385

376386
ClientRequest.prototype._finish = function _finish() {
377387
FunctionPrototypeCall(OutgoingMessage.prototype._finish, this);
388+
const url = `${this.protocol}//${this.host}${this.path}`;
378389
if (hasObserver('http')) {
379390
startPerf(this, kClientRequestStatistics, {
380391
type: 'http',
381392
name: 'HttpClient',
382393
detail: {
383394
req: {
384395
method: this.method,
385-
url: `${this.protocol}//${this.host}${this.path}`,
396+
url,
386397
headers: typeof this.getHeaders === 'function' ? this.getHeaders() : {},
387398
},
388399
},
@@ -393,6 +404,14 @@ ClientRequest.prototype._finish = function _finish() {
393404
request: this,
394405
});
395406
}
407+
408+
if (isInspectorEnabled()) {
409+
this._inspectorEventId = getNextInspectorEventId();
410+
const wallTime = DateNow();
411+
const timestamp = wallTime / 1000;
412+
requestWillBeSent(this._inspectorEventId, url, this.method, timestamp, wallTime);
413+
}
414+
396415
if (isTraceHTTPEnabled()) {
397416
this._traceEventId = getNextTraceEventId();
398417
traceBegin(HTTP_CLIENT_TRACE_EVENT_NAME, this._traceEventId);
@@ -680,6 +699,21 @@ function parserOnIncomingClient(res, shouldKeepAlive) {
680699
response: res,
681700
});
682701
}
702+
703+
if (isInspectorEnabled() && typeof req._inspectorEventId === 'string') {
704+
responseReceived(req._inspectorEventId, DateNow() / 1000);
705+
let response = '';
706+
const onData = (chunk) => {
707+
dataReceived(req._inspectorEventId, DateNow() / 1000, chunk.length);
708+
response += chunk.toString();
709+
};
710+
res.on('data', onData);
711+
res.on('end', () => {
712+
loadingFinished(req._inspectorEventId, response, DateNow() / 1000, response.length);
713+
res.removeListener('data', onData);
714+
});
715+
}
716+
683717
if (isTraceHTTPEnabled() && typeof req._traceEventId === 'number') {
684718
traceEnd(HTTP_CLIENT_TRACE_EVENT_NAME, req._traceEventId, {
685719
path: req.path,

lib/internal/http.js

+8
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ function resetCache() {
3131
utcCache = undefined;
3232
}
3333

34+
let inspectorEventId = 0;
35+
36+
function getNextInspectorEventId() {
37+
const id = ++inspectorEventId;
38+
return `node-network-inspect-event-${id}`;
39+
}
40+
3441
let traceEventId = 0;
3542

3643
function getNextTraceEventId() {
@@ -57,6 +64,7 @@ module.exports = {
5764
utcDate,
5865
traceBegin,
5966
traceEnd,
67+
getNextInspectorEventId,
6068
getNextTraceEventId,
6169
isTraceHTTPEnabled,
6270
};

src/inspector/network_agent.cc

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

src/inspector/network_agent.h

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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(
21+
const String& in_requestId, String* out_body) override;
22+
23+
void requestWillBeSent(
24+
const String& request_id, const String& url, const String& method,
25+
double timestamp, double wall_time);
26+
27+
void responseReceived(const String& request_id, double timestamp);
28+
29+
void dataReceived(
30+
const String& request_id, double timestamp, int data_length);
31+
32+
void loadingFinished(
33+
const String& request_id, const String& response, double timestamp,
34+
int encoded_data_length);
35+
36+
private:
37+
std::shared_ptr<Network::Frontend> frontend_;
38+
std::unordered_map<String, String> request_id_to_response_;
39+
};
40+
41+
} // namespace protocol
42+
} // namespace inspector
43+
} // namespace node
44+
45+
#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)