From d823d8a6b2b720f43bc4bb70bf230bf6302ea25a Mon Sep 17 00:00:00 2001 From: cola119 Date: Thu, 1 Aug 2024 15:32:35 +0900 Subject: [PATCH] inspector: provide detailed info to fix DevTools frontend errors --- lib/internal/inspector_network_tracking.js | 10 +++- src/inspector/network_agent.cc | 53 ++++++++++++++++--- src/inspector/network_agent.h | 8 ++- src/inspector/node_protocol.pdl | 37 +++++++++++++ .../test-inspector-emit-protocol-event.js | 20 ++++++- .../parallel/test-inspector-network-domain.js | 10 ++++ 6 files changed, 127 insertions(+), 11 deletions(-) diff --git a/lib/internal/inspector_network_tracking.js b/lib/internal/inspector_network_tracking.js index 4865537e37b7d5..428c5033154147 100644 --- a/lib/internal/inspector_network_tracking.js +++ b/lib/internal/inspector_network_tracking.js @@ -22,18 +22,26 @@ function onClientRequestStart({ request }) { request: { url, method: request.method, + headers: request.getHeaders(), }, }); } -function onClientResponseFinish({ request }) { +function onClientResponseFinish({ request, response }) { if (typeof request._inspectorRequestId !== 'string') { return; } + const url = `${request.protocol}//${request.host}${request.path}`; const timestamp = DateNow() / 1000; Network.responseReceived({ requestId: request._inspectorRequestId, timestamp, + type: 'Other', + response: { + url, + status: response.statusCode, + headers: response.headers, + }, }); Network.loadingFinished({ requestId: request._inspectorRequestId, diff --git a/src/inspector/network_agent.cc b/src/inspector/network_agent.cc index de17ff0ecb2041..a75a7f8d6edd5d 100644 --- a/src/inspector/network_agent.cc +++ b/src/inspector/network_agent.cc @@ -5,9 +5,24 @@ namespace node { namespace inspector { namespace protocol { -std::unique_ptr Request(const String& url, - const String& method) { - return Network::Request::create().setUrl(url).setMethod(method).build(); +std::unique_ptr createRequest( + const String& url, + const String& method, + std::unique_ptr headers) { + return Network::Request::create() + .setUrl(url) + .setMethod(method) + .setHeaders(std::move(headers)) + .build(); +} + +std::unique_ptr createResponse( + const String& url, int status, std::unique_ptr headers) { + return Network::Response::create() + .setUrl(url) + .setStatus(status) + .setHeaders(std::move(headers)) + .build(); } NetworkAgent::NetworkAgent(NetworkInspector* inspector) @@ -55,8 +70,17 @@ void NetworkAgent::requestWillBeSent( String method; request->getString("method", &method); - frontend_->requestWillBeSent( - request_id, Request(url, method), timestamp, wall_time); + ErrorSupport errors; + auto headers = + Network::Headers::fromValue(request->getObject("headers"), &errors); + if (errors.hasErrors()) { + headers = std::make_unique(DictionaryValue::create()); + } + + frontend_->requestWillBeSent(request_id, + createRequest(url, method, std::move(headers)), + timestamp, + wall_time); } void NetworkAgent::responseReceived( @@ -65,8 +89,25 @@ void NetworkAgent::responseReceived( params->getString("requestId", &request_id); double timestamp; params->getDouble("timestamp", ×tamp); + String type; + params->getString("type", &type); + auto response = params->getObject("response"); + String url; + response->getString("url", &url); + int status; + response->getInteger("status", &status); + + ErrorSupport errors; + auto headers = + Network::Headers::fromValue(response->getObject("headers"), &errors); + if (errors.hasErrors()) { + headers = std::make_unique(DictionaryValue::create()); + } - frontend_->responseReceived(request_id, timestamp); + frontend_->responseReceived(request_id, + timestamp, + type, + createResponse(url, status, std::move(headers))); } void NetworkAgent::loadingFinished( diff --git a/src/inspector/network_agent.h b/src/inspector/network_agent.h index e2ca447b6e9480..bd0f82bffd3c5e 100644 --- a/src/inspector/network_agent.h +++ b/src/inspector/network_agent.h @@ -12,8 +12,12 @@ class NetworkInspector; namespace protocol { -std::unique_ptr Request(const String& url, - const String& method); +std::unique_ptr createRequest( + const String& url, + const String& method, + std::unique_ptr headers); +std::unique_ptr createResponse( + const String& url, int status, std::unique_ptr headers); class NetworkAgent : public Network::Backend { public: diff --git a/src/inspector/node_protocol.pdl b/src/inspector/node_protocol.pdl index ab7b6a5414c846..a0859e215ac19b 100644 --- a/src/inspector/node_protocol.pdl +++ b/src/inspector/node_protocol.pdl @@ -101,6 +101,28 @@ experimental domain NodeWorker # Partial support for Network domain of ChromeDevTools Protocol. # https://chromedevtools.github.io/devtools-protocol/tot/Network experimental domain Network + # Resource type as it was perceived by the rendering engine. + type ResourceType extends string + enum + Document + Stylesheet + Image + Media + Font + Script + TextTrack + XHR + Fetch + Prefetch + EventSource + WebSocket + Manifest + SignedExchange + Ping + CSPViolationReport + Preflight + Other + # Unique request identifier. type RequestId extends string @@ -115,6 +137,17 @@ experimental domain Network properties string url string method + Headers headers + + # HTTP response data. + type Response extends object + properties + string url + integer status + Headers headers + + # Request / response headers as keys / values of JSON object. + type Headers extends object # Disables network tracking, prevents network events from being sent to the client. command disable @@ -141,6 +174,10 @@ experimental domain Network RequestId requestId # Timestamp. MonotonicTime timestamp + # Resource type. + ResourceType type + # Response data. + Response response event loadingFinished parameters diff --git a/test/parallel/test-inspector-emit-protocol-event.js b/test/parallel/test-inspector-emit-protocol-event.js index 1a4e622c78881b..ec494ea8e9ef99 100644 --- a/test/parallel/test-inspector-emit-protocol-event.js +++ b/test/parallel/test-inspector-emit-protocol-event.js @@ -15,7 +15,17 @@ const EXPECTED_EVENTS = { requestId: 'request-id-1', request: { url: 'https://nodejs.org/en', - method: 'GET' + method: 'GET', + }, + timestamp: 1000, + wallTime: 1000, + }, + expected: { + requestId: 'request-id-1', + request: { + url: 'https://nodejs.org/en', + method: 'GET', + headers: {} // Headers should be an empty object if not provided. }, timestamp: 1000, wallTime: 1000, @@ -26,6 +36,12 @@ const EXPECTED_EVENTS = { params: { requestId: 'request-id-1', timestamp: 1000, + type: 'Other', + response: { + url: 'https://nodejs.org/en', + status: 200, + headers: { host: 'nodejs.org' } + } } }, { @@ -68,7 +84,7 @@ const runAsyncTest = async () => { for (const [domain, events] of Object.entries(EXPECTED_EVENTS)) { for (const event of events) { session.on(`${domain}.${event.name}`, common.mustCall(({ params }) => { - assert.deepStrictEqual(params, event.params); + assert.deepStrictEqual(params, event.expected ?? event.params); })); inspector[domain][event.name](event.params); } diff --git a/test/parallel/test-inspector-network-domain.js b/test/parallel/test-inspector-network-domain.js index 1dc0d4f65a216e..18b7c247178595 100644 --- a/test/parallel/test-inspector-network-domain.js +++ b/test/parallel/test-inspector-network-domain.js @@ -52,12 +52,17 @@ const testHttpGet = () => new Promise((resolve, reject) => { assert.ok(params.requestId.startsWith('node-network-event-')); assert.strictEqual(params.request.url, 'http://127.0.0.1/hello-world'); assert.strictEqual(params.request.method, 'GET'); + assert.strictEqual(typeof params.request.headers, 'object'); assert.strictEqual(typeof params.timestamp, 'number'); assert.strictEqual(typeof params.wallTime, 'number'); })); session.on('Network.responseReceived', common.mustCall(({ params }) => { assert.ok(params.requestId.startsWith('node-network-event-')); assert.strictEqual(typeof params.timestamp, 'number'); + assert.strictEqual(params.type, 'Other'); + assert.strictEqual(params.response.status, 200); + assert.strictEqual(params.response.url, 'http://127.0.0.1/hello-world'); + assert.strictEqual(typeof params.response.headers, 'object'); })); session.on('Network.loadingFinished', common.mustCall(({ params }) => { assert.ok(params.requestId.startsWith('node-network-event-')); @@ -77,12 +82,17 @@ const testHttpsGet = () => new Promise((resolve, reject) => { assert.ok(params.requestId.startsWith('node-network-event-')); assert.strictEqual(params.request.url, 'https://127.0.0.1/hello-world'); assert.strictEqual(params.request.method, 'GET'); + assert.strictEqual(typeof params.request.headers, 'object'); assert.strictEqual(typeof params.timestamp, 'number'); assert.strictEqual(typeof params.wallTime, 'number'); })); session.on('Network.responseReceived', common.mustCall(({ params }) => { assert.ok(params.requestId.startsWith('node-network-event-')); assert.strictEqual(typeof params.timestamp, 'number'); + assert.strictEqual(params.type, 'Other'); + assert.strictEqual(params.response.status, 200); + assert.strictEqual(params.response.url, 'https://127.0.0.1/hello-world'); + assert.strictEqual(typeof params.response.headers, 'object'); })); session.on('Network.loadingFinished', common.mustCall(({ params }) => { assert.ok(params.requestId.startsWith('node-network-event-'));