Skip to content

Commit be93091

Browse files
legendecasRafaelGSS
authored andcommitted
inspector: add protocol methods retrieving sent/received data
Add protocol method `Network.dataSent` to buffer request data. And expose protocol methods `Network.getRequestPostData` and `Network.getResponseBody` allowing devtool to retrieve buffered data. PR-URL: #58645 Reviewed-By: Ryuhei Shima <[email protected]>
1 parent b5ff3f4 commit be93091

11 files changed

+480
-85
lines changed

doc/api/inspector.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,20 @@ This feature is only available with the `--experimental-network-inspection` flag
524524
Broadcasts the `Network.dataReceived` event to connected frontends, or buffers the data if
525525
`Network.streamResourceContent` command was not invoked for the given request yet.
526526

527+
Also enables `Network.getResponseBody` command to retrieve the response data.
528+
529+
### `inspector.Network.dataSent([params])`
530+
531+
<!-- YAML
532+
added: REPLACEME
533+
-->
534+
535+
* `params` {Object}
536+
537+
This feature is only available with the `--experimental-network-inspection` flag enabled.
538+
539+
Enables `Network.getRequestPostData` command to retrieve the request data.
540+
527541
### `inspector.Network.requestWillBeSent([params])`
528542

529543
<!-- YAML

lib/inspector.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ const Network = {
214214
responseReceived: (params) => broadcastToFrontend('Network.responseReceived', params),
215215
loadingFinished: (params) => broadcastToFrontend('Network.loadingFinished', params),
216216
loadingFailed: (params) => broadcastToFrontend('Network.loadingFailed', params),
217+
dataSent: (params) => broadcastToFrontend('Network.dataSent', params),
217218
dataReceived: (params) => broadcastToFrontend('Network.dataReceived', params),
218219
};
219220

lib/internal/inspector/network.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const {
66
} = primordials;
77

88
const { now } = require('internal/perf/utils');
9+
const { MIMEType } = require('internal/mime');
910
const kInspectorRequestId = Symbol('kInspectorRequestId');
1011

1112
// https://chromedevtools.github.io/devtools-protocol/1-3/Network/#type-ResourceType
@@ -46,9 +47,29 @@ function getNextRequestId() {
4647
return `node-network-event-${++requestId}`;
4748
};
4849

50+
function sniffMimeType(contentType) {
51+
let mimeType;
52+
let charset;
53+
try {
54+
const mimeTypeObj = new MIMEType(contentType);
55+
mimeType = mimeTypeObj.essence || '';
56+
charset = mimeTypeObj.params.get('charset') || '';
57+
} catch {
58+
mimeType = '';
59+
charset = '';
60+
}
61+
62+
return {
63+
__proto__: null,
64+
mimeType,
65+
charset,
66+
};
67+
}
68+
4969
module.exports = {
5070
kInspectorRequestId,
5171
kResourceType,
5272
getMonotonicTime,
5373
getNextRequestId,
74+
sniffMimeType,
5475
};

lib/internal/inspector/network_http.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,43 @@ const {
1313
kResourceType,
1414
getMonotonicTime,
1515
getNextRequestId,
16+
sniffMimeType,
1617
} = require('internal/inspector/network');
1718
const dc = require('diagnostics_channel');
1819
const { Network } = require('inspector');
19-
const { MIMEType } = require('internal/mime');
2020

2121
const kRequestUrl = Symbol('kRequestUrl');
2222

2323
// Convert a Headers object (Map<string, number | string | string[]>) to a plain object (Map<string, string>)
2424
const convertHeaderObject = (headers = {}) => {
2525
// The 'host' header that contains the host and port of the URL.
2626
let host;
27+
let charset;
28+
let mimeType;
2729
const dict = {};
2830
for (const { 0: key, 1: value } of ObjectEntries(headers)) {
29-
if (key.toLowerCase() === 'host') {
31+
const lowerCasedKey = key.toLowerCase();
32+
if (lowerCasedKey === 'host') {
3033
host = value;
3134
}
35+
if (lowerCasedKey === 'content-type') {
36+
const result = sniffMimeType(value);
37+
charset = result.charset;
38+
mimeType = result.mimeType;
39+
}
3240
if (typeof value === 'string') {
3341
dict[key] = value;
3442
} else if (ArrayIsArray(value)) {
35-
if (key.toLowerCase() === 'cookie') dict[key] = value.join('; ');
43+
if (lowerCasedKey === 'cookie') dict[key] = value.join('; ');
3644
// ChromeDevTools frontend treats 'set-cookie' as a special case
3745
// https://github.com/ChromeDevTools/devtools-frontend/blob/4275917f84266ef40613db3c1784a25f902ea74e/front_end/core/sdk/NetworkRequest.ts#L1368
38-
else if (key.toLowerCase() === 'set-cookie') dict[key] = value.join('\n');
46+
else if (lowerCasedKey === 'set-cookie') dict[key] = value.join('\n');
3947
else dict[key] = value.join(', ');
4048
} else {
4149
dict[key] = String(value);
4250
}
4351
}
44-
return [host, dict];
52+
return [dict, host, charset, mimeType];
4553
};
4654

4755
/**
@@ -52,14 +60,15 @@ const convertHeaderObject = (headers = {}) => {
5260
function onClientRequestCreated({ request }) {
5361
request[kInspectorRequestId] = getNextRequestId();
5462

55-
const { 0: host, 1: headers } = convertHeaderObject(request.getHeaders());
63+
const { 0: headers, 1: host, 2: charset } = convertHeaderObject(request.getHeaders());
5664
const url = `${request.protocol}//${host}${request.path}`;
5765
request[kRequestUrl] = url;
5866

5967
Network.requestWillBeSent({
6068
requestId: request[kInspectorRequestId],
6169
timestamp: getMonotonicTime(),
6270
wallTime: DateNow(),
71+
charset,
6372
request: {
6473
url,
6574
method: request.method,
@@ -95,16 +104,7 @@ function onClientResponseFinish({ request, response }) {
95104
return;
96105
}
97106

98-
let mimeType;
99-
let charset;
100-
try {
101-
const mimeTypeObj = new MIMEType(response.headers['content-type']);
102-
mimeType = mimeTypeObj.essence || '';
103-
charset = mimeTypeObj.params.get('charset') || '';
104-
} catch {
105-
mimeType = '';
106-
charset = '';
107-
}
107+
const { 0: headers, 2: charset, 3: mimeType } = convertHeaderObject(response.headers);
108108

109109
Network.responseReceived({
110110
requestId: request[kInspectorRequestId],
@@ -114,7 +114,7 @@ function onClientResponseFinish({ request, response }) {
114114
url: request[kRequestUrl],
115115
status: response.statusCode,
116116
statusText: response.statusMessage ?? '',
117-
headers: convertHeaderObject(response.headers)[1],
117+
headers,
118118
mimeType,
119119
charset,
120120
},

lib/internal/inspector/network_undici.js

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const {
4-
ArrayPrototypeFindIndex,
54
DateNow,
65
} = primordials;
76

@@ -10,10 +9,10 @@ const {
109
kResourceType,
1110
getMonotonicTime,
1211
getNextRequestId,
12+
sniffMimeType,
1313
} = require('internal/inspector/network');
1414
const dc = require('diagnostics_channel');
1515
const { Network } = require('inspector');
16-
const { MIMEType } = require('internal/mime');
1716

1817
// Convert an undici request headers array to a plain object (Map<string, string>)
1918
function requestHeadersArrayToDictionary(headers) {
@@ -29,21 +28,30 @@ function requestHeadersArrayToDictionary(headers) {
2928
// Convert an undici response headers array to a plain object (Map<string, string>)
3029
function responseHeadersArrayToDictionary(headers) {
3130
const dict = {};
31+
let charset;
32+
let mimeType;
3233
for (let idx = 0; idx < headers.length; idx += 2) {
3334
const key = `${headers[idx]}`;
35+
const lowerCasedKey = key.toLowerCase();
3436
const value = `${headers[idx + 1]}`;
3537
const prevValue = dict[key];
3638

39+
if (lowerCasedKey === 'content-type') {
40+
const result = sniffMimeType(value);
41+
charset = result.charset;
42+
mimeType = result.mimeType;
43+
}
44+
3745
if (typeof prevValue === 'string') {
3846
// ChromeDevTools frontend treats 'set-cookie' as a special case
3947
// https://github.com/ChromeDevTools/devtools-frontend/blob/4275917f84266ef40613db3c1784a25f902ea74e/front_end/core/sdk/NetworkRequest.ts#L1368
40-
if (key.toLowerCase() === 'set-cookie') dict[key] = `${prevValue}\n${value}`;
48+
if (lowerCasedKey === 'set-cookie') dict[key] = `${prevValue}\n${value}`;
4149
else dict[key] = `${prevValue}, ${value}`;
4250
} else {
4351
dict[key] = value;
4452
}
4553
}
46-
return dict;
54+
return [dict, charset, mimeType];
4755
};
4856

4957
/**
@@ -54,10 +62,15 @@ function responseHeadersArrayToDictionary(headers) {
5462
function onClientRequestStart({ request }) {
5563
const url = `${request.origin}${request.path}`;
5664
request[kInspectorRequestId] = getNextRequestId();
65+
66+
const headers = requestHeadersArrayToDictionary(request.headers);
67+
const { charset } = sniffMimeType(headers);
68+
5769
Network.requestWillBeSent({
5870
requestId: request[kInspectorRequestId],
5971
timestamp: getMonotonicTime(),
6072
wallTime: DateNow(),
73+
charset,
6174
request: {
6275
url,
6376
method: request.method,
@@ -94,19 +107,7 @@ function onClientResponseHeaders({ request, response }) {
94107
return;
95108
}
96109

97-
let mimeType;
98-
let charset;
99-
try {
100-
const contentTypeKeyIndex =
101-
ArrayPrototypeFindIndex(response.headers, (header) => header.toString().toLowerCase() === 'content-type');
102-
const contentType = contentTypeKeyIndex !== -1 ? response.headers[contentTypeKeyIndex + 1].toString() : '';
103-
const mimeTypeObj = new MIMEType(contentType);
104-
mimeType = mimeTypeObj.essence || '';
105-
charset = mimeTypeObj.params.get('charset') || '';
106-
} catch {
107-
mimeType = '';
108-
charset = '';
109-
}
110+
const { 0: headers, 1: charset, 2: mimeType } = responseHeadersArrayToDictionary(response.headers);
110111

111112
const url = `${request.origin}${request.path}`;
112113
Network.responseReceived({
@@ -118,7 +119,7 @@ function onClientResponseHeaders({ request, response }) {
118119
url,
119120
status: response.statusCode,
120121
statusText: response.statusText,
121-
headers: responseHeadersArrayToDictionary(response.headers),
122+
headers,
122123
mimeType,
123124
charset,
124125
},

0 commit comments

Comments
 (0)