Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/internal/inspector/network.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const {
NumberMAX_SAFE_INTEGER,
StringPrototypeToLowerCase,
Symbol,
} = primordials;

Expand Down Expand Up @@ -52,8 +53,8 @@ function sniffMimeType(contentType) {
let charset;
try {
const mimeTypeObj = new MIMEType(contentType);
mimeType = mimeTypeObj.essence || '';
charset = mimeTypeObj.params.get('charset') || '';
mimeType = StringPrototypeToLowerCase(mimeTypeObj.essence || '');
charset = StringPrototypeToLowerCase(mimeTypeObj.params.get('charset') || '');
} catch {
mimeType = '';
charset = '';
Expand Down
81 changes: 76 additions & 5 deletions lib/internal/inspector/network_undici.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const {
DateNow,
StringPrototypeToLowerCase,
} = primordials;

const {
Expand All @@ -13,16 +14,25 @@ const {
} = require('internal/inspector/network');
const dc = require('diagnostics_channel');
const { Network } = require('inspector');
const { Buffer } = require('buffer');

// Convert an undici request headers array to a plain object (Map<string, string>)
function requestHeadersArrayToDictionary(headers) {
const dict = {};
let charset;
let mimeType;
for (let idx = 0; idx < headers.length; idx += 2) {
const key = `${headers[idx]}`;
const value = `${headers[idx + 1]}`;
dict[key] = value;

if (StringPrototypeToLowerCase(key) === 'content-type') {
const result = sniffMimeType(value);
charset = result.charset;
mimeType = result.mimeType;
}
}
return dict;
return [dict, charset, mimeType];
};

// Convert an undici response headers array to a plain object (Map<string, string>)
Expand All @@ -32,7 +42,7 @@ function responseHeadersArrayToDictionary(headers) {
let mimeType;
for (let idx = 0; idx < headers.length; idx += 2) {
const key = `${headers[idx]}`;
const lowerCasedKey = key.toLowerCase();
const lowerCasedKey = StringPrototypeToLowerCase(key);
const value = `${headers[idx + 1]}`;
const prevValue = dict[key];

Expand Down Expand Up @@ -63,8 +73,7 @@ function onClientRequestStart({ request }) {
const url = `${request.origin}${request.path}`;
request[kInspectorRequestId] = getNextRequestId();

const headers = requestHeadersArrayToDictionary(request.headers);
const { charset } = sniffMimeType(headers);
const { 0: headers, 1: charset } = requestHeadersArrayToDictionary(request.headers);

Network.requestWillBeSent({
requestId: request[kInspectorRequestId],
Expand All @@ -74,7 +83,8 @@ function onClientRequestStart({ request }) {
request: {
url,
method: request.method,
headers: requestHeadersArrayToDictionary(request.headers),
headers: headers,
hasPostData: request.body != null,
},
});
}
Expand All @@ -97,6 +107,40 @@ function onClientRequestError({ request, error }) {
});
}

/**
* When a chunk of the request body is being sent, cache it until `getRequestPostData` request.
* https://chromedevtools.github.io/devtools-protocol/1-3/Network/#method-getRequestPostData
* @param {{ request: undici.Request, chunk: Uint8Array | string }} event
*/
function onClientRequestBodyChunkSent({ request, chunk }) {
if (typeof request[kInspectorRequestId] !== 'string') {
return;
}

const buffer = Buffer.from(chunk);
Network.dataSent({
requestId: request[kInspectorRequestId],
timestamp: getMonotonicTime(),
dataLength: buffer.byteLength,
data: buffer,
});
}

/**
* Mark a request body as fully sent.
* @param {{request: undici.Request}} event
*/
function onClientRequestBodySent({ request }) {
if (typeof request[kInspectorRequestId] !== 'string') {
return;
}

Network.dataSent({
requestId: request[kInspectorRequestId],
finished: true,
});
}

/**
* When response headers are received, emit Network.responseReceived event.
* https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-responseReceived
Expand Down Expand Up @@ -126,6 +170,27 @@ function onClientResponseHeaders({ request, response }) {
});
}

/**
* When a chunk of the response body has been received, cache it until `getResponseBody` request
* https://chromedevtools.github.io/devtools-protocol/1-3/Network/#method-getResponseBody or
* stream it with `streamResourceContent` request.
* https://chromedevtools.github.io/devtools-protocol/tot/Network/#method-streamResourceContent
* @param {{ request: undici.Request, chunk: Uint8Array | string }} event
*/
function onClientRequestBodyChunkReceived({ request, chunk }) {
if (typeof request[kInspectorRequestId] !== 'string') {
return;
}

Network.dataReceived({
requestId: request[kInspectorRequestId],
timestamp: getMonotonicTime(),
dataLength: chunk.byteLength,
encodedDataLength: chunk.byteLength,
data: chunk,
});
}

/**
* When a response is completed, emit Network.loadingFinished event.
* https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-loadingFinished
Expand All @@ -146,13 +211,19 @@ function enable() {
dc.subscribe('undici:request:error', onClientRequestError);
dc.subscribe('undici:request:headers', onClientResponseHeaders);
dc.subscribe('undici:request:trailers', onClientResponseFinish);
dc.subscribe('undici:request:bodyChunkSent', onClientRequestBodyChunkSent);
dc.subscribe('undici:request:bodySent', onClientRequestBodySent);
dc.subscribe('undici:request:bodyChunkReceived', onClientRequestBodyChunkReceived);
}

function disable() {
dc.unsubscribe('undici:request:create', onClientRequestStart);
dc.unsubscribe('undici:request:error', onClientRequestError);
dc.unsubscribe('undici:request:headers', onClientResponseHeaders);
dc.unsubscribe('undici:request:trailers', onClientResponseFinish);
dc.unsubscribe('undici:request:bodyChunkSent', onClientRequestBodyChunkSent);
dc.unsubscribe('undici:request:bodySent', onClientRequestBodySent);
dc.unsubscribe('undici:request:bodyChunkReceived', onClientRequestBodyChunkReceived);
}

module.exports = {
Expand Down
Loading
Loading