/** * HTTP请求工具模块 * * 该模块基于axios创建了预配置的HTTP客户端实例,提供了优化的网络请求功能。 * 包含了连接池管理、SSL证书验证配置等网络优化设置。 * * @author drpy-node * @version 1.0.0 */ import _axios from 'axios'; import https from 'https'; import http from 'http'; import {resolveDoh, getSystemProxy} from './dns_doh.js'; import {HttpsProxyAgent} from 'https-proxy-agent'; /** * 默认的HTTP请求客户端 * * 配置特性: * - 启用HTTP/HTTPS连接池(keepAlive: true) * - 禁用HTTPS证书验证(rejectUnauthorized: false) * - 适用于大多数网络请求场景 * - 启用DOH支持 * - 自动继承系统代理 */ const req = _axios.create({ httpsAgent: new https.Agent({keepAlive: true, rejectUnauthorized: false}), // HTTPS代理配置 httpAgent: new http.Agent({keepAlive: true}), // HTTP代理配置 }); // Add System Proxy & DOH interceptor req.interceptors.request.use(async config => { if (!config.url) return config; try { // 1. Check System Proxy first const proxy = await getSystemProxy(); if (proxy) { const agent = new HttpsProxyAgent(proxy); config.httpsAgent = agent; config.proxy = false; // Disable axios internal proxy handling return config; // Return early if proxy is used (let proxy handle DNS) } // 2. DOH Logic (Only if no proxy) let fullUrl = config.url; // Handle relative URLs if baseURL is provided if (config.baseURL && !/^https?:\/\//i.test(fullUrl)) { try { const parsed = new URL(fullUrl, config.baseURL); fullUrl = parsed.toString(); } catch (e) { } } const urlObj = new URL(fullUrl); const hostname = urlObj.hostname; // Skip if not a domain or localhost if (!hostname || /^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') { return config; } const ip = await resolveDoh(hostname); if (ip && ip !== hostname) { // Keep original Host header if not set if (!config.headers) config.headers = {}; // check case-insensitive host header let hasHost = false; const keys = Object.keys(config.headers); for (const k of keys) { if (k.toLowerCase() === 'host') { hasHost = true; break; } } if (!hasHost) { config.headers.Host = hostname; } urlObj.hostname = ip; config.url = urlObj.toString(); // Clear baseURL to avoid double-prefixing if we converted to absolute if (config.baseURL) { delete config.baseURL; } } } catch (e) { // Ignore URL parse errors } return config; }); /** * 简化版HTTP请求客户端 * * 配置特性: * - 仅禁用HTTPS证书验证 * - 不启用连接池 * - 适用于简单的一次性请求 * - 启用DOH支持 * - 自动继承系统代理 */ export const reqs = new _axios.create({ httpsAgent: new https.Agent({ rejectUnauthorized: false // 禁用SSL证书验证 }) }); // Add System Proxy & DOH interceptor to reqs as well reqs.interceptors.request.use(async config => { if (!config.url) return config; try { // 1. Check System Proxy const proxy = await getSystemProxy(); if (proxy) { const agent = new HttpsProxyAgent(proxy); config.httpsAgent = agent; config.proxy = false; return config; } // 2. DOH let fullUrl = config.url; if (config.baseURL && !/^https?:\/\//i.test(fullUrl)) { try { const parsed = new URL(fullUrl, config.baseURL); fullUrl = parsed.toString(); } catch (e) { } } const urlObj = new URL(fullUrl); const hostname = urlObj.hostname; if (!hostname || /^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || hostname === 'localhost') return config; const ip = await resolveDoh(hostname); if (ip && ip !== hostname) { if (!config.headers) config.headers = {}; let hasHost = false; const keys = Object.keys(config.headers); for (const k of keys) { if (k.toLowerCase() === 'host') { hasHost = true; break; } } if (!hasHost) config.headers.Host = hostname; urlObj.hostname = ip; config.url = urlObj.toString(); if (config.baseURL) delete config.baseURL; } } catch (e) { } return config; }); // 导出默认的HTTP请求客户端 export default req;