diff --git a/env.example.js b/env.example.js index 241fc0517..dca73a827 100644 --- a/env.example.js +++ b/env.example.js @@ -7,6 +7,10 @@ module.exports = Object.freeze({ * - `CLEAR` 是否启用清理功能 * - `ENABLE_MULTIPLE_ACCOUNT` 是否启用多账号 * - `MULTIPLE_ACCOUNT_PARM` 多账号参数(JSON格式) + * ## 代理相关 + * - `ENABLE_PROXY` 启用代理 + * - `XMDL_ORDERNNO` 熊猫动态代理订单号 + * - `XMDL_SECRET` 熊猫动态代理密钥 * ## 调试相关 * - `LOTTERY_LOG_LEVEL` 输出日志等级 Error { - send({ + let ro = { url, method: 'GET', config, @@ -100,7 +101,11 @@ function get({ url, config, contents, query }) { contents, success: res => resolve(res.body), failure: err => resolve(err) - }) + } + if (hasEnv("ENABLE_PROXY")) { + ro.proxy = proxies.xiongmaodaili(); + } + send(ro) }) } @@ -111,7 +116,7 @@ function get({ url, config, contents, query }) { */ function post({ url, config, contents, query }) { return new Promise((resolve) => { - send({ + let ro = { url, method: 'POST', config, @@ -124,7 +129,11 @@ function post({ url, config, contents, query }) { contents, success: res => resolve(res.body), failure: err => resolve(err) - }) + }; + if (hasEnv("ENABLE_PROXY")) { + ro.proxy = proxies.xiongmaodaili(); + } + send(ro) }) } diff --git a/lib/net/http.js b/lib/net/http.js index fb18b2e65..37e8e4e05 100644 --- a/lib/net/http.js +++ b/lib/net/http.js @@ -20,12 +20,16 @@ * @property {boolean} [redirect] 是否重定向 * @property {number} [retry_times] 重试次数 * + * @typedef ProxyConfig + * @property {string} url https?://{IP}:{PORT} + * @property {[[string, string]]} auth_headers [[k,v],[k,v]] + * * @typedef {object} RequestOptions Http请求选项 * @property {string} [method] 请求方法 * @property {string} url 完整链接 * @property {boolean} [stream] 是否流式数据 * @property {RequestConfig} [config] 设置 - * @property {string} [proxy] HTTP代理 IP:PORT + * @property {ProxyConfig} [proxy] HTTP代理 IP:PORT * @property {Object.} [query] 查询选项 * @property {Object. | string} [contents] 内容 * @property {HttpHeaders} [headers] 请求头 @@ -34,7 +38,9 @@ */ const { request: http_request } = require('http'); +const { HttpProxyAgent } = require('http-proxy-agent'); const { request: https_request } = require('https'); +const { HttpsProxyAgent } = require('https-proxy-agent'); const { stringify } = require('querystring'); /**默认编码 */ @@ -64,7 +70,10 @@ function send(detail) { const { timeout, wait, retry, redirect, retry_times } = config; const thisURL = new URL(url) , content = formatContents(headers["content-type"], contents) - , request = (thisURL.protocol === 'https:') && !proxy ? https_request : http_request; + , request = (thisURL.protocol === 'https:') ? https_request : http_request; + /** + * @type {import("https").RequestOptions} + */ let options = { timeout, method: method.toUpperCase(), @@ -80,9 +89,13 @@ function send(detail) { options.headers['content-length'] = Buffer.byteLength(content, 'utf-8').toString(); } if (proxy) { - options.headers.host = thisURL.host; - options.path = thisURL.href; - [options.host, options.port] = proxy.split(':'); + options.agent = (thisURL.protocol === 'https:') + ? new HttpsProxyAgent(proxy.url) + : new HttpProxyAgent(proxy.url); + for (const ah of proxy.auth_headers) { + options.headers[ah[0]] = ah[1] + } + options.rejectUnauthorized = false } const req = request(options, res => { let protodata = ''; diff --git a/package.json b/package.json index 0c3db4370..30dd4d5f5 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,8 @@ }, "dependencies": { "chalk": "^4.1.2", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", "nodemailer": "^6.7.0" } } diff --git a/test/api.test.js b/test/api.test.js index 82e9e8997..6563c239b 100644 --- a/test/api.test.js +++ b/test/api.test.js @@ -6,7 +6,7 @@ const { parseDynamicCard } = require('../lib/core/searcher'); (async () => { assert(await bili_client.getMyinfo()); - await util.par_run([0, 1, 2, 3, 4, 6], [ + await util.par_run([0, 1, 2, 3, 4, 5], [ // 0 async () => { assert.equal((await bili_client.getTopRcmd()).length, 10) diff --git a/test/index.js b/test/index.js index 19d20edf9..0ba591d94 100644 --- a/test/index.js +++ b/test/index.js @@ -7,6 +7,7 @@ log._level = 2 env.init() global_var.init(process.env["COOKIE"], 1) + fs.readdirSync(module.path) .filter(file => file.endsWith(".test.js")) .forEach(file => require(`${module.path}/${file}`)) \ No newline at end of file diff --git a/test/proxy.test.js b/test/proxy.test.js new file mode 100644 index 000000000..fd0ef2575 --- /dev/null +++ b/test/proxy.test.js @@ -0,0 +1,38 @@ +const util = require('./util'); +const crypto = require('crypto'); +const { send } = require('../lib/net/http'); + +(async () => { + await util.par_run([], [ + // 0 + async () => { + let timestamp = parseInt(new Date().getTime() / 1000); + let orderno = process.env["XMDL_ORDERNNO"]; + let secret = process.env["XMDL_SECRET"]; + + if (orderno && secret) { + let txt = 'orderno=' + orderno + ',secret=' + secret + ',timestamp=' + timestamp; + let md5 = crypto.createHash('md5'); + let sign = md5.update(txt).digest('hex').toUpperCase(); + + console.log(await new Promise((resolve) => { + send({ + url: "https://api.bilibili.com/client_info", + proxy: { + url: "http://dtan.xiongmaodaili.com:8088", + auth_headers: [ + ["Proxy-Authorization", 'sign=' + sign + '&orderno=' + orderno + "×tamp=" + timestamp] + ] + }, + config: { + retry: false + }, + success: (res) => { resolve(JSON.parse(res.body)) }, + failure: resolve + }) + })); + console.log("proxy.test ... ok!"); + } + }, + ]) +})() \ No newline at end of file