urllib
Version:
Help in opening URLs (mostly HTTP) in a complex world — basic and digest authentication, redirections, timeout and more. Base undici API.
229 lines • 23.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.initDiagnosticsChannel = initDiagnosticsChannel;
const node_diagnostics_channel_1 = __importDefault(require("node:diagnostics_channel"));
const node_perf_hooks_1 = require("node:perf_hooks");
const node_util_1 = require("node:util");
const node_net_1 = require("node:net");
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const symbols_js_1 = __importDefault(require("./symbols.js"));
const utils_js_1 = require("./utils.js");
const debug = (0, node_util_1.debuglog)('urllib/diagnosticsChannel');
let initedDiagnosticsChannel = false;
// https://undici.nodejs.org/#/docs/api/DiagnosticsChannel
// client --> server
// undici:request:create => { request }
// -> [optional] undici:client:connected => { socket } [first request will create socket]
// -> undici:client:sendHeaders => { socket, request }
// -> undici:request:bodySent => { request }
//
// server --> client
// undici:request:headers => { request, response }
// -> undici:request:trailers => { request, trailers }
function subscribe(name, listener) {
node_diagnostics_channel_1.default.subscribe(name, listener);
}
let kSocketReset;
function formatSocket(socket) {
if (!socket)
return socket;
if (!kSocketReset) {
const symbols = Object.getOwnPropertySymbols(socket);
for (const symbol of symbols) {
if (symbol.description === 'reset') {
kSocketReset = symbol;
break;
}
}
}
return {
localAddress: socket[symbols_js_1.default.kSocketLocalAddress],
localPort: socket[symbols_js_1.default.kSocketLocalPort],
remoteAddress: socket.remoteAddress,
remotePort: socket.remotePort,
attemptedAddresses: socket.autoSelectFamilyAttemptedAddresses,
connecting: socket.connecting,
reset: socket[kSocketReset],
};
}
// make sure error contains socket info
const destroySocket = node_net_1.Socket.prototype.destroy;
node_net_1.Socket.prototype.destroy = function (err) {
if (err) {
Object.defineProperty(err, symbols_js_1.default.kErrorSocket, {
// don't show on console log
enumerable: false,
value: this,
});
}
return destroySocket.call(this, err);
};
function getRequestOpaque(request, kHandler) {
if (!kHandler)
return;
const handler = Reflect.get(request, kHandler);
// maxRedirects = 0 will get [Symbol(handler)]: RequestHandler {
// responseHeaders: null,
// opaque: {
// [Symbol(request id)]: 1,
// [Symbol(request start time)]: 465.0712921619415,
// [Symbol(enable request timing or not)]: true,
// [Symbol(request timing)]: [Object],
// [Symbol(request original opaque)]: undefined
// }
return handler?.opts?.opaque ?? handler?.opaque;
}
function initDiagnosticsChannel() {
// make sure init global DiagnosticsChannel once
if (initedDiagnosticsChannel)
return;
initedDiagnosticsChannel = true;
let kHandler;
// This message is published when a new outgoing request is created.
// Note: a request is only loosely completed to a given socket.
subscribe('undici:request:create', (message, name) => {
const { request } = message;
if (!kHandler) {
const symbols = Object.getOwnPropertySymbols(request);
for (const symbol of symbols) {
if (symbol.description === 'handler') {
kHandler = symbol;
break;
}
}
}
const opaque = getRequestOpaque(request, kHandler);
// ignore non HttpClient Request
if (!opaque || !opaque[symbols_js_1.default.kRequestId])
return;
Reflect.set(request, symbols_js_1.default.kRequestInternalOpaque, opaque);
debug('[%s] Request#%d %s %s, path: %s, headers: %j', name, opaque[symbols_js_1.default.kRequestId], request.method, request.origin, request.path, request.headers);
if (!opaque[symbols_js_1.default.kEnableRequestTiming])
return;
opaque[symbols_js_1.default.kRequestTiming].queuing = (0, utils_js_1.performanceTime)(opaque[symbols_js_1.default.kRequestStartTime]);
});
subscribe('undici:client:connectError', (message, name) => {
const { error, connectParams, socket } = message;
let sock = socket;
if (!sock && error[symbols_js_1.default.kErrorSocket]) {
sock = error[symbols_js_1.default.kErrorSocket];
}
if (sock) {
sock[symbols_js_1.default.kSocketId] = (0, utils_js_1.globalId)('UndiciSocket');
sock[symbols_js_1.default.kSocketConnectErrorTime] = new Date();
sock[symbols_js_1.default.kHandledRequests] = 0;
sock[symbols_js_1.default.kHandledResponses] = 0;
// copy local address to symbol, avoid them be reset after request error throw
if (sock.localAddress) {
sock[symbols_js_1.default.kSocketLocalAddress] = sock.localAddress;
sock[symbols_js_1.default.kSocketLocalPort] = sock.localPort;
}
sock[symbols_js_1.default.kSocketConnectProtocol] = connectParams.protocol;
sock[symbols_js_1.default.kSocketConnectHost] = connectParams.host;
sock[symbols_js_1.default.kSocketConnectPort] = connectParams.port;
debug('[%s] Socket#%d connectError, connectParams: %j, error: %s, (sock: %j)', name, sock[symbols_js_1.default.kSocketId], connectParams, error.message, formatSocket(sock));
}
else {
debug('[%s] connectError, connectParams: %j, error: %o', name, connectParams, error);
}
});
// This message is published after a connection is established.
subscribe('undici:client:connected', (message, name) => {
const { socket, connectParams } = message;
socket[symbols_js_1.default.kSocketId] = (0, utils_js_1.globalId)('UndiciSocket');
socket[symbols_js_1.default.kSocketStartTime] = node_perf_hooks_1.performance.now();
socket[symbols_js_1.default.kSocketConnectedTime] = new Date();
socket[symbols_js_1.default.kHandledRequests] = 0;
socket[symbols_js_1.default.kHandledResponses] = 0;
// copy local address to symbol, avoid them be reset after request error throw
socket[symbols_js_1.default.kSocketLocalAddress] = socket.localAddress;
socket[symbols_js_1.default.kSocketLocalPort] = socket.localPort;
socket[symbols_js_1.default.kSocketConnectProtocol] = connectParams.protocol;
socket[symbols_js_1.default.kSocketConnectHost] = connectParams.host;
socket[symbols_js_1.default.kSocketConnectPort] = connectParams.port;
debug('[%s] Socket#%d connected (sock: %j)', name, socket[symbols_js_1.default.kSocketId], formatSocket(socket));
});
// This message is published right before the first byte of the request is written to the socket.
subscribe('undici:client:sendHeaders', (message, name) => {
const { request, socket } = message;
const opaque = Reflect.get(request, symbols_js_1.default.kRequestInternalOpaque);
if (!opaque || !opaque[symbols_js_1.default.kRequestId]) {
debug('[%s] opaque not found', name);
return;
}
socket[symbols_js_1.default.kHandledRequests]++;
// attach socket to opaque
opaque[symbols_js_1.default.kRequestSocket] = socket;
debug('[%s] Request#%d send headers on Socket#%d (handled %d requests, sock: %j)', name, opaque[symbols_js_1.default.kRequestId], socket[symbols_js_1.default.kSocketId], socket[symbols_js_1.default.kHandledRequests], formatSocket(socket));
if (!opaque[symbols_js_1.default.kEnableRequestTiming])
return;
opaque[symbols_js_1.default.kRequestTiming].requestHeadersSent = (0, utils_js_1.performanceTime)(opaque[symbols_js_1.default.kRequestStartTime]);
// first socket need to calculate the connected time
if (socket[symbols_js_1.default.kHandledRequests] === 1) {
// kSocketStartTime - kRequestStartTime = connected time
opaque[symbols_js_1.default.kRequestTiming].connected =
(0, utils_js_1.performanceTime)(opaque[symbols_js_1.default.kRequestStartTime], socket[symbols_js_1.default.kSocketStartTime]);
}
});
subscribe('undici:request:bodySent', (message, name) => {
const { request } = message;
const opaque = Reflect.get(request, symbols_js_1.default.kRequestInternalOpaque);
if (!opaque || !opaque[symbols_js_1.default.kRequestId]) {
debug('[%s] opaque not found', name);
return;
}
debug('[%s] Request#%d send body', name, opaque[symbols_js_1.default.kRequestId]);
if (!opaque[symbols_js_1.default.kEnableRequestTiming])
return;
opaque[symbols_js_1.default.kRequestTiming].requestSent = (0, utils_js_1.performanceTime)(opaque[symbols_js_1.default.kRequestStartTime]);
});
// This message is published after the response headers have been received, i.e. the response has been completed.
subscribe('undici:request:headers', (message, name) => {
const { request, response } = message;
const opaque = Reflect.get(request, symbols_js_1.default.kRequestInternalOpaque);
if (!opaque || !opaque[symbols_js_1.default.kRequestId]) {
debug('[%s] opaque not found', name);
return;
}
// get socket from opaque
const socket = opaque[symbols_js_1.default.kRequestSocket];
if (socket) {
socket[symbols_js_1.default.kHandledResponses]++;
debug('[%s] Request#%d get %s response headers on Socket#%d (handled %d responses, sock: %j)', name, opaque[symbols_js_1.default.kRequestId], response.statusCode, socket[symbols_js_1.default.kSocketId], socket[symbols_js_1.default.kHandledResponses], formatSocket(socket));
}
else {
debug('[%s] Request#%d get %s response headers on Unknown Socket', name, opaque[symbols_js_1.default.kRequestId], response.statusCode);
}
if (!opaque[symbols_js_1.default.kEnableRequestTiming])
return;
opaque[symbols_js_1.default.kRequestTiming].waiting = (0, utils_js_1.performanceTime)(opaque[symbols_js_1.default.kRequestStartTime]);
});
// This message is published after the response body and trailers have been received, i.e. the response has been completed.
subscribe('undici:request:trailers', (message, name) => {
const { request } = message;
const opaque = Reflect.get(request, symbols_js_1.default.kRequestInternalOpaque);
if (!opaque || !opaque[symbols_js_1.default.kRequestId]) {
debug('[%s] opaque not found', name);
return;
}
debug('[%s] Request#%d get response body and trailers', name, opaque[symbols_js_1.default.kRequestId]);
if (!opaque[symbols_js_1.default.kEnableRequestTiming])
return;
opaque[symbols_js_1.default.kRequestTiming].contentDownload = (0, utils_js_1.performanceTime)(opaque[symbols_js_1.default.kRequestStartTime]);
});
// This message is published if the request is going to error, but it has not errored yet.
// subscribe('undici:request:error', (message, name) => {
// const { request, error } = message as DiagnosticsChannel.RequestErrorMessage;
// const opaque = request[kHandler]?.opts?.opaque;
// if (!opaque || !opaque[symbols.kRequestId]) return;
// const socket = opaque[symbols.kRequestSocket];
// debug('[%s] Request#%d error on Socket#%d (handled %d responses, sock: %o), error: %o',
// name, opaque[symbols.kRequestId], socket[symbols.kSocketId], socket[symbols.kHandledResponses],
// formatSocket(socket), error);
// });
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlhZ25vc3RpY3NDaGFubmVsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RpYWdub3N0aWNzQ2hhbm5lbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQWtGQSx3REFtS0M7QUFyUEQsd0ZBQTBEO0FBQzFELHFEQUE4QztBQUM5Qyx5Q0FBcUM7QUFDckMsdUNBQWtDO0FBRWxDLDZEQUE2RDtBQUM3RCxhQUFhO0FBQ2IsOERBQW1DO0FBQ25DLHlDQUF1RDtBQUV2RCxNQUFNLEtBQUssR0FBRyxJQUFBLG9CQUFRLEVBQUMsMkJBQTJCLENBQUMsQ0FBQztBQUNwRCxJQUFJLHdCQUF3QixHQUFHLEtBQUssQ0FBQztBQUNyQywwREFBMEQ7QUFDMUQsb0JBQW9CO0FBQ3BCLHVDQUF1QztBQUN2QywyRkFBMkY7QUFDM0Ysd0RBQXdEO0FBQ3hELGdEQUFnRDtBQUNoRCxFQUFFO0FBQ0Ysb0JBQW9CO0FBQ3BCLGtEQUFrRDtBQUNsRCx3REFBd0Q7QUFFeEQsU0FBUyxTQUFTLENBQUMsSUFBWSxFQUFFLFFBQWtFO0lBQ2pHLGtDQUFrQixDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDL0MsQ0FBQztBQU1ELElBQUksWUFBb0IsQ0FBQztBQUN6QixTQUFTLFlBQVksQ0FBQyxNQUFvQjtJQUN4QyxJQUFJLENBQUMsTUFBTTtRQUFFLE9BQU8sTUFBTSxDQUFDO0lBQzNCLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNsQixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMscUJBQXFCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckQsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUM3QixJQUFJLE1BQU0sQ0FBQyxXQUFXLEtBQUssT0FBTyxFQUFFLENBQUM7Z0JBQ25DLFlBQVksR0FBRyxNQUFNLENBQUM7Z0JBQ3RCLE1BQU07WUFDUixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFD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