rezo 1.0.45 → 1.0.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,6 +22,7 @@ const { ResponseCache } = require('../cache/response-cache.cjs');
22
22
  const { getGlobalAgentPool } = require('../utils/agent-pool.cjs');
23
23
  const { StagedTimeoutManager, parseStagedTimeouts } = require('../utils/staged-timeout.cjs');
24
24
  const { handleRateLimitWait, shouldWaitOnStatus } = require('../utils/rate-limit-wait.cjs');
25
+ const { getSocketTelemetry, beginRequestContext } = require('../utils/socket-telemetry.cjs');
25
26
  const dns = require("node:dns");
26
27
  const debugLog = {
27
28
  requestStart: (config, url, method) => {
@@ -1029,149 +1030,188 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
1029
1030
  }
1030
1031
  resolve(error);
1031
1032
  });
1032
- const isAlreadyConnected = !socket.connecting && (socket.readyState === "open" || socket.writable === true);
1033
- if (isAlreadyConnected) {
1034
- timeoutManager.clearPhase("connect");
1035
- if (timeoutManager.hasPhase("headers")) {
1036
- timeoutManager.startPhase("headers");
1037
- }
1038
- } else {
1039
- if (timeoutManager.hasPhase("connect")) {
1040
- timeoutManager.startPhase("connect");
1041
- }
1042
- }
1043
- socket.on("error", (err) => {
1033
+ const reqContext = beginRequestContext(socket, isSecure);
1034
+ const telemetry = getSocketTelemetry(socket);
1035
+ socket.once("error", (err) => {
1044
1036
  timeoutManager.clearAll();
1045
1037
  _stats.statusOnNext = "error";
1046
1038
  const error = buildSmartError(config, fetchOptions, err);
1047
1039
  resolve(error);
1048
1040
  });
1049
- timing.dnsStart = performance.now();
1050
- config.timing.domainLookupStart = timing.dnsStart;
1051
- socket.on("lookup", (err, address, family) => {
1052
- if (!timing.dnsEnd) {
1053
- timing.dnsEnd = performance.now();
1054
- config.timing.domainLookupEnd = timing.dnsEnd;
1055
- timing.tcpStart = performance.now();
1056
- config.timing.connectStart = timing.tcpStart;
1057
- }
1058
- if (config.hooks?.onDns && config.hooks.onDns.length > 0) {
1059
- const familyNum = typeof family === "number" ? family : family === "IPv6" ? 6 : 4;
1060
- for (const hook of config.hooks.onDns) {
1061
- try {
1062
- hook({
1063
- hostname: url.hostname,
1064
- address: address || "",
1065
- family: familyNum,
1066
- duration: timing.dnsEnd - timing.dnsStart,
1067
- timestamp: Date.now()
1068
- }, config);
1069
- } catch (err) {
1070
- if (config.debug) {
1071
- console.log("[Rezo Debug] onDns hook error:", err);
1072
- }
1073
- }
1074
- }
1075
- }
1076
- });
1077
- socket.on("secureConnect", () => {
1041
+ if (reqContext.connectionReused) {
1078
1042
  timeoutManager.clearPhase("connect");
1079
1043
  if (timeoutManager.hasPhase("headers")) {
1080
1044
  timeoutManager.startPhase("headers");
1081
1045
  }
1082
- if (!timing.tlsEnd && timing.tlsStart) {
1083
- timing.tlsEnd = performance.now();
1084
- config.timing.connectEnd = timing.tlsEnd;
1046
+ if (telemetry) {
1047
+ config.timing.domainLookupStart = timing.dnsStart = performance.now();
1048
+ config.timing.domainLookupEnd = timing.dnsEnd = timing.dnsStart;
1049
+ config.timing.connectStart = timing.tcpStart = timing.dnsEnd;
1050
+ config.timing.connectEnd = timing.tcpEnd = timing.tcpStart;
1051
+ if (telemetry.network.remoteAddress) {
1052
+ config.network.remoteAddress = telemetry.network.remoteAddress;
1053
+ config.network.remotePort = telemetry.network.remotePort;
1054
+ config.network.localAddress = telemetry.network.localAddress;
1055
+ config.network.localPort = telemetry.network.localPort;
1056
+ config.network.family = telemetry.network.family;
1057
+ }
1058
+ if (isSecure && telemetry.tls) {
1059
+ config.security.tlsVersion = telemetry.tls.protocol;
1060
+ config.security.cipher = telemetry.tls.cipher;
1061
+ if (telemetry.tls.certificate) {
1062
+ config.security.certificateInfo = {
1063
+ subject: { CN: telemetry.tls.certificate.subject },
1064
+ issuer: { CN: telemetry.tls.certificate.issuer },
1065
+ validFrom: telemetry.tls.certificate.validFrom,
1066
+ validTo: telemetry.tls.certificate.validTo,
1067
+ fingerprint: telemetry.tls.certificate.fingerprint
1068
+ };
1069
+ }
1070
+ }
1071
+ config.connectionReuse = {
1072
+ reused: true,
1073
+ reuseCount: telemetry.reuse.count,
1074
+ socketAge: Date.now() - telemetry.timings.created,
1075
+ historicalDns: telemetry.timings.dnsDuration || 0,
1076
+ historicalTcp: telemetry.timings.tcpDuration || 0,
1077
+ historicalTls: telemetry.timings.tlsDuration || 0
1078
+ };
1085
1079
  }
1086
- const tls = {
1087
- cipher: socket.getCipher(),
1088
- cert: socket.getPeerCertificate(),
1089
- tlsVersion: socket.getProtocol()
1090
- };
1091
- const { cipher, cert, tlsVersion } = tls;
1092
- config.security.tlsVersion = tlsVersion;
1093
- config.security.cipher = cipher?.name;
1094
- config.security.certificateInfo = {
1095
- subject: cert.subject,
1096
- issuer: cert.issuer,
1097
- validFrom: cert.valid_from,
1098
- validTo: cert.valid_to,
1099
- fingerprint: cert.fingerprint
1100
- };
1101
- config.security.validationResults = {
1102
- certificateValid: !cert.fingerprint?.includes("error"),
1103
- hostnameMatch: cert.subject?.CN === url.hostname,
1104
- chainValid: socket.authorized === true,
1105
- authorizationError: socket.authorizationError || null
1080
+ } else {
1081
+ if (timeoutManager.hasPhase("connect")) {
1082
+ timeoutManager.startPhase("connect");
1083
+ }
1084
+ timing.dnsStart = performance.now();
1085
+ config.timing.domainLookupStart = timing.dnsStart;
1086
+ config.connectionReuse = {
1087
+ reused: false,
1088
+ reuseCount: 1
1106
1089
  };
1107
- if (config.hooks?.onTls && config.hooks.onTls.length > 0) {
1108
- for (const hook of config.hooks.onTls) {
1109
- try {
1110
- hook({
1111
- protocol: tlsVersion,
1112
- cipher: cipher?.name || "",
1113
- authorized: !socket.authorizationError,
1114
- authorizationError: socket.authorizationError,
1115
- certificate: cert ? {
1116
- subject: cert.subject?.CN || "",
1117
- issuer: cert.issuer?.CN || "",
1118
- validFrom: cert.valid_from || "",
1119
- validTo: cert.valid_to || "",
1120
- fingerprint: cert.fingerprint || ""
1121
- } : undefined,
1122
- duration: timing.tlsEnd - timing.tlsStart,
1123
- timestamp: Date.now()
1124
- }, config);
1125
- } catch (err) {
1126
- if (config.debug) {
1127
- console.log("[Rezo Debug] onTls hook error:", err);
1090
+ const populateFromTelemetry = () => {
1091
+ if (!telemetry)
1092
+ return;
1093
+ if (telemetry.timings.dnsEnd && !timing.dnsEnd) {
1094
+ timing.dnsEnd = performance.now();
1095
+ config.timing.domainLookupEnd = timing.dnsEnd;
1096
+ timing.tcpStart = performance.now();
1097
+ config.timing.connectStart = timing.tcpStart;
1098
+ if (config.hooks?.onDns && config.hooks.onDns.length > 0) {
1099
+ for (const hook of config.hooks.onDns) {
1100
+ try {
1101
+ hook({
1102
+ hostname: url.hostname,
1103
+ address: telemetry.timings.address || "",
1104
+ family: telemetry.timings.family || 4,
1105
+ duration: telemetry.timings.dnsDuration || 0,
1106
+ timestamp: Date.now()
1107
+ }, config);
1108
+ } catch (err) {
1109
+ if (config.debug) {
1110
+ console.log("[Rezo Debug] onDns hook error:", err);
1111
+ }
1112
+ }
1128
1113
  }
1129
1114
  }
1130
1115
  }
1131
- }
1132
- });
1133
- socket.on("connect", () => {
1134
- if (!isSecure) {
1135
- timeoutManager.clearPhase("connect");
1136
- if (timeoutManager.hasPhase("headers")) {
1137
- timeoutManager.startPhase("headers");
1138
- }
1139
- }
1140
- if (!timing.tcpEnd) {
1141
- timing.tcpEnd = performance.now();
1142
- config.timing.connectEnd = timing.tcpEnd;
1143
- if (isSecure) {
1144
- timing.tlsStart = performance.now();
1145
- config.timing.secureConnectionStart = timing.tlsStart;
1116
+ if (telemetry.timings.connectEnd && !timing.tcpEnd) {
1117
+ timing.tcpEnd = performance.now();
1118
+ config.timing.connectEnd = timing.tcpEnd;
1119
+ if (isSecure) {
1120
+ timing.tlsStart = performance.now();
1121
+ config.timing.secureConnectionStart = timing.tlsStart;
1122
+ }
1123
+ if (telemetry.network.remoteAddress) {
1124
+ config.network.remoteAddress = telemetry.network.remoteAddress;
1125
+ config.network.remotePort = telemetry.network.remotePort;
1126
+ config.network.localAddress = telemetry.network.localAddress;
1127
+ config.network.localPort = telemetry.network.localPort;
1128
+ config.network.family = telemetry.network.family;
1129
+ }
1130
+ if (config.hooks?.onSocket && config.hooks.onSocket.length > 0) {
1131
+ for (const hook of config.hooks.onSocket) {
1132
+ try {
1133
+ hook({
1134
+ type: "connect",
1135
+ localAddress: telemetry.network.localAddress,
1136
+ localPort: telemetry.network.localPort,
1137
+ remoteAddress: telemetry.network.remoteAddress,
1138
+ remotePort: telemetry.network.remotePort,
1139
+ timestamp: Date.now()
1140
+ }, socket);
1141
+ } catch (err) {
1142
+ if (config.debug) {
1143
+ console.log("[Rezo Debug] onSocket hook error:", err);
1144
+ }
1145
+ }
1146
+ }
1147
+ }
1148
+ if (!isSecure) {
1149
+ timeoutManager.clearPhase("connect");
1150
+ if (timeoutManager.hasPhase("headers")) {
1151
+ timeoutManager.startPhase("headers");
1152
+ }
1153
+ }
1146
1154
  }
1147
- }
1148
- const { remoteAddress, remotePort, localAddress, localPort, remoteFamily } = socket;
1149
- if (remoteAddress && !config.network.remoteAddress) {
1150
- config.network.remoteAddress = remoteAddress;
1151
- config.network.remotePort = remotePort;
1152
- config.network.localAddress = localAddress;
1153
- config.network.localPort = localPort;
1154
- config.network.family = remoteFamily;
1155
- }
1156
- if (config.hooks?.onSocket && config.hooks.onSocket.length > 0) {
1157
- for (const hook of config.hooks.onSocket) {
1158
- try {
1159
- hook({
1160
- type: "connect",
1161
- localAddress,
1162
- localPort,
1163
- remoteAddress,
1164
- remotePort,
1165
- timestamp: Date.now()
1166
- }, socket);
1167
- } catch (err) {
1168
- if (config.debug) {
1169
- console.log("[Rezo Debug] onSocket hook error:", err);
1155
+ if (isSecure && telemetry.timings.secureConnectEnd && !timing.tlsEnd) {
1156
+ timing.tlsEnd = performance.now();
1157
+ config.timing.connectEnd = timing.tlsEnd;
1158
+ timeoutManager.clearPhase("connect");
1159
+ if (timeoutManager.hasPhase("headers")) {
1160
+ timeoutManager.startPhase("headers");
1161
+ }
1162
+ if (telemetry.tls) {
1163
+ config.security.tlsVersion = telemetry.tls.protocol;
1164
+ config.security.cipher = telemetry.tls.cipher;
1165
+ config.security.certificateInfo = telemetry.tls.certificate ? {
1166
+ subject: { CN: telemetry.tls.certificate.subject },
1167
+ issuer: { CN: telemetry.tls.certificate.issuer },
1168
+ validFrom: telemetry.tls.certificate.validFrom,
1169
+ validTo: telemetry.tls.certificate.validTo,
1170
+ fingerprint: telemetry.tls.certificate.fingerprint
1171
+ } : undefined;
1172
+ config.security.validationResults = {
1173
+ certificateValid: true,
1174
+ hostnameMatch: telemetry.tls.certificate?.subject === url.hostname || false,
1175
+ chainValid: telemetry.tls.authorized === true,
1176
+ authorizationError: telemetry.tls.authorizationError ? true : false
1177
+ };
1178
+ if (config.hooks?.onTls && config.hooks.onTls.length > 0) {
1179
+ for (const hook of config.hooks.onTls) {
1180
+ try {
1181
+ hook({
1182
+ protocol: telemetry.tls.protocol || "",
1183
+ cipher: telemetry.tls.cipher || "",
1184
+ authorized: telemetry.tls.authorized !== false,
1185
+ authorizationError: telemetry.tls.authorizationError,
1186
+ certificate: telemetry.tls.certificate ? {
1187
+ subject: telemetry.tls.certificate.subject || "",
1188
+ issuer: telemetry.tls.certificate.issuer || "",
1189
+ validFrom: telemetry.tls.certificate.validFrom || "",
1190
+ validTo: telemetry.tls.certificate.validTo || "",
1191
+ fingerprint: telemetry.tls.certificate.fingerprint || ""
1192
+ } : undefined,
1193
+ duration: telemetry.timings.tlsDuration || 0,
1194
+ timestamp: Date.now()
1195
+ }, config);
1196
+ } catch (err) {
1197
+ if (config.debug) {
1198
+ console.log("[Rezo Debug] onTls hook error:", err);
1199
+ }
1200
+ }
1201
+ }
1170
1202
  }
1171
1203
  }
1172
1204
  }
1173
- }
1174
- });
1205
+ };
1206
+ const checkTelemetry = setInterval(() => {
1207
+ if (telemetry?.connected || telemetry?.closed) {
1208
+ clearInterval(checkTelemetry);
1209
+ populateFromTelemetry();
1210
+ }
1211
+ }, 1);
1212
+ socket.once("close", () => clearInterval(checkTelemetry));
1213
+ setTimeout(() => clearInterval(checkTelemetry), 30000);
1214
+ }
1175
1215
  });
1176
1216
  req.on("error", (error) => {
1177
1217
  timeoutManager.clearAll();
@@ -22,6 +22,7 @@ import { ResponseCache } from '../cache/response-cache.js';
22
22
  import { getGlobalAgentPool } from '../utils/agent-pool.js';
23
23
  import { StagedTimeoutManager, parseStagedTimeouts } from '../utils/staged-timeout.js';
24
24
  import { handleRateLimitWait, shouldWaitOnStatus } from '../utils/rate-limit-wait.js';
25
+ import { getSocketTelemetry, beginRequestContext } from '../utils/socket-telemetry.js';
25
26
  import dns from "node:dns";
26
27
  const debugLog = {
27
28
  requestStart: (config, url, method) => {
@@ -1029,149 +1030,188 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
1029
1030
  }
1030
1031
  resolve(error);
1031
1032
  });
1032
- const isAlreadyConnected = !socket.connecting && (socket.readyState === "open" || socket.writable === true);
1033
- if (isAlreadyConnected) {
1034
- timeoutManager.clearPhase("connect");
1035
- if (timeoutManager.hasPhase("headers")) {
1036
- timeoutManager.startPhase("headers");
1037
- }
1038
- } else {
1039
- if (timeoutManager.hasPhase("connect")) {
1040
- timeoutManager.startPhase("connect");
1041
- }
1042
- }
1043
- socket.on("error", (err) => {
1033
+ const reqContext = beginRequestContext(socket, isSecure);
1034
+ const telemetry = getSocketTelemetry(socket);
1035
+ socket.once("error", (err) => {
1044
1036
  timeoutManager.clearAll();
1045
1037
  _stats.statusOnNext = "error";
1046
1038
  const error = buildSmartError(config, fetchOptions, err);
1047
1039
  resolve(error);
1048
1040
  });
1049
- timing.dnsStart = performance.now();
1050
- config.timing.domainLookupStart = timing.dnsStart;
1051
- socket.on("lookup", (err, address, family) => {
1052
- if (!timing.dnsEnd) {
1053
- timing.dnsEnd = performance.now();
1054
- config.timing.domainLookupEnd = timing.dnsEnd;
1055
- timing.tcpStart = performance.now();
1056
- config.timing.connectStart = timing.tcpStart;
1057
- }
1058
- if (config.hooks?.onDns && config.hooks.onDns.length > 0) {
1059
- const familyNum = typeof family === "number" ? family : family === "IPv6" ? 6 : 4;
1060
- for (const hook of config.hooks.onDns) {
1061
- try {
1062
- hook({
1063
- hostname: url.hostname,
1064
- address: address || "",
1065
- family: familyNum,
1066
- duration: timing.dnsEnd - timing.dnsStart,
1067
- timestamp: Date.now()
1068
- }, config);
1069
- } catch (err) {
1070
- if (config.debug) {
1071
- console.log("[Rezo Debug] onDns hook error:", err);
1072
- }
1073
- }
1074
- }
1075
- }
1076
- });
1077
- socket.on("secureConnect", () => {
1041
+ if (reqContext.connectionReused) {
1078
1042
  timeoutManager.clearPhase("connect");
1079
1043
  if (timeoutManager.hasPhase("headers")) {
1080
1044
  timeoutManager.startPhase("headers");
1081
1045
  }
1082
- if (!timing.tlsEnd && timing.tlsStart) {
1083
- timing.tlsEnd = performance.now();
1084
- config.timing.connectEnd = timing.tlsEnd;
1046
+ if (telemetry) {
1047
+ config.timing.domainLookupStart = timing.dnsStart = performance.now();
1048
+ config.timing.domainLookupEnd = timing.dnsEnd = timing.dnsStart;
1049
+ config.timing.connectStart = timing.tcpStart = timing.dnsEnd;
1050
+ config.timing.connectEnd = timing.tcpEnd = timing.tcpStart;
1051
+ if (telemetry.network.remoteAddress) {
1052
+ config.network.remoteAddress = telemetry.network.remoteAddress;
1053
+ config.network.remotePort = telemetry.network.remotePort;
1054
+ config.network.localAddress = telemetry.network.localAddress;
1055
+ config.network.localPort = telemetry.network.localPort;
1056
+ config.network.family = telemetry.network.family;
1057
+ }
1058
+ if (isSecure && telemetry.tls) {
1059
+ config.security.tlsVersion = telemetry.tls.protocol;
1060
+ config.security.cipher = telemetry.tls.cipher;
1061
+ if (telemetry.tls.certificate) {
1062
+ config.security.certificateInfo = {
1063
+ subject: { CN: telemetry.tls.certificate.subject },
1064
+ issuer: { CN: telemetry.tls.certificate.issuer },
1065
+ validFrom: telemetry.tls.certificate.validFrom,
1066
+ validTo: telemetry.tls.certificate.validTo,
1067
+ fingerprint: telemetry.tls.certificate.fingerprint
1068
+ };
1069
+ }
1070
+ }
1071
+ config.connectionReuse = {
1072
+ reused: true,
1073
+ reuseCount: telemetry.reuse.count,
1074
+ socketAge: Date.now() - telemetry.timings.created,
1075
+ historicalDns: telemetry.timings.dnsDuration || 0,
1076
+ historicalTcp: telemetry.timings.tcpDuration || 0,
1077
+ historicalTls: telemetry.timings.tlsDuration || 0
1078
+ };
1085
1079
  }
1086
- const tls = {
1087
- cipher: socket.getCipher(),
1088
- cert: socket.getPeerCertificate(),
1089
- tlsVersion: socket.getProtocol()
1090
- };
1091
- const { cipher, cert, tlsVersion } = tls;
1092
- config.security.tlsVersion = tlsVersion;
1093
- config.security.cipher = cipher?.name;
1094
- config.security.certificateInfo = {
1095
- subject: cert.subject,
1096
- issuer: cert.issuer,
1097
- validFrom: cert.valid_from,
1098
- validTo: cert.valid_to,
1099
- fingerprint: cert.fingerprint
1100
- };
1101
- config.security.validationResults = {
1102
- certificateValid: !cert.fingerprint?.includes("error"),
1103
- hostnameMatch: cert.subject?.CN === url.hostname,
1104
- chainValid: socket.authorized === true,
1105
- authorizationError: socket.authorizationError || null
1080
+ } else {
1081
+ if (timeoutManager.hasPhase("connect")) {
1082
+ timeoutManager.startPhase("connect");
1083
+ }
1084
+ timing.dnsStart = performance.now();
1085
+ config.timing.domainLookupStart = timing.dnsStart;
1086
+ config.connectionReuse = {
1087
+ reused: false,
1088
+ reuseCount: 1
1106
1089
  };
1107
- if (config.hooks?.onTls && config.hooks.onTls.length > 0) {
1108
- for (const hook of config.hooks.onTls) {
1109
- try {
1110
- hook({
1111
- protocol: tlsVersion,
1112
- cipher: cipher?.name || "",
1113
- authorized: !socket.authorizationError,
1114
- authorizationError: socket.authorizationError,
1115
- certificate: cert ? {
1116
- subject: cert.subject?.CN || "",
1117
- issuer: cert.issuer?.CN || "",
1118
- validFrom: cert.valid_from || "",
1119
- validTo: cert.valid_to || "",
1120
- fingerprint: cert.fingerprint || ""
1121
- } : undefined,
1122
- duration: timing.tlsEnd - timing.tlsStart,
1123
- timestamp: Date.now()
1124
- }, config);
1125
- } catch (err) {
1126
- if (config.debug) {
1127
- console.log("[Rezo Debug] onTls hook error:", err);
1090
+ const populateFromTelemetry = () => {
1091
+ if (!telemetry)
1092
+ return;
1093
+ if (telemetry.timings.dnsEnd && !timing.dnsEnd) {
1094
+ timing.dnsEnd = performance.now();
1095
+ config.timing.domainLookupEnd = timing.dnsEnd;
1096
+ timing.tcpStart = performance.now();
1097
+ config.timing.connectStart = timing.tcpStart;
1098
+ if (config.hooks?.onDns && config.hooks.onDns.length > 0) {
1099
+ for (const hook of config.hooks.onDns) {
1100
+ try {
1101
+ hook({
1102
+ hostname: url.hostname,
1103
+ address: telemetry.timings.address || "",
1104
+ family: telemetry.timings.family || 4,
1105
+ duration: telemetry.timings.dnsDuration || 0,
1106
+ timestamp: Date.now()
1107
+ }, config);
1108
+ } catch (err) {
1109
+ if (config.debug) {
1110
+ console.log("[Rezo Debug] onDns hook error:", err);
1111
+ }
1112
+ }
1128
1113
  }
1129
1114
  }
1130
1115
  }
1131
- }
1132
- });
1133
- socket.on("connect", () => {
1134
- if (!isSecure) {
1135
- timeoutManager.clearPhase("connect");
1136
- if (timeoutManager.hasPhase("headers")) {
1137
- timeoutManager.startPhase("headers");
1138
- }
1139
- }
1140
- if (!timing.tcpEnd) {
1141
- timing.tcpEnd = performance.now();
1142
- config.timing.connectEnd = timing.tcpEnd;
1143
- if (isSecure) {
1144
- timing.tlsStart = performance.now();
1145
- config.timing.secureConnectionStart = timing.tlsStart;
1116
+ if (telemetry.timings.connectEnd && !timing.tcpEnd) {
1117
+ timing.tcpEnd = performance.now();
1118
+ config.timing.connectEnd = timing.tcpEnd;
1119
+ if (isSecure) {
1120
+ timing.tlsStart = performance.now();
1121
+ config.timing.secureConnectionStart = timing.tlsStart;
1122
+ }
1123
+ if (telemetry.network.remoteAddress) {
1124
+ config.network.remoteAddress = telemetry.network.remoteAddress;
1125
+ config.network.remotePort = telemetry.network.remotePort;
1126
+ config.network.localAddress = telemetry.network.localAddress;
1127
+ config.network.localPort = telemetry.network.localPort;
1128
+ config.network.family = telemetry.network.family;
1129
+ }
1130
+ if (config.hooks?.onSocket && config.hooks.onSocket.length > 0) {
1131
+ for (const hook of config.hooks.onSocket) {
1132
+ try {
1133
+ hook({
1134
+ type: "connect",
1135
+ localAddress: telemetry.network.localAddress,
1136
+ localPort: telemetry.network.localPort,
1137
+ remoteAddress: telemetry.network.remoteAddress,
1138
+ remotePort: telemetry.network.remotePort,
1139
+ timestamp: Date.now()
1140
+ }, socket);
1141
+ } catch (err) {
1142
+ if (config.debug) {
1143
+ console.log("[Rezo Debug] onSocket hook error:", err);
1144
+ }
1145
+ }
1146
+ }
1147
+ }
1148
+ if (!isSecure) {
1149
+ timeoutManager.clearPhase("connect");
1150
+ if (timeoutManager.hasPhase("headers")) {
1151
+ timeoutManager.startPhase("headers");
1152
+ }
1153
+ }
1146
1154
  }
1147
- }
1148
- const { remoteAddress, remotePort, localAddress, localPort, remoteFamily } = socket;
1149
- if (remoteAddress && !config.network.remoteAddress) {
1150
- config.network.remoteAddress = remoteAddress;
1151
- config.network.remotePort = remotePort;
1152
- config.network.localAddress = localAddress;
1153
- config.network.localPort = localPort;
1154
- config.network.family = remoteFamily;
1155
- }
1156
- if (config.hooks?.onSocket && config.hooks.onSocket.length > 0) {
1157
- for (const hook of config.hooks.onSocket) {
1158
- try {
1159
- hook({
1160
- type: "connect",
1161
- localAddress,
1162
- localPort,
1163
- remoteAddress,
1164
- remotePort,
1165
- timestamp: Date.now()
1166
- }, socket);
1167
- } catch (err) {
1168
- if (config.debug) {
1169
- console.log("[Rezo Debug] onSocket hook error:", err);
1155
+ if (isSecure && telemetry.timings.secureConnectEnd && !timing.tlsEnd) {
1156
+ timing.tlsEnd = performance.now();
1157
+ config.timing.connectEnd = timing.tlsEnd;
1158
+ timeoutManager.clearPhase("connect");
1159
+ if (timeoutManager.hasPhase("headers")) {
1160
+ timeoutManager.startPhase("headers");
1161
+ }
1162
+ if (telemetry.tls) {
1163
+ config.security.tlsVersion = telemetry.tls.protocol;
1164
+ config.security.cipher = telemetry.tls.cipher;
1165
+ config.security.certificateInfo = telemetry.tls.certificate ? {
1166
+ subject: { CN: telemetry.tls.certificate.subject },
1167
+ issuer: { CN: telemetry.tls.certificate.issuer },
1168
+ validFrom: telemetry.tls.certificate.validFrom,
1169
+ validTo: telemetry.tls.certificate.validTo,
1170
+ fingerprint: telemetry.tls.certificate.fingerprint
1171
+ } : undefined;
1172
+ config.security.validationResults = {
1173
+ certificateValid: true,
1174
+ hostnameMatch: telemetry.tls.certificate?.subject === url.hostname || false,
1175
+ chainValid: telemetry.tls.authorized === true,
1176
+ authorizationError: telemetry.tls.authorizationError ? true : false
1177
+ };
1178
+ if (config.hooks?.onTls && config.hooks.onTls.length > 0) {
1179
+ for (const hook of config.hooks.onTls) {
1180
+ try {
1181
+ hook({
1182
+ protocol: telemetry.tls.protocol || "",
1183
+ cipher: telemetry.tls.cipher || "",
1184
+ authorized: telemetry.tls.authorized !== false,
1185
+ authorizationError: telemetry.tls.authorizationError,
1186
+ certificate: telemetry.tls.certificate ? {
1187
+ subject: telemetry.tls.certificate.subject || "",
1188
+ issuer: telemetry.tls.certificate.issuer || "",
1189
+ validFrom: telemetry.tls.certificate.validFrom || "",
1190
+ validTo: telemetry.tls.certificate.validTo || "",
1191
+ fingerprint: telemetry.tls.certificate.fingerprint || ""
1192
+ } : undefined,
1193
+ duration: telemetry.timings.tlsDuration || 0,
1194
+ timestamp: Date.now()
1195
+ }, config);
1196
+ } catch (err) {
1197
+ if (config.debug) {
1198
+ console.log("[Rezo Debug] onTls hook error:", err);
1199
+ }
1200
+ }
1201
+ }
1170
1202
  }
1171
1203
  }
1172
1204
  }
1173
- }
1174
- });
1205
+ };
1206
+ const checkTelemetry = setInterval(() => {
1207
+ if (telemetry?.connected || telemetry?.closed) {
1208
+ clearInterval(checkTelemetry);
1209
+ populateFromTelemetry();
1210
+ }
1211
+ }, 1);
1212
+ socket.once("close", () => clearInterval(checkTelemetry));
1213
+ setTimeout(() => clearInterval(checkTelemetry), 30000);
1214
+ }
1175
1215
  });
1176
1216
  req.on("error", (error) => {
1177
1217
  timeoutManager.clearAll();
@@ -260,6 +260,7 @@ class Http2SessionPool {
260
260
  }
261
261
  return new Promise((resolve, reject) => {
262
262
  const session = http2.connect(authority, sessionOptions);
263
+ session.setMaxListeners(20);
263
264
  let settled = false;
264
265
  const timeoutId = timeout ? setTimeout(() => {
265
266
  if (!settled) {
@@ -337,6 +338,7 @@ class Http2SessionPool {
337
338
  rejectUnauthorized: rejectUnauthorized !== false,
338
339
  ALPNProtocols: ["h2", "http/1.1"]
339
340
  });
341
+ tlsSocket.setMaxListeners(20);
340
342
  const tlsTimeoutId = timeout ? setTimeout(() => {
341
343
  tlsSocket.destroy();
342
344
  reject(new Error(`TLS handshake timeout after ${timeout}ms`));
@@ -434,6 +436,7 @@ class Http2SessionPool {
434
436
  rejectUnauthorized: rejectUnauthorized !== false,
435
437
  ALPNProtocols: ["h2", "http/1.1"]
436
438
  });
439
+ tlsSocket.setMaxListeners(20);
437
440
  const tlsTimeoutId = timeout ? setTimeout(() => {
438
441
  tlsSocket.destroy();
439
442
  reject(new Error(`TLS handshake timeout after ${timeout}ms`));
@@ -260,6 +260,7 @@ class Http2SessionPool {
260
260
  }
261
261
  return new Promise((resolve, reject) => {
262
262
  const session = http2.connect(authority, sessionOptions);
263
+ session.setMaxListeners(20);
263
264
  let settled = false;
264
265
  const timeoutId = timeout ? setTimeout(() => {
265
266
  if (!settled) {
@@ -337,6 +338,7 @@ class Http2SessionPool {
337
338
  rejectUnauthorized: rejectUnauthorized !== false,
338
339
  ALPNProtocols: ["h2", "http/1.1"]
339
340
  });
341
+ tlsSocket.setMaxListeners(20);
340
342
  const tlsTimeoutId = timeout ? setTimeout(() => {
341
343
  tlsSocket.destroy();
342
344
  reject(new Error(`TLS handshake timeout after ${timeout}ms`));
@@ -434,6 +436,7 @@ class Http2SessionPool {
434
436
  rejectUnauthorized: rejectUnauthorized !== false,
435
437
  ALPNProtocols: ["h2", "http/1.1"]
436
438
  });
439
+ tlsSocket.setMaxListeners(20);
437
440
  const tlsTimeoutId = timeout ? setTimeout(() => {
438
441
  tlsSocket.destroy();
439
442
  reject(new Error(`TLS handshake timeout after ${timeout}ms`));
@@ -1,6 +1,6 @@
1
- const _mod_jrw0vw = require('./picker.cjs');
2
- exports.detectRuntime = _mod_jrw0vw.detectRuntime;
3
- exports.getAdapterCapabilities = _mod_jrw0vw.getAdapterCapabilities;
4
- exports.buildAdapterContext = _mod_jrw0vw.buildAdapterContext;
5
- exports.getAvailableAdapters = _mod_jrw0vw.getAvailableAdapters;
6
- exports.selectAdapter = _mod_jrw0vw.selectAdapter;;
1
+ const _mod_nhcrtu = require('./picker.cjs');
2
+ exports.detectRuntime = _mod_nhcrtu.detectRuntime;
3
+ exports.getAdapterCapabilities = _mod_nhcrtu.getAdapterCapabilities;
4
+ exports.buildAdapterContext = _mod_nhcrtu.buildAdapterContext;
5
+ exports.getAvailableAdapters = _mod_nhcrtu.getAvailableAdapters;
6
+ exports.selectAdapter = _mod_nhcrtu.selectAdapter;;
@@ -1,9 +1,9 @@
1
- const _mod_0ku4z2 = require('./lru-cache.cjs');
2
- exports.LRUCache = _mod_0ku4z2.LRUCache;;
3
- const _mod_odvwch = require('./dns-cache.cjs');
4
- exports.DNSCache = _mod_odvwch.DNSCache;
5
- exports.getGlobalDNSCache = _mod_odvwch.getGlobalDNSCache;
6
- exports.resetGlobalDNSCache = _mod_odvwch.resetGlobalDNSCache;;
7
- const _mod_b9x6qw = require('./response-cache.cjs');
8
- exports.ResponseCache = _mod_b9x6qw.ResponseCache;
9
- exports.normalizeResponseCacheConfig = _mod_b9x6qw.normalizeResponseCacheConfig;;
1
+ const _mod_bw1z42 = require('./lru-cache.cjs');
2
+ exports.LRUCache = _mod_bw1z42.LRUCache;;
3
+ const _mod_pywm2s = require('./dns-cache.cjs');
4
+ exports.DNSCache = _mod_pywm2s.DNSCache;
5
+ exports.getGlobalDNSCache = _mod_pywm2s.getGlobalDNSCache;
6
+ exports.resetGlobalDNSCache = _mod_pywm2s.resetGlobalDNSCache;;
7
+ const _mod_1izn4c = require('./response-cache.cjs');
8
+ exports.ResponseCache = _mod_1izn4c.ResponseCache;
9
+ exports.normalizeResponseCacheConfig = _mod_1izn4c.normalizeResponseCacheConfig;;
@@ -1,40 +1,40 @@
1
- const _mod_ohy0ht = require('./crawler.cjs');
2
- exports.Crawler = _mod_ohy0ht.Crawler;;
3
- const _mod_lcpyaf = require('./crawler-options.cjs');
4
- exports.CrawlerOptions = _mod_lcpyaf.CrawlerOptions;;
5
- const _mod_i89xd7 = require('./plugin/robots-txt.cjs');
6
- exports.RobotsTxt = _mod_i89xd7.RobotsTxt;;
7
- const _mod_5bw1j8 = require('./plugin/file-cacher.cjs');
8
- exports.FileCacher = _mod_5bw1j8.FileCacher;;
9
- const _mod_fhan3k = require('./plugin/url-store.cjs');
10
- exports.UrlStore = _mod_fhan3k.UrlStore;;
11
- const _mod_23xqla = require('./plugin/navigation-history.cjs');
12
- exports.NavigationHistory = _mod_23xqla.NavigationHistory;;
13
- const _mod_bugokk = require('./addon/oxylabs/index.cjs');
14
- exports.Oxylabs = _mod_bugokk.Oxylabs;;
15
- const _mod_rqu5cf = require('./addon/oxylabs/options.cjs');
16
- exports.OXYLABS_BROWSER_TYPES = _mod_rqu5cf.OXYLABS_BROWSER_TYPES;
17
- exports.OXYLABS_COMMON_LOCALES = _mod_rqu5cf.OXYLABS_COMMON_LOCALES;
18
- exports.OXYLABS_COMMON_GEO_LOCATIONS = _mod_rqu5cf.OXYLABS_COMMON_GEO_LOCATIONS;
19
- exports.OXYLABS_US_STATES = _mod_rqu5cf.OXYLABS_US_STATES;
20
- exports.OXYLABS_EUROPEAN_COUNTRIES = _mod_rqu5cf.OXYLABS_EUROPEAN_COUNTRIES;
21
- exports.OXYLABS_ASIAN_COUNTRIES = _mod_rqu5cf.OXYLABS_ASIAN_COUNTRIES;
22
- exports.getRandomOxylabsBrowserType = _mod_rqu5cf.getRandomBrowserType;
23
- exports.getRandomOxylabsLocale = _mod_rqu5cf.getRandomLocale;
24
- exports.getRandomOxylabsGeoLocation = _mod_rqu5cf.getRandomGeoLocation;;
25
- const _mod_eh5umb = require('./addon/decodo/index.cjs');
26
- exports.Decodo = _mod_eh5umb.Decodo;;
27
- const _mod_pa9reb = require('./addon/decodo/options.cjs');
28
- exports.DECODO_DEVICE_TYPES = _mod_pa9reb.DECODO_DEVICE_TYPES;
29
- exports.DECODO_HEADLESS_MODES = _mod_pa9reb.DECODO_HEADLESS_MODES;
30
- exports.DECODO_COMMON_LOCALES = _mod_pa9reb.DECODO_COMMON_LOCALES;
31
- exports.DECODO_COMMON_COUNTRIES = _mod_pa9reb.DECODO_COMMON_COUNTRIES;
32
- exports.DECODO_EUROPEAN_COUNTRIES = _mod_pa9reb.DECODO_EUROPEAN_COUNTRIES;
33
- exports.DECODO_ASIAN_COUNTRIES = _mod_pa9reb.DECODO_ASIAN_COUNTRIES;
34
- exports.DECODO_US_STATES = _mod_pa9reb.DECODO_US_STATES;
35
- exports.DECODO_COMMON_CITIES = _mod_pa9reb.DECODO_COMMON_CITIES;
36
- exports.getRandomDecodoDeviceType = _mod_pa9reb.getRandomDeviceType;
37
- exports.getRandomDecodoLocale = _mod_pa9reb.getRandomLocale;
38
- exports.getRandomDecodoCountry = _mod_pa9reb.getRandomCountry;
39
- exports.getRandomDecodoCity = _mod_pa9reb.getRandomCity;
40
- exports.generateDecodoSessionId = _mod_pa9reb.generateSessionId;;
1
+ const _mod_9vxiez = require('./crawler.cjs');
2
+ exports.Crawler = _mod_9vxiez.Crawler;;
3
+ const _mod_y54fdi = require('./crawler-options.cjs');
4
+ exports.CrawlerOptions = _mod_y54fdi.CrawlerOptions;;
5
+ const _mod_wq1zsf = require('./plugin/robots-txt.cjs');
6
+ exports.RobotsTxt = _mod_wq1zsf.RobotsTxt;;
7
+ const _mod_m3lb7n = require('./plugin/file-cacher.cjs');
8
+ exports.FileCacher = _mod_m3lb7n.FileCacher;;
9
+ const _mod_lp12wc = require('./plugin/url-store.cjs');
10
+ exports.UrlStore = _mod_lp12wc.UrlStore;;
11
+ const _mod_mauvz5 = require('./plugin/navigation-history.cjs');
12
+ exports.NavigationHistory = _mod_mauvz5.NavigationHistory;;
13
+ const _mod_ajlky5 = require('./addon/oxylabs/index.cjs');
14
+ exports.Oxylabs = _mod_ajlky5.Oxylabs;;
15
+ const _mod_u3qll6 = require('./addon/oxylabs/options.cjs');
16
+ exports.OXYLABS_BROWSER_TYPES = _mod_u3qll6.OXYLABS_BROWSER_TYPES;
17
+ exports.OXYLABS_COMMON_LOCALES = _mod_u3qll6.OXYLABS_COMMON_LOCALES;
18
+ exports.OXYLABS_COMMON_GEO_LOCATIONS = _mod_u3qll6.OXYLABS_COMMON_GEO_LOCATIONS;
19
+ exports.OXYLABS_US_STATES = _mod_u3qll6.OXYLABS_US_STATES;
20
+ exports.OXYLABS_EUROPEAN_COUNTRIES = _mod_u3qll6.OXYLABS_EUROPEAN_COUNTRIES;
21
+ exports.OXYLABS_ASIAN_COUNTRIES = _mod_u3qll6.OXYLABS_ASIAN_COUNTRIES;
22
+ exports.getRandomOxylabsBrowserType = _mod_u3qll6.getRandomBrowserType;
23
+ exports.getRandomOxylabsLocale = _mod_u3qll6.getRandomLocale;
24
+ exports.getRandomOxylabsGeoLocation = _mod_u3qll6.getRandomGeoLocation;;
25
+ const _mod_1qdq35 = require('./addon/decodo/index.cjs');
26
+ exports.Decodo = _mod_1qdq35.Decodo;;
27
+ const _mod_2k0fmv = require('./addon/decodo/options.cjs');
28
+ exports.DECODO_DEVICE_TYPES = _mod_2k0fmv.DECODO_DEVICE_TYPES;
29
+ exports.DECODO_HEADLESS_MODES = _mod_2k0fmv.DECODO_HEADLESS_MODES;
30
+ exports.DECODO_COMMON_LOCALES = _mod_2k0fmv.DECODO_COMMON_LOCALES;
31
+ exports.DECODO_COMMON_COUNTRIES = _mod_2k0fmv.DECODO_COMMON_COUNTRIES;
32
+ exports.DECODO_EUROPEAN_COUNTRIES = _mod_2k0fmv.DECODO_EUROPEAN_COUNTRIES;
33
+ exports.DECODO_ASIAN_COUNTRIES = _mod_2k0fmv.DECODO_ASIAN_COUNTRIES;
34
+ exports.DECODO_US_STATES = _mod_2k0fmv.DECODO_US_STATES;
35
+ exports.DECODO_COMMON_CITIES = _mod_2k0fmv.DECODO_COMMON_CITIES;
36
+ exports.getRandomDecodoDeviceType = _mod_2k0fmv.getRandomDeviceType;
37
+ exports.getRandomDecodoLocale = _mod_2k0fmv.getRandomLocale;
38
+ exports.getRandomDecodoCountry = _mod_2k0fmv.getRandomCountry;
39
+ exports.getRandomDecodoCity = _mod_2k0fmv.getRandomCity;
40
+ exports.generateDecodoSessionId = _mod_2k0fmv.generateSessionId;;
@@ -1,5 +1,5 @@
1
- const _mod_xbq6an = require('../crawler/crawler.cjs');
2
- exports.Crawler = _mod_xbq6an.Crawler;;
3
- const _mod_8a6dxq = require('../crawler/crawler-options.cjs');
4
- exports.CrawlerOptions = _mod_8a6dxq.CrawlerOptions;
5
- exports.Domain = _mod_8a6dxq.Domain;;
1
+ const _mod_6eolh9 = require('../crawler/crawler.cjs');
2
+ exports.Crawler = _mod_6eolh9.Crawler;;
3
+ const _mod_28rvj3 = require('../crawler/crawler-options.cjs');
4
+ exports.CrawlerOptions = _mod_28rvj3.CrawlerOptions;
5
+ exports.Domain = _mod_28rvj3.Domain;;
package/dist/index.cjs CHANGED
@@ -1,30 +1,30 @@
1
- const _mod_oop3nu = require('./core/rezo.cjs');
2
- exports.Rezo = _mod_oop3nu.Rezo;
3
- exports.createRezoInstance = _mod_oop3nu.createRezoInstance;
4
- exports.createDefaultInstance = _mod_oop3nu.createDefaultInstance;;
5
- const _mod_39unfu = require('./errors/rezo-error.cjs');
6
- exports.RezoError = _mod_39unfu.RezoError;
7
- exports.RezoErrorCode = _mod_39unfu.RezoErrorCode;;
8
- const _mod_bkzmv4 = require('./utils/headers.cjs');
9
- exports.RezoHeaders = _mod_bkzmv4.RezoHeaders;;
10
- const _mod_3i5b1l = require('./utils/form-data.cjs');
11
- exports.RezoFormData = _mod_3i5b1l.RezoFormData;;
12
- const _mod_rrz4g7 = require('./utils/cookies.cjs');
13
- exports.RezoCookieJar = _mod_rrz4g7.RezoCookieJar;
14
- exports.Cookie = _mod_rrz4g7.Cookie;;
15
- const _mod_zlh68v = require('./utils/curl.cjs');
16
- exports.toCurl = _mod_zlh68v.toCurl;
17
- exports.fromCurl = _mod_zlh68v.fromCurl;;
18
- const _mod_excrbc = require('./core/hooks.cjs');
19
- exports.createDefaultHooks = _mod_excrbc.createDefaultHooks;
20
- exports.mergeHooks = _mod_excrbc.mergeHooks;;
21
- const _mod_xgb0br = require('./proxy/manager.cjs');
22
- exports.ProxyManager = _mod_xgb0br.ProxyManager;;
23
- const _mod_9gi7fv = require('./queue/index.cjs');
24
- exports.RezoQueue = _mod_9gi7fv.RezoQueue;
25
- exports.HttpQueue = _mod_9gi7fv.HttpQueue;
26
- exports.Priority = _mod_9gi7fv.Priority;
27
- exports.HttpMethodPriority = _mod_9gi7fv.HttpMethodPriority;;
1
+ const _mod_s1gca7 = require('./core/rezo.cjs');
2
+ exports.Rezo = _mod_s1gca7.Rezo;
3
+ exports.createRezoInstance = _mod_s1gca7.createRezoInstance;
4
+ exports.createDefaultInstance = _mod_s1gca7.createDefaultInstance;;
5
+ const _mod_v6gpph = require('./errors/rezo-error.cjs');
6
+ exports.RezoError = _mod_v6gpph.RezoError;
7
+ exports.RezoErrorCode = _mod_v6gpph.RezoErrorCode;;
8
+ const _mod_u3m56y = require('./utils/headers.cjs');
9
+ exports.RezoHeaders = _mod_u3m56y.RezoHeaders;;
10
+ const _mod_mswq0f = require('./utils/form-data.cjs');
11
+ exports.RezoFormData = _mod_mswq0f.RezoFormData;;
12
+ const _mod_zi4sg0 = require('./utils/cookies.cjs');
13
+ exports.RezoCookieJar = _mod_zi4sg0.RezoCookieJar;
14
+ exports.Cookie = _mod_zi4sg0.Cookie;;
15
+ const _mod_pmct8p = require('./utils/curl.cjs');
16
+ exports.toCurl = _mod_pmct8p.toCurl;
17
+ exports.fromCurl = _mod_pmct8p.fromCurl;;
18
+ const _mod_joston = require('./core/hooks.cjs');
19
+ exports.createDefaultHooks = _mod_joston.createDefaultHooks;
20
+ exports.mergeHooks = _mod_joston.mergeHooks;;
21
+ const _mod_roms61 = require('./proxy/manager.cjs');
22
+ exports.ProxyManager = _mod_roms61.ProxyManager;;
23
+ const _mod_s72k3v = require('./queue/index.cjs');
24
+ exports.RezoQueue = _mod_s72k3v.RezoQueue;
25
+ exports.HttpQueue = _mod_s72k3v.HttpQueue;
26
+ exports.Priority = _mod_s72k3v.Priority;
27
+ exports.HttpMethodPriority = _mod_s72k3v.HttpMethodPriority;;
28
28
  const { RezoError } = require('./errors/rezo-error.cjs');
29
29
  const isRezoError = exports.isRezoError = RezoError.isRezoError;
30
30
  const Cancel = exports.Cancel = RezoError;
@@ -87,8 +87,8 @@ function parseProxyResponse(socket) {
87
87
  buffered
88
88
  });
89
89
  }
90
- socket.on("error", onerror);
91
- socket.on("end", onend);
90
+ socket.once("error", onerror);
91
+ socket.once("end", onend);
92
92
  read();
93
93
  });
94
94
  }
@@ -87,8 +87,8 @@ function parseProxyResponse(socket) {
87
87
  buffered
88
88
  });
89
89
  }
90
- socket.on("error", onerror);
91
- socket.on("end", onend);
90
+ socket.once("error", onerror);
91
+ socket.once("end", onend);
92
92
  read();
93
93
  });
94
94
  }
@@ -1,10 +1,10 @@
1
- const _mod_ii5t0u = require('./base.cjs');
2
- exports.Agent = _mod_ii5t0u.Agent;;
3
- const _mod_ul6g5e = require('./http-proxy.cjs');
4
- exports.HttpProxyAgent = _mod_ul6g5e.HttpProxyAgent;;
5
- const _mod_nwv5nl = require('./https-proxy.cjs');
6
- exports.HttpsProxyAgent = _mod_nwv5nl.HttpsProxyAgent;;
7
- const _mod_rcnb54 = require('./socks-proxy.cjs');
8
- exports.SocksProxyAgent = _mod_rcnb54.SocksProxyAgent;;
9
- const _mod_g5wt9x = require('./socks-client.cjs');
10
- exports.SocksClient = _mod_g5wt9x.SocksClient;;
1
+ const _mod_zivpen = require('./base.cjs');
2
+ exports.Agent = _mod_zivpen.Agent;;
3
+ const _mod_acdvd9 = require('./http-proxy.cjs');
4
+ exports.HttpProxyAgent = _mod_acdvd9.HttpProxyAgent;;
5
+ const _mod_uuge9b = require('./https-proxy.cjs');
6
+ exports.HttpsProxyAgent = _mod_uuge9b.HttpsProxyAgent;;
7
+ const _mod_6egylw = require('./socks-proxy.cjs');
8
+ exports.SocksProxyAgent = _mod_6egylw.SocksProxyAgent;;
9
+ const _mod_6r9bok = require('./socks-client.cjs');
10
+ exports.SocksClient = _mod_6r9bok.SocksClient;;
@@ -1,9 +1,9 @@
1
1
  const { Agent, HttpProxyAgent, HttpsProxyAgent, SocksProxyAgent } = require('../internal/agents/index.cjs');
2
2
  const { parseProxyString } = require('./parse.cjs');
3
- const _mod_0wfzka = require('./manager.cjs');
4
- exports.ProxyManager = _mod_0wfzka.ProxyManager;;
5
- const _mod_bwzrrk = require('./parse.cjs');
6
- exports.parseProxyString = _mod_bwzrrk.parseProxyString;;
3
+ const _mod_cch0wk = require('./manager.cjs');
4
+ exports.ProxyManager = _mod_cch0wk.ProxyManager;;
5
+ const _mod_ktsrlf = require('./parse.cjs');
6
+ exports.parseProxyString = _mod_ktsrlf.parseProxyString;;
7
7
  function createOptions(uri, opts) {
8
8
  if (uri instanceof URL || typeof uri === "string") {
9
9
  return {
@@ -1,8 +1,8 @@
1
- const _mod_cfqi4l = require('./queue.cjs');
2
- exports.RezoQueue = _mod_cfqi4l.RezoQueue;;
3
- const _mod_9m2if8 = require('./http-queue.cjs');
4
- exports.HttpQueue = _mod_9m2if8.HttpQueue;
5
- exports.extractDomain = _mod_9m2if8.extractDomain;;
6
- const _mod_w9of0o = require('./types.cjs');
7
- exports.Priority = _mod_w9of0o.Priority;
8
- exports.HttpMethodPriority = _mod_w9of0o.HttpMethodPriority;;
1
+ const _mod_vhb3c6 = require('./queue.cjs');
2
+ exports.RezoQueue = _mod_vhb3c6.RezoQueue;;
3
+ const _mod_g8qvdd = require('./http-queue.cjs');
4
+ exports.HttpQueue = _mod_g8qvdd.HttpQueue;
5
+ exports.extractDomain = _mod_g8qvdd.extractDomain;;
6
+ const _mod_ndfksp = require('./types.cjs');
7
+ exports.Priority = _mod_ndfksp.Priority;
8
+ exports.HttpMethodPriority = _mod_ndfksp.HttpMethodPriority;;
@@ -1,11 +1,11 @@
1
- const _mod_rxkza8 = require('./event-emitter.cjs');
2
- exports.UniversalEventEmitter = _mod_rxkza8.UniversalEventEmitter;;
3
- const _mod_gre5wb = require('./stream.cjs');
4
- exports.UniversalStreamResponse = _mod_gre5wb.UniversalStreamResponse;
5
- exports.StreamResponse = _mod_gre5wb.StreamResponse;;
6
- const _mod_xea59w = require('./download.cjs');
7
- exports.UniversalDownloadResponse = _mod_xea59w.UniversalDownloadResponse;
8
- exports.DownloadResponse = _mod_xea59w.DownloadResponse;;
9
- const _mod_1q9fpp = require('./upload.cjs');
10
- exports.UniversalUploadResponse = _mod_1q9fpp.UniversalUploadResponse;
11
- exports.UploadResponse = _mod_1q9fpp.UploadResponse;;
1
+ const _mod_i1xls3 = require('./event-emitter.cjs');
2
+ exports.UniversalEventEmitter = _mod_i1xls3.UniversalEventEmitter;;
3
+ const _mod_ris11a = require('./stream.cjs');
4
+ exports.UniversalStreamResponse = _mod_ris11a.UniversalStreamResponse;
5
+ exports.StreamResponse = _mod_ris11a.StreamResponse;;
6
+ const _mod_itq9aa = require('./download.cjs');
7
+ exports.UniversalDownloadResponse = _mod_itq9aa.UniversalDownloadResponse;
8
+ exports.DownloadResponse = _mod_itq9aa.DownloadResponse;;
9
+ const _mod_c440cb = require('./upload.cjs');
10
+ exports.UniversalUploadResponse = _mod_c440cb.UniversalUploadResponse;
11
+ exports.UploadResponse = _mod_c440cb.UploadResponse;;
@@ -0,0 +1,125 @@
1
+ const socketTelemetryMap = new WeakMap;
2
+ let socketIdCounter = 0;
3
+ function instrumentSocket(socket, isSecure = false) {
4
+ const existing = socketTelemetryMap.get(socket);
5
+ if (existing) {
6
+ existing.reuse.count++;
7
+ existing.reuse.lastUsed = Date.now();
8
+ existing.reuse.isReused = true;
9
+ return existing;
10
+ }
11
+ const now = Date.now();
12
+ const telemetry = {
13
+ id: ++socketIdCounter,
14
+ timings: {
15
+ created: now
16
+ },
17
+ network: {},
18
+ reuse: {
19
+ count: 1,
20
+ lastUsed: now,
21
+ isReused: false
22
+ },
23
+ connected: false,
24
+ closed: false
25
+ };
26
+ socketTelemetryMap.set(socket, telemetry);
27
+ socket.once("lookup", (err, address, family) => {
28
+ if (!err && address) {
29
+ telemetry.timings.dnsEnd = Date.now();
30
+ telemetry.timings.dnsDuration = telemetry.timings.dnsEnd - telemetry.timings.created;
31
+ telemetry.timings.address = address;
32
+ telemetry.timings.family = typeof family === "number" ? family : family === "IPv6" ? 6 : 4;
33
+ }
34
+ });
35
+ socket.once("connect", () => {
36
+ telemetry.timings.connectEnd = Date.now();
37
+ telemetry.timings.tcpDuration = telemetry.timings.connectEnd - (telemetry.timings.dnsEnd || telemetry.timings.created);
38
+ telemetry.connected = true;
39
+ const s = socket;
40
+ telemetry.network = {
41
+ remoteAddress: s.remoteAddress,
42
+ remotePort: s.remotePort,
43
+ localAddress: s.localAddress,
44
+ localPort: s.localPort,
45
+ family: s.remoteFamily
46
+ };
47
+ });
48
+ if (isSecure) {
49
+ socket.once("secureConnect", () => {
50
+ const tlsSocket = socket;
51
+ telemetry.timings.secureConnectEnd = Date.now();
52
+ telemetry.timings.tlsDuration = telemetry.timings.secureConnectEnd - (telemetry.timings.connectEnd || telemetry.timings.created);
53
+ const cipher = tlsSocket.getCipher?.();
54
+ const cert = tlsSocket.getPeerCertificate?.();
55
+ telemetry.tls = {
56
+ protocol: tlsSocket.getProtocol?.() || undefined,
57
+ cipher: cipher?.name,
58
+ authorized: tlsSocket.authorized,
59
+ authorizationError: tlsSocket.authorizationError,
60
+ certificate: cert ? {
61
+ subject: cert.subject?.CN,
62
+ issuer: cert.issuer?.CN,
63
+ validFrom: cert.valid_from,
64
+ validTo: cert.valid_to,
65
+ fingerprint: cert.fingerprint
66
+ } : undefined
67
+ };
68
+ });
69
+ }
70
+ socket.once("close", () => {
71
+ telemetry.closed = true;
72
+ telemetry.connected = false;
73
+ });
74
+ return telemetry;
75
+ }
76
+ function getSocketTelemetry(socket) {
77
+ return socketTelemetryMap.get(socket);
78
+ }
79
+ function isSocketInstrumented(socket) {
80
+ return socketTelemetryMap.has(socket);
81
+ }
82
+ function beginRequestContext(socket, isSecure = false) {
83
+ const startTime = Date.now();
84
+ let telemetry = getSocketTelemetry(socket);
85
+ const wasInstrumented = !!telemetry;
86
+ if (!telemetry) {
87
+ telemetry = instrumentSocket(socket, isSecure);
88
+ } else {
89
+ telemetry.reuse.count++;
90
+ telemetry.reuse.lastUsed = startTime;
91
+ telemetry.reuse.isReused = true;
92
+ }
93
+ const connectionReused = wasInstrumented || telemetry.connected;
94
+ return {
95
+ startTime,
96
+ connectionReused,
97
+ socketWait: 0,
98
+ dns: connectionReused ? 0 : telemetry.timings.dnsDuration || 0,
99
+ tcp: connectionReused ? 0 : telemetry.timings.tcpDuration || 0,
100
+ tls: connectionReused ? 0 : telemetry.timings.tlsDuration || 0,
101
+ socketTimings: { ...telemetry.timings }
102
+ };
103
+ }
104
+ function getSocketReuseStats(socket) {
105
+ const telemetry = socketTelemetryMap.get(socket);
106
+ if (!telemetry)
107
+ return;
108
+ return {
109
+ count: telemetry.reuse.count,
110
+ lifetime: Date.now() - telemetry.timings.created,
111
+ isReused: telemetry.reuse.isReused
112
+ };
113
+ }
114
+ function exportTelemetryStats() {
115
+ return {
116
+ activeSocketCount: socketIdCounter
117
+ };
118
+ }
119
+
120
+ exports.instrumentSocket = instrumentSocket;
121
+ exports.getSocketTelemetry = getSocketTelemetry;
122
+ exports.isSocketInstrumented = isSocketInstrumented;
123
+ exports.beginRequestContext = beginRequestContext;
124
+ exports.getSocketReuseStats = getSocketReuseStats;
125
+ exports.exportTelemetryStats = exportTelemetryStats;
@@ -0,0 +1,118 @@
1
+ const socketTelemetryMap = new WeakMap;
2
+ let socketIdCounter = 0;
3
+ export function instrumentSocket(socket, isSecure = false) {
4
+ const existing = socketTelemetryMap.get(socket);
5
+ if (existing) {
6
+ existing.reuse.count++;
7
+ existing.reuse.lastUsed = Date.now();
8
+ existing.reuse.isReused = true;
9
+ return existing;
10
+ }
11
+ const now = Date.now();
12
+ const telemetry = {
13
+ id: ++socketIdCounter,
14
+ timings: {
15
+ created: now
16
+ },
17
+ network: {},
18
+ reuse: {
19
+ count: 1,
20
+ lastUsed: now,
21
+ isReused: false
22
+ },
23
+ connected: false,
24
+ closed: false
25
+ };
26
+ socketTelemetryMap.set(socket, telemetry);
27
+ socket.once("lookup", (err, address, family) => {
28
+ if (!err && address) {
29
+ telemetry.timings.dnsEnd = Date.now();
30
+ telemetry.timings.dnsDuration = telemetry.timings.dnsEnd - telemetry.timings.created;
31
+ telemetry.timings.address = address;
32
+ telemetry.timings.family = typeof family === "number" ? family : family === "IPv6" ? 6 : 4;
33
+ }
34
+ });
35
+ socket.once("connect", () => {
36
+ telemetry.timings.connectEnd = Date.now();
37
+ telemetry.timings.tcpDuration = telemetry.timings.connectEnd - (telemetry.timings.dnsEnd || telemetry.timings.created);
38
+ telemetry.connected = true;
39
+ const s = socket;
40
+ telemetry.network = {
41
+ remoteAddress: s.remoteAddress,
42
+ remotePort: s.remotePort,
43
+ localAddress: s.localAddress,
44
+ localPort: s.localPort,
45
+ family: s.remoteFamily
46
+ };
47
+ });
48
+ if (isSecure) {
49
+ socket.once("secureConnect", () => {
50
+ const tlsSocket = socket;
51
+ telemetry.timings.secureConnectEnd = Date.now();
52
+ telemetry.timings.tlsDuration = telemetry.timings.secureConnectEnd - (telemetry.timings.connectEnd || telemetry.timings.created);
53
+ const cipher = tlsSocket.getCipher?.();
54
+ const cert = tlsSocket.getPeerCertificate?.();
55
+ telemetry.tls = {
56
+ protocol: tlsSocket.getProtocol?.() || undefined,
57
+ cipher: cipher?.name,
58
+ authorized: tlsSocket.authorized,
59
+ authorizationError: tlsSocket.authorizationError,
60
+ certificate: cert ? {
61
+ subject: cert.subject?.CN,
62
+ issuer: cert.issuer?.CN,
63
+ validFrom: cert.valid_from,
64
+ validTo: cert.valid_to,
65
+ fingerprint: cert.fingerprint
66
+ } : undefined
67
+ };
68
+ });
69
+ }
70
+ socket.once("close", () => {
71
+ telemetry.closed = true;
72
+ telemetry.connected = false;
73
+ });
74
+ return telemetry;
75
+ }
76
+ export function getSocketTelemetry(socket) {
77
+ return socketTelemetryMap.get(socket);
78
+ }
79
+ export function isSocketInstrumented(socket) {
80
+ return socketTelemetryMap.has(socket);
81
+ }
82
+ export function beginRequestContext(socket, isSecure = false) {
83
+ const startTime = Date.now();
84
+ let telemetry = getSocketTelemetry(socket);
85
+ const wasInstrumented = !!telemetry;
86
+ if (!telemetry) {
87
+ telemetry = instrumentSocket(socket, isSecure);
88
+ } else {
89
+ telemetry.reuse.count++;
90
+ telemetry.reuse.lastUsed = startTime;
91
+ telemetry.reuse.isReused = true;
92
+ }
93
+ const connectionReused = wasInstrumented || telemetry.connected;
94
+ return {
95
+ startTime,
96
+ connectionReused,
97
+ socketWait: 0,
98
+ dns: connectionReused ? 0 : telemetry.timings.dnsDuration || 0,
99
+ tcp: connectionReused ? 0 : telemetry.timings.tcpDuration || 0,
100
+ tls: connectionReused ? 0 : telemetry.timings.tlsDuration || 0,
101
+ socketTimings: { ...telemetry.timings }
102
+ };
103
+ }
104
+ export function getSocketReuseStats(socket) {
105
+ const telemetry = socketTelemetryMap.get(socket);
106
+ if (!telemetry)
107
+ return;
108
+ return {
109
+ count: telemetry.reuse.count,
110
+ lifetime: Date.now() - telemetry.timings.created,
111
+ isReused: telemetry.reuse.isReused
112
+ };
113
+ }
114
+ export function exportTelemetryStats() {
115
+ return {
116
+ activeSocketCount: socketIdCounter
117
+ };
118
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rezo",
3
- "version": "1.0.45",
3
+ "version": "1.0.47",
4
4
  "description": "Lightning-fast, enterprise-grade HTTP client for modern JavaScript. Full HTTP/2 support, intelligent cookie management, multiple adapters (HTTP, Fetch, cURL, XHR), streaming, proxy support (HTTP/HTTPS/SOCKS), and cross-environment compatibility.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",