curl-cffi
Version:
A powerful HTTP client for Node.js based on libcurl with browser fingerprinting capabilities.
935 lines (913 loc) • 25.6 kB
JavaScript
// node_modules/.pnpm/tsup@8.5.0_typescript@5.8.3/node_modules/tsup/assets/esm_shims.js
import path from "path";
import { fileURLToPath } from "url";
var getFilename = () => fileURLToPath(import.meta.url);
var getDirname = () => path.dirname(getFilename());
var __dirname = /* @__PURE__ */ getDirname();
// src/index.ts
import { getLibPath as getLibPathBase, getVersion } from "@tocha688/libcurl";
import { CurlMOpt as CurlMOpt2, CurlHttpVersion as CurlHttpVersion2, CurlOpt as CurlOpt2, CurlError, CurlInfo as CurlInfo3, CurlIpResolve, CurlSslVersion as CurlSslVersion2, CurlWsFlag, Curl as Curl5 } from "@tocha688/libcurl";
// src/type/header.ts
var HttpHeaders = class _HttpHeaders {
constructor(headers) {
this.headers = /* @__PURE__ */ new Map();
// 需要保持小写的特殊请求头
this.lowercaseHeaders = /* @__PURE__ */ new Set([
"sec-ch-ua",
"sec-ch-ua-mobile",
"sec-ch-ua-platform",
"sec-fetch-site",
"sec-fetch-mode",
"sec-fetch-dest",
"sec-fetch-user"
]);
if (!headers) return;
if (headers instanceof _HttpHeaders) {
this.headers = new Map(headers.headers);
return;
}
if (typeof headers === "string") {
headers.split("\r\n").forEach((header) => {
const colonIndex = header.indexOf(":");
if (colonIndex > 0) {
const key = header.substring(0, colonIndex);
const value = header.substring(colonIndex + 1).trim();
this.set(key, value);
}
});
return;
}
Object.entries(headers).forEach(([key, value]) => {
this.set(key, value);
});
}
get status() {
const num = this.head?.match(/(?<=HTTP\/[\d\.]+\s+)(\d+)/);
return num ? parseInt(num[0]) : 0;
}
// 将请求头转换为合适的格式
normalizeKey(key) {
const lowerKey = key.toLowerCase();
if (this.lowercaseHeaders.has(lowerKey)) {
return lowerKey;
}
return lowerKey.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("-");
}
set(key, value) {
const normalizedKey = this.normalizeKey(key);
if (value instanceof Array) {
return this.headers.set(normalizedKey, value);
}
const arr = this.get(key) || [];
arr.push(value);
this.headers.set(normalizedKey, arr);
}
get(key) {
const normalizedKey = this.normalizeKey(key);
return this.headers.get(normalizedKey) || null;
}
first(key) {
return this.get(key)?.[0];
}
delete(key) {
const normalizedKey = this.normalizeKey(key);
this.headers.delete(normalizedKey);
}
has(key) {
const normalizedKey = this.normalizeKey(key);
return this.headers.has(normalizedKey);
}
all() {
return Object.fromEntries(this.headers);
}
toObject() {
const obj = {};
this.headers.forEach((values, key) => {
obj[key] = values[0];
});
return obj;
}
toArray() {
const arr = [];
this.headers.forEach((values, key) => {
arr.push(`${key}: ${values[0]}`);
});
return arr;
}
toString() {
return Array.from(this.headers.entries()).map(([key, values]) => values.map((value) => `${key}: ${value}`).join("\r\n")).flat().join("\r\n");
}
clone() {
const newHeaders = new _HttpHeaders();
this.headers.forEach((values, key) => {
newHeaders.headers.set(key, [...values]);
});
return newHeaders;
}
};
// src/type/response.ts
var CurlResponse = class {
constructor(opts) {
this.stacks = [];
this.index = 0;
this.redirects = 0;
this.url = opts.url ?? opts.request?.url ?? "";
this.request = opts.request;
this.status = opts.headers.status;
this.dataRaw = opts.dataRaw;
this.headers = opts.headers;
this.stacks = opts.stacks || [];
this.options = opts.options;
this.index = opts.index ?? 0;
this.curl = opts.curl;
}
get text() {
return this.dataRaw?.toString("utf-8");
}
get data() {
if (!this.text) return;
try {
return JSON.parse(this.text);
} catch (e) {
return this.text;
}
}
get jar() {
return this.request.jar;
}
};
// src/type/index.ts
var defaultRequestOption = {
method: "GET",
timeout: 3e4,
allowRedirects: true,
maxRedirects: 5,
verify: true,
acceptEncoding: "gzip, deflate, br, zstd",
// impersonate: "chrome136",
// maxRecvSpeed: 0,
ipType: "auto",
defaultHeaders: true,
maxRecvSpeed: 0
};
// src/request/request.ts
import { Curl as Curl3 } from "@tocha688/libcurl";
// src/impl/index.ts
import { setLibPath } from "@tocha688/libcurl";
// src/app.ts
import path2 from "path";
import os from "os";
import fs from "fs";
var libsPath = path2.join(__dirname, "..", "libs");
var certPath = path2.join(libsPath, "cacert.pem");
function getDirName() {
const archMap = {
"x64": "x86_64",
"arm64": os.platform() == "linux" ? "aarch64" : "arm64",
"arm": "arm-linux-gnueabihf",
"riscv64": "riscv64",
"i386": "i386",
"ia32": "i686"
};
const platformMap = {
"linux": "linux-gnu",
"darwin": "macos",
"win32": "win32"
};
const arch = archMap[os.arch()] || os.arch();
const platform = platformMap[os.platform()] || os.platform();
return `${arch}-${platform}`;
}
function getLibPath() {
const name = getDirName();
const libs = {
"win32": ["bin/libcurl.dll"],
"darwin": ["libcurl-impersonate.4.dylib", "libcurl-impersonate.dylib"],
"linux": ["libcurl-impersonate.so"]
};
for (let lib of libs[os.platform()] || []) {
const libpath = path2.join(libsPath, name, lib);
if (fs.existsSync(libpath)) {
return libpath;
}
}
console.error(`Expected path: ${path2.join(libsPath, name)}`);
throw new Error(`libcurl not found for platform ${os.platform()} and arch ${os.arch()}`);
}
// src/impl/curl_multi_timer.ts
import { CurlMulti, CurlInfo as CurlInfo2 } from "@tocha688/libcurl";
// src/helper.ts
import { CurlOpt } from "@tocha688/libcurl";
// src/utils.ts
import qs from "querystring";
import { Cookie } from "tough-cookie";
import { CurlHttpVersion } from "@tocha688/libcurl";
function buildUrl(baseUrl, params) {
if (!params) return baseUrl;
const url = new URL(baseUrl);
qs.stringify(params).split("&").forEach((param) => {
const [key, value] = param.split("=");
url.searchParams.set(key, value);
});
return url.toString();
}
function parseResponseHeaders(str) {
const headers = [];
let ch = new HttpHeaders();
for (const line of str.split("\r\n")) {
if (!line) continue;
if (line.startsWith("HTTP/")) {
ch = new HttpHeaders();
ch.head = line.trim();
headers.push(ch);
continue;
}
if (line.includes(":")) {
const [key, ...vals] = line.split(":");
ch.set(key, vals.join(":").trim());
}
}
return headers;
}
function normalize_http_version(version) {
if (typeof version === "number") {
return version;
} else if (version === "v1") {
return CurlHttpVersion.V1_1;
} else if (version === "v2") {
return CurlHttpVersion.V2_0;
} else if (version === "v3") {
return CurlHttpVersion.V3;
} else if (version === "v3only") {
return CurlHttpVersion.V3Only;
} else if (version === "v2tls") {
return CurlHttpVersion.V2Tls;
} else if (version === "v2_prior_knowledge") {
return CurlHttpVersion.V2PriorKnowledge;
}
return version;
}
// src/helper.ts
import _ from "lodash";
function setRequestOptions(curl, opts, isCors = false) {
opts = { ...defaultRequestOption, ...opts };
const currentUrl = buildUrl(opts.url, opts.params);
const method = opts.method?.toLocaleUpperCase() || "GET";
if (method == "POST") {
curl.setOption(CurlOpt.Post, 1);
} else if (method !== "GET") {
curl.setOption(CurlOpt.CustomRequest, method);
}
if (method == "HEAD") {
curl.setOption(CurlOpt.Nobody, 1);
}
curl.setOption(CurlOpt.Url, currentUrl);
let body = opts.data;
const headers = new HttpHeaders(opts.headers);
let contentType = headers.first("Content-Type");
if (opts.data && typeof opts.data === "object") {
if (opts.data instanceof URLSearchParams) {
body = opts.data.toString();
if (contentType) {
contentType = "application/x-www-form-urlencoded";
}
} else if (Buffer.isBuffer(opts.data)) {
body = opts.data;
if (contentType) {
contentType = "application/octet-stream";
}
} else {
body = JSON.stringify(opts.data);
if (contentType) {
contentType = "application/json";
}
}
} else if (typeof opts.data === "string") {
body = opts.data;
} else {
body = "";
}
if (body || ["POST", "PUT", "PATCH"].includes(method)) {
curl.setBody(body);
if (method == "GET") {
curl.setOption(CurlOpt.CustomRequest, method);
}
}
if (contentType) {
headers.set("Content-Type", contentType);
}
headers.delete("Expect");
curl.setHeadersRaw(headers.toArray());
curl.setOption(CurlOpt.CookieFile, "");
curl.setOption(CurlOpt.CookieList, "ALL");
const cookieHeader = headers.first("cookie");
if (cookieHeader || opts.jar) {
const cookies = /* @__PURE__ */ new Map();
if (cookieHeader) {
if (cookieHeader) {
cookieHeader.split(";").forEach((cookie) => {
if (!cookie?.trim()) return;
const [key, value] = cookie.split("=");
cookies.set(key.trim(), (value ?? "").trim());
});
}
}
if (opts.jar) {
const cookieJar = opts.jar;
const jarCookies = cookieJar.getCookiesSync(currentUrl);
if (jarCookies.length > 0) {
jarCookies.forEach((cookie) => {
cookies.set(cookie.key, cookie.value);
});
}
}
if (cookies.size > 0) {
const cookieStr = Array.from(cookies.entries()).map(([key, value]) => `${key}=${value}`).join("; ");
curl.setCookies(cookieStr);
}
}
if (opts.auth) {
const { username, password } = opts.auth;
curl.setOption(CurlOpt.Username, username);
curl.setOption(CurlOpt.Password, password);
}
opts.timeout = opts.timeout ?? 0;
if (opts.timeout && opts.timeout > 0) {
curl.setOption(CurlOpt.TimeoutMs, opts.timeout);
}
curl.setOption(CurlOpt.FollowLocation, opts.allowRedirects ?? true);
curl.setOption(CurlOpt.MaxRedirs, opts.maxRedirects ?? 30);
if (opts.proxy) {
const proxy = new URL(opts.proxy);
curl.setOption(CurlOpt.Proxy, proxy.protocol + "//" + proxy.host);
if (!proxy.protocol.startsWith("socks")) {
curl.setOption(CurlOpt.HttpProxyTunnel, true);
}
if (proxy.username && proxy.password) {
curl.setOption(CurlOpt.ProxyUsername, proxy.username);
curl.setOption(CurlOpt.ProxyPassword, proxy.password);
}
}
if (opts.verify === false) {
curl.setOption(CurlOpt.SslVerifyPeer, 0);
curl.setOption(CurlOpt.SslVerifyHost, 0);
} else {
curl.setOption(CurlOpt.SslVerifyPeer, 1);
curl.setOption(CurlOpt.SslVerifyHost, 2);
curl.setOption(CurlOpt.CaInfo, certPath);
curl.setOption(CurlOpt.ProxyCaInfo, certPath);
}
if (opts.impersonate) {
curl.impersonate(opts.impersonate, opts.defaultHeaders ?? true);
}
if (opts.referer) {
curl.setOption(CurlOpt.Referer, opts.referer);
}
if (opts.acceptEncoding) {
curl.setOption(CurlOpt.AcceptEncoding, opts.acceptEncoding);
}
if (typeof opts.cert === "string") {
curl.setOption(CurlOpt.SslCert, opts.cert);
} else if (!!opts.cert) {
!!opts.cert?.cert && curl.setOption(CurlOpt.SslCert, opts.cert.cert);
!!opts.cert?.key && curl.setOption(CurlOpt.SslKey, opts.cert.key);
}
if (!opts.impersonate && !opts.httpVersion) {
curl.setOption(CurlOpt.HttpVersion, normalize_http_version("v2"));
} else if (!opts.impersonate && opts.httpVersion) {
curl.setOption(CurlOpt.HttpVersion, normalize_http_version(opts.httpVersion));
}
if (opts.interface) {
curl.setOption(CurlOpt.Interface, opts.interface);
}
if (opts.ipType) {
switch (opts.ipType) {
case "ipv4":
curl.setOption(CurlOpt.IpResolve, 1);
break;
case "ipv6":
curl.setOption(CurlOpt.IpResolve, 2);
break;
case "auto":
curl.setOption(CurlOpt.IpResolve, 0);
break;
}
}
if (opts.keepAlive === false && isCors === false) {
curl.setOption(CurlOpt.TcpKeepAlive, 0);
curl.setOption(CurlOpt.FreshConnect, 1);
}
if (opts.dev) {
curl.setOption(CurlOpt.Verbose, 1);
}
curl.setOption(CurlOpt.MaxRecvSpeedLarge, opts.maxRecvSpeed ?? 0);
if (opts.curlOptions) {
if (!!opts?.curlOptions) {
for (const [key, value] of Object.entries(opts.curlOptions)) {
let ekey = key;
if (typeof value === "string") {
curl.setOption(ekey, value);
} else if (typeof value === "number") {
curl.setOption(ekey, value);
} else if (typeof value === "boolean") {
curl.setOption(ekey, value);
}
}
}
}
}
function parseResponse(curl, req2) {
const dataRaw = curl.getRespBody();
const headerRaw = curl.getRespHeaders().toString("utf-8");
const stacks = [];
const hds = parseResponseHeaders(headerRaw);
const jar = req2.jar;
let nextReq = _.clone(req2);
hds.forEach((header, i) => {
const treq = _.clone(nextReq);
const res = new CurlResponse({
url: treq.url,
headers: header,
request: treq,
options: req2,
stacks,
index: stacks.length,
curl
});
res.redirects = Math.max(0, stacks.length - 1);
treq.response = res;
let loction = res.headers.first("location");
if (loction) {
nextReq.url = new URL(loction, treq.url).toString();
nextReq.method = "GET";
nextReq.data = void 0;
} else {
res.dataRaw = dataRaw;
}
if (jar) {
res.headers.get("set-cookie")?.forEach((cookie) => {
jar.setCookieSync(cookie, treq.url);
});
}
stacks.push(treq);
});
return stacks[Math.max(stacks.length - 1, 0)].response;
}
// src/logger.ts
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
LogLevel2[LogLevel2["none"] = 0] = "none";
LogLevel2[LogLevel2["error"] = 1] = "error";
LogLevel2[LogLevel2["info"] = 2] = "info";
LogLevel2[LogLevel2["warn"] = 3] = "warn";
LogLevel2[LogLevel2["debug"] = 4] = "debug";
return LogLevel2;
})(LogLevel || {});
var Logger = class {
constructor() {
}
static time() {
return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").replace("Z", "");
}
static info(...args) {
if (this.level >= 2 /* info */) {
console.log(this.time(), ...args);
}
}
static debug(...args) {
if (this.level >= 4 /* debug */) {
console.log(this.time(), ...args);
}
}
static warn(...args) {
if (this.level >= 3 /* warn */) {
console.warn(this.time(), ...args);
}
}
static error(...args) {
if (this.level >= 1 /* error */) {
console.log(this.time(), ...args);
}
}
};
Logger.level = 2 /* info */;
// src/impl/curl_multi_timer.ts
var CURLMSG_DONE = 1;
var CurlMultiTimer = class extends CurlMulti {
constructor() {
super();
this.forceTimeoutTimer = null;
this.timers = [];
this.curls = /* @__PURE__ */ new Map();
this.sockfds = /* @__PURE__ */ new Set();
this.isCecker = false;
this.setupCallbacks();
this.startForceTimeout();
}
startForceTimeout() {
const forceTimeout = () => {
if (this.closed) return;
if (this.curls.size > 0) {
this.processData();
}
};
this.forceTimeoutTimer = setInterval(forceTimeout, 10);
this.forceTimeoutTimer.unref();
}
/**
* 设置回调函数
*/
setupCallbacks() {
Logger.debug("setupCallbacks - setTimerCallback");
this.setTimerCallback((err, { timeoutMs }) => {
if (err) {
Logger.error(err);
return;
}
if (timeoutMs == -1) {
this.timers.forEach((timer) => clearTimeout(timer));
this.timers = [];
} else {
this.timers.push(setTimeout(() => {
Logger.debug("CurlMultiTimer - setTimerCallback - timeout", timeoutMs);
this.processData();
}, timeoutMs));
}
});
}
processData() {
if (this.closed) return;
try {
Logger.debug("CurlMultiTimer - perform - start");
const runSize = this.perform();
Logger.debug("CurlMultiTimer - perform - end", runSize);
this.curls.size > 0 && this.checkProcess();
} catch (error) {
Logger.error("CurlMultiTimer - error", error);
}
}
checkProcess() {
if (this.isCecker) return;
try {
while (true) {
Logger.debug(`CurlMultiTimer - checkProcess - infoRead start`);
const msg = this.infoRead();
Logger.debug(`CurlMultiTimer - checkProcess - infoRead end`);
if (!msg) {
break;
}
if (msg.msg === CURLMSG_DONE) {
const call = this.curls.get(msg.easyId);
if (!call || !msg.data) continue;
this.curls.delete(msg.easyId);
this.removeHandle(call.curl);
if (msg.data.result == 0) {
Logger.debug(`CurlMultiTimer - getInfoNumber - start`, msg.easyId);
const status = call.curl.getInfoNumber(CurlInfo2.ResponseCode) || 200;
Logger.debug(`CurlMultiTimer - getInfoNumber - end`, msg.easyId);
if (status < 100) {
call.reject(new Error(call.curl.error(status)));
} else {
call.resolve(parseResponse(call.curl, call.options));
}
} else {
call.reject(new Error(call.curl.error(msg.data.result)));
}
Logger.debug(`CurlMultiTimer - checkProcess - DONE`);
Logger.debug(`CurlMultiTimer - checkProcess - DONE OK`);
} else {
Logger.warn(`CurlMultiTimer - checkProcess - NOT DONE`, msg);
}
}
} catch (e) {
Logger.error("\u5904\u7406\u5B8C\u6210\u6D88\u606F\u65F6\u51FA\u9519", e);
} finally {
this.isCecker = false;
}
}
async request(ops, curl) {
return new Promise((resolve, reject) => {
this.curls.set(curl.id(), {
options: ops,
curl,
resolve,
reject
});
Logger.debug(`CurlMultiTimer - request - addHandle start`);
this.addHandle(curl);
Logger.debug(`CurlMultiTimer - request - addHandle end`);
setImmediate(() => {
if (!this.closed) {
this.processData();
}
});
});
}
close() {
if (this.closed) return;
Logger.debug(`CurlMultiTimer - close start`);
if (this.forceTimeoutTimer) {
clearInterval(this.forceTimeoutTimer);
this.forceTimeoutTimer = null;
}
super.close();
this.sockfds.clear();
this.timers.forEach((timer) => clearTimeout(timer));
this.timers = [];
this.curls.forEach((call) => {
call.reject(new Error("CurlPools is closed"));
});
this.curls.clear();
}
};
// src/impl/request_sync.ts
function requestSync(options, curl) {
try {
curl.performSync();
return parseResponse(curl, options);
} finally {
}
}
async function request(options, curl) {
try {
await curl.perform();
return parseResponse(curl, options);
} finally {
}
}
// src/impl/index.ts
var CurlMultiImpl = class extends CurlMultiTimer {
};
function curlGlobalInit() {
setLibPath(getLibPath());
}
// src/request/request.ts
async function fetch(url, options = {}) {
options.url = url;
options.data = options.body;
let curl = new Curl3();
setRequestOptions(curl, options);
if (options.sync) {
return await requestSync(options, curl);
}
return await request(options, curl);
}
// src/request/session.ts
import { CookieJar as CookieJar2 } from "tough-cookie";
// src/request/client.ts
import { Curl as Curl4, CurlMOpt } from "@tocha688/libcurl";
import _2 from "lodash";
var CurlRequestImplBase = class {
constructor(baseOptions = _2.clone(defaultRequestOption)) {
this.baseOptions = baseOptions;
this.init();
}
init() {
}
request(options) {
throw new Error("Method not implemented.");
}
async beforeRequest(options) {
return this.request(options);
}
get(url, options) {
return this.beforeRequest({
url,
method: "GET",
...options
});
}
post(url, data, options) {
return this.beforeRequest({
url,
method: "POST",
data,
...options
});
}
put(url, data, options) {
return this.beforeRequest({
url,
method: "PUT",
data,
...options
});
}
delete(url, data, options) {
return this.beforeRequest({
url,
method: "DELETE",
data,
...options
});
}
patch(url, data, options) {
return this.beforeRequest({
url,
method: "PATCH",
data,
...options
});
}
head(url, options) {
return this.beforeRequest({
url,
method: "HEAD",
...options
});
}
options(url, options) {
return this.beforeRequest({
url,
method: "OPTIONS",
...options
});
}
get jar() {
return this.baseOptions.jar;
}
};
var CurlClient = class extends CurlRequestImplBase {
constructor(ops) {
super(ops);
this.reqs = [];
this.resps = [];
ops = _2.merge({}, defaultRequestOption, ops);
this.multi = ops?.impl;
this.initOptions(ops);
}
async emits(options, calls) {
for (const call of calls) {
options = await call(options);
}
return options;
}
onRequest(event) {
if (this.reqs.indexOf(event) === -1) {
this.reqs.push(event);
}
}
onResponse(event) {
if (this.resps.indexOf(event) === -1) {
this.resps.push(event);
}
}
initOptions(ops) {
if (!ops) return;
if (!this.multi) return;
if (ops.keepAlive == false) {
this.multi.setOption(CurlMOpt.Pipelining, 1);
} else {
this.multi.setOption(CurlMOpt.Pipelining, 2);
}
this.multi.setOption(CurlMOpt.Pipelining, 2);
this.multi.setOption(CurlMOpt.MaxConnects, ops.MaxConnects ?? 10);
this.multi.setOption(CurlMOpt.MaxConcurrentStreams, ops.MaxConcurrentStreams ?? 500);
}
async send(options, curl) {
if (this.multi) {
return await this.multi.request(options, curl);
} else if (options.sync) {
return await requestSync(options, curl);
} else {
return await request(options, curl);
}
}
getCurl() {
return new Curl4();
}
async beforeResponse(options, curl, res) {
curl.close();
return res;
}
async request(options) {
let curl = this.getCurl();
const opts = _2.merge({}, this.baseOptions, options);
if (opts.cors) {
const corsOpts = _2.merge({}, opts, {
method: "OPTIONS",
data: null,
body: null,
headers: {
"Content-Type": null
}
});
await setRequestOptions(curl, corsOpts);
await this.send(corsOpts, curl);
}
let retryCount = opts?.retryCount ?? 0;
let result;
do {
try {
curl.reset();
await setRequestOptions(curl, opts);
await this.emits(opts, this.reqs);
result = await this.send(opts, curl);
break;
} catch (e) {
if (retryCount <= 0) {
throw e;
}
console.warn(`Request failed, retrying... (${retryCount} retries left)`, e);
}
} while (retryCount-- > 0);
await this.emits(result, this.resps);
return this.beforeResponse(opts, curl, result);
}
close() {
this.multi?.close();
}
setImpl(impl) {
this.multi = impl;
}
getImpl() {
return this.multi;
}
};
// src/request/session.ts
var CurlSession = class extends CurlClient {
constructor(ops) {
super({
...ops,
jar: ops?.jar ?? new CookieJar2()
});
this.curls = [];
this.startCheckCurlClose();
storageCurls.add(this);
}
startCheckCurlClose() {
this.curlCheckTimer = setInterval(() => {
const now = Date.now();
this.curls = this.curls.filter((info) => {
if (now - info.lastTime > 60 * 1e3) {
info.curl.close();
return false;
}
return true;
});
}, 60 * 1e3);
this.curlCheckTimer.unref();
}
getCurl() {
let info = this.curls.shift();
if (info) {
info.curl.reset();
}
return info?.curl ?? new Curl5();
}
close() {
this.curls.forEach((info) => info.curl.close());
this.curls = [];
this.curlCheckTimer && clearInterval(this.curlCheckTimer);
this.curlCheckTimer = void 0;
super.close();
storageCurls.delete(this);
}
async beforeResponse(options, curl, res) {
this.curls.push({
curl,
lastTime: Date.now()
});
return res;
}
};
// src/request/global.ts
import { globalCleanup } from "@tocha688/libcurl";
curlGlobalInit();
var storageCurls = global.__Tocha_CurlStorage = global.__Tocha_CurlStorage ?? /* @__PURE__ */ new Set();
var req = new CurlClient();
storageCurls.add(req);
var cleanup = () => {
console.log("Cleaning up...");
storageCurls.forEach((item) => {
item.close();
});
globalCleanup();
};
process.on("exit", cleanup);
// src/index.ts
var libVersion = () => getVersion();
var libPath = () => getLibPathBase();
export {
Curl5 as Curl,
CurlClient,
CurlError,
CurlHttpVersion2 as CurlHttpVersion,
CurlInfo3 as CurlInfo,
CurlIpResolve,
CurlMOpt2 as CurlMOpt,
CurlMultiImpl,
CurlOpt2 as CurlOpt,
CurlResponse,
CurlSession,
CurlSslVersion2 as CurlSslVersion,
CurlWsFlag,
HttpHeaders,
LogLevel,
Logger,
defaultRequestOption,
fetch,
libPath,
libVersion,
req,
storageCurls
};