123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- const defer_to_connect_1 = require("defer-to-connect");
- const util_1 = require("util");
- const nodejsMajorVersion = Number(process.versions.node.split('.')[0]);
- const timer = (request) => {
- if (request.timings) {
- return request.timings;
- }
- const timings = {
- start: Date.now(),
- socket: undefined,
- lookup: undefined,
- connect: undefined,
- secureConnect: undefined,
- upload: undefined,
- response: undefined,
- end: undefined,
- error: undefined,
- abort: undefined,
- phases: {
- wait: undefined,
- dns: undefined,
- tcp: undefined,
- tls: undefined,
- request: undefined,
- firstByte: undefined,
- download: undefined,
- total: undefined
- }
- };
- request.timings = timings;
- const handleError = (origin) => {
- const emit = origin.emit.bind(origin);
- origin.emit = (event, ...args) => {
- // Catches the `error` event
- if (event === 'error') {
- timings.error = Date.now();
- timings.phases.total = timings.error - timings.start;
- origin.emit = emit;
- }
- // Saves the original behavior
- return emit(event, ...args);
- };
- };
- handleError(request);
- const onAbort = () => {
- timings.abort = Date.now();
- // Let the `end` response event be responsible for setting the total phase,
- // unless the Node.js major version is >= 13.
- if (!timings.response || nodejsMajorVersion >= 13) {
- timings.phases.total = Date.now() - timings.start;
- }
- };
- request.prependOnceListener('abort', onAbort);
- const onSocket = (socket) => {
- timings.socket = Date.now();
- timings.phases.wait = timings.socket - timings.start;
- if (util_1.types.isProxy(socket)) {
- return;
- }
- const lookupListener = () => {
- timings.lookup = Date.now();
- timings.phases.dns = timings.lookup - timings.socket;
- };
- socket.prependOnceListener('lookup', lookupListener);
- defer_to_connect_1.default(socket, {
- connect: () => {
- timings.connect = Date.now();
- if (timings.lookup === undefined) {
- socket.removeListener('lookup', lookupListener);
- timings.lookup = timings.connect;
- timings.phases.dns = timings.lookup - timings.socket;
- }
- timings.phases.tcp = timings.connect - timings.lookup;
- // This callback is called before flushing any data,
- // so we don't need to set `timings.phases.request` here.
- },
- secureConnect: () => {
- timings.secureConnect = Date.now();
- timings.phases.tls = timings.secureConnect - timings.connect;
- }
- });
- };
- if (request.socket) {
- onSocket(request.socket);
- }
- else {
- request.prependOnceListener('socket', onSocket);
- }
- const onUpload = () => {
- var _a;
- timings.upload = Date.now();
- timings.phases.request = timings.upload - ((_a = timings.secureConnect) !== null && _a !== void 0 ? _a : timings.connect);
- };
- const writableFinished = () => {
- if (typeof request.writableFinished === 'boolean') {
- return request.writableFinished;
- }
- // Node.js doesn't have `request.writableFinished` property
- return request.finished && request.outputSize === 0 && (!request.socket || request.socket.writableLength === 0);
- };
- if (writableFinished()) {
- onUpload();
- }
- else {
- request.prependOnceListener('finish', onUpload);
- }
- request.prependOnceListener('response', (response) => {
- timings.response = Date.now();
- timings.phases.firstByte = timings.response - timings.upload;
- response.timings = timings;
- handleError(response);
- response.prependOnceListener('end', () => {
- timings.end = Date.now();
- timings.phases.download = timings.end - timings.response;
- timings.phases.total = timings.end - timings.start;
- });
- response.prependOnceListener('aborted', onAbort);
- });
- return timings;
- };
- exports.default = timer;
- // For CommonJS default export support
- module.exports = timer;
- module.exports.default = timer;
|