/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
lib/internal/inspector/network_http.js
163 строки
5 KB
Antoine du Hamel
lib: add lint rule to enforce use of `kEmptyObject`
10 июн 2026, 13:56
Не верифицирован
10 июн 2026, 13:56
1778eeb
Код
Авторство
О чём код?
'use strict'; const { ArrayIsArray, DateNow, ObjectEntries, String, StringPrototypeStartsWith, Symbol, } = primordials; const { kInspectorRequestId, kResourceType, getMonotonicTime, getNextRequestId, registerDiagnosticChannels, sniffMimeType, } = require('internal/inspector/network'); const { Network } = require('inspector'); const EventEmitter = require('events'); const { kEmptyObject } = require('internal/util'); const kRequestUrl = Symbol('kRequestUrl'); function isAbsoluteURLPath(path) { return typeof path === 'string' && (StringPrototypeStartsWith(path, 'http://') || StringPrototypeStartsWith(path, 'https://')); } function getRequestURL(request, host) { if (isAbsoluteURLPath(request.path)) { return request.path; } return `${request.protocol}//${host}${request.path}`; } // Convert a Headers object (Map<string, number | string | string[]>) to a plain object (Map<string, string>) const convertHeaderObject = (headers = kEmptyObject) => { // The 'host' header that contains the host and port of the URL. let host; let charset; let mimeType; const dict = {}; for (const { 0: key, 1: value } of ObjectEntries(headers)) { const lowerCasedKey = key.toLowerCase(); if (lowerCasedKey === 'host') { host = value; } if (lowerCasedKey === 'content-type') { const result = sniffMimeType(value); charset = result.charset; mimeType = result.mimeType; } if (typeof value === 'string') { dict[key] = value; } else if (ArrayIsArray(value)) { if (lowerCasedKey === 'cookie') dict[key] = value.join('; '); // ChromeDevTools frontend treats 'set-cookie' as a special case // https://github.com/ChromeDevTools/devtools-frontend/blob/4275917f84266ef40613db3c1784a25f902ea74e/front_end/core/sdk/NetworkRequest.ts#L1368 else if (lowerCasedKey === 'set-cookie') dict[key] = value.join('\n'); else dict[key] = value.join(', '); } else { dict[key] = String(value); } } return [dict, host, charset, mimeType]; }; /** * When a client request is created, emit Network.requestWillBeSent event. * https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-requestWillBeSent * @param {{ request: import('http').ClientRequest }} event */ function onClientRequestCreated({ request }) { request[kInspectorRequestId] = getNextRequestId(); const { 0: headers, 1: host, 2: charset } = convertHeaderObject(request.getHeaders()); const url = getRequestURL(request, host); request[kRequestUrl] = url; Network.requestWillBeSent({ requestId: request[kInspectorRequestId], timestamp: getMonotonicTime(), wallTime: DateNow(), charset, request: { url, method: request.method, headers, }, }); } /** * When a client request errors, emit Network.loadingFailed event. * https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-loadingFailed * @param {{ request: import('http').ClientRequest, error: any }} event */ function onClientRequestError({ request, error }) { if (typeof request[kInspectorRequestId] !== 'string') { return; } Network.loadingFailed({ requestId: request[kInspectorRequestId], timestamp: getMonotonicTime(), type: kResourceType.Other, errorText: error.message, }); } /** * When response headers are received, emit Network.responseReceived event. * https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-responseReceived * @param {{ request: import('http').ClientRequest, error: any }} event */ function onClientResponseFinish({ request, response }) { if (typeof request[kInspectorRequestId] !== 'string') { return; } const { 0: headers, 2: charset, 3: mimeType } = convertHeaderObject(response.headers); Network.responseReceived({ requestId: request[kInspectorRequestId], timestamp: getMonotonicTime(), type: kResourceType.Other, response: { url: request[kRequestUrl], status: response.statusCode, statusText: response.statusMessage ?? '', headers, mimeType, charset, }, }); // Unlike response.on('data', ...), this does not put the stream into flowing mode. EventEmitter.prototype.on.call(response, 'data', (chunk) => { Network.dataReceived({ requestId: request[kInspectorRequestId], timestamp: getMonotonicTime(), dataLength: chunk.byteLength, encodedDataLength: chunk.byteLength, data: chunk, }); }); // Wait until the response body is consumed by user code. response.once('end', () => { Network.loadingFinished({ requestId: request[kInspectorRequestId], timestamp: getMonotonicTime(), }); }); } module.exports = registerDiagnosticChannels([ ['http.client.request.created', onClientRequestCreated], ['http.client.request.error', onClientRequestError], ['http.client.response.finish', onClientResponseFinish], ]);