const axios = require('axios') const https = require('https') const path = require('path') const Logger = require('../../lib/Logger') const { getJkesSettings, normalizeApiBase } = require('./jkesSettings') const logger = new Logger(path.join(__dirname, '../../logs/JKES.log'), 'INFO') let jkesHttpsAgent function getJkesHttpsAgent() { if (!jkesHttpsAgent) { const s = getJkesSettings() jkesHttpsAgent = new https.Agent({ keepAlive: true, minVersion: 'TLSv1.2', rejectUnauthorized: s.tlsRejectUnauthorized !== false }) } return jkesHttpsAgent } function buildJkesHeaders(token) { const tokenClean = String(token ?? '').trim() const s = getJkesSettings() return { 'x-auth-token': tokenClean, 'content-type': 'application/json', 'Accept-Encoding': 'gzip,compress,br,deflate', 'User-Agent': s.userAgent, Referer: s.referer } } /** * @param {string} url 如 /sys/user/getMyInfo * @param {object} [data] POST body * @param {string} token */ async function jkesRequest(url, data, token) { const tokenClean = String(token ?? '').trim() if (!tokenClean) { logger.error('[JKES] 缺少 token') return null } const s = getJkesSettings() const pathPart = url.startsWith('/') ? url : `/${url}` const fullUrl = `${normalizeApiBase(s.apiBase)}${pathPart}` const body = data === undefined || data === null ? {} : data let parsed try { parsed = new URL(fullUrl) } catch (e) { logger.error(`[JKES] 非法 URL: ${fullUrl}`) return null } if (parsed.protocol !== 'https:') { logger.error(`[JKES] 必须使用 https: ${fullUrl}`) return null } try { logger.info(`[JKES] POST ${pathPart}`) const axiosOpts = { headers: buildJkesHeaders(tokenClean), timeout: Number(s.requestTimeoutMs) || 30000, validateStatus: () => true, httpsAgent: getJkesHttpsAgent(), beforeRedirect: (options) => { if (options.protocol !== 'https:') { logger.error(`[JKES] 拒绝跟随非 HTTPS 重定向: ${options.href}`) throw new Error('JKES 重定向目标必须为 https') } } } if (!s.useSystemProxy) { axiosOpts.proxy = false } const res = await axios.post(fullUrl, body, axiosOpts) const payload = res.data const payloadPreview = typeof payload === 'object' && payload !== null ? JSON.stringify(payload) : String(payload ?? '') if (res.status !== 200) { logger.error( `[JKES] HTTP ${res.status} ${pathPart} 响应: ${payloadPreview.slice(0, 1000)}` ) if (typeof payload === 'object' && payload !== null) { return payload } return null } return payload } catch (error) { const st = error.response?.status const dataErr = error.response?.data const errStr = typeof dataErr === 'object' && dataErr !== null ? JSON.stringify(dataErr) : String(dataErr ?? '') logger.error( `[JKES] 请求异常 ${pathPart} http=${st ?? 'n/a'} body=${errStr.slice(0, 500)} ${error.message}` ) return null } } module.exports = { jkesRequest, get BASE_URL() { return normalizeApiBase(getJkesSettings().apiBase) } }