From 896a62ec960f9d68aa5b4b4f88c99101819626bb Mon Sep 17 00:00:00 2001 From: 70CentsApple <70centsapple@gmail.com> Date: Mon, 19 Oct 2026 14:04:57 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=A9=BA=20cookie?= =?UTF-8?q?=20=E5=AF=B9=E8=B1=A1=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.js | 2 +- module/login_qr_create.js | 4 ++-- module/scrobble.js | 9 +++++++-- module/scrobble_v1.js | 5 ++++- util/index.js | 11 +++++++++++ util/option.js | 6 +++++- 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/main.js b/main.js index 6c7634b..bb5505c 100644 --- a/main.js +++ b/main.js @@ -27,7 +27,7 @@ moduleFiles.forEach((file) => { const cookie = typeof data.cookie === 'string' ? cookieToJson(data.cookie) - : data.cookie || {} + : data.cookie return fileModule( { diff --git a/module/login_qr_create.js b/module/login_qr_create.js index d94cbec..5562099 100644 --- a/module/login_qr_create.js +++ b/module/login_qr_create.js @@ -1,10 +1,10 @@ const QRCode = require('qrcode') -const { generateChainId } = require('../util/index') +const { generateChainId, hasCookie } = require('../util/index') module.exports = (query) => { return new Promise(async (resolve) => { const platform = query.platform || 'pc' - const cookie = query.cookie || '' + const cookie = hasCookie(query.cookie) ? query.cookie : '' // 构建基础URL let url = `https://music.163.com/login?codekey=${query.key}` diff --git a/module/scrobble.js b/module/scrobble.js index 7adf91e..e2ed226 100644 --- a/module/scrobble.js +++ b/module/scrobble.js @@ -1,18 +1,23 @@ // 听歌打卡 const createOption = require('../util/option.js') +const { hasCookie } = require('../util/index') const { APP_CONF } = require('../util/config.json') const DOMAIN = APP_CONF.clDomian module.exports = async (query, request) => { // 注入 os=osx 的 cookie - let cookie = query.cookie || '' + let cookie = hasCookie(query.cookie) + ? query.cookie + : process.env.NETEASE_COOKIE || '' if (typeof cookie === 'object') { cookie = Object.assign({ os: 'osx' }, cookie) } else if (typeof cookie === 'string') { if (cookie.indexOf('os=') > -1) { cookie = cookie.replace(/os=[^;]+/g, 'os=osx') - } else { + } else if (cookie) { cookie = cookie + '; os=osx' + } else { + cookie = 'os=osx' } } else { cookie = 'os=osx' diff --git a/module/scrobble_v1.js b/module/scrobble_v1.js index 84c3658..0351baa 100644 --- a/module/scrobble_v1.js +++ b/module/scrobble_v1.js @@ -13,6 +13,7 @@ const { buildMetaJson, doUpload, } = require('../util/ncbl') +const { hasCookie } = require('../util/index') module.exports = async (query, request) => { // --- 参数校验 --- @@ -32,7 +33,9 @@ module.exports = async (query, request) => { const sourceName = query.source || 'list' // --- 解析认证上下文 --- - const rawCookie = query.cookie || '' + const rawCookie = hasCookie(query.cookie) + ? query.cookie + : process.env.NETEASE_COOKIE || '' const cookieObj = parseCookie(rawCookie) cookieObj.os = 'pc' const ctx = extractContext(cookieObj) diff --git a/util/index.js b/util/index.js index e76d665..e253912 100644 --- a/util/index.js +++ b/util/index.js @@ -103,6 +103,15 @@ module.exports = { return obj }, + hasCookie(cookie) { + if (typeof cookie === 'string') return cookie.length > 0 + return ( + cookie !== null && + typeof cookie === 'object' && + Object.keys(cookie).length > 0 + ) + }, + cookieObjToString(cookie) { // 优化:使用预绑定的keys函数和for循环 const cookieKeys = keys(cookie) @@ -226,6 +235,8 @@ const cookieToJsonOptimized = (function() { function getCookieValue(cookieStr, name) { if (!cookieStr) return '' + if (typeof cookieStr === 'object') return cookieStr[name] || '' + const cookies = '; ' + cookieStr const parts = cookies.split('; ' + name + '=') if (parts.length === 2) return parts.pop().split(';').shift() diff --git a/util/option.js b/util/option.js index 9796234..e10078f 100644 --- a/util/option.js +++ b/util/option.js @@ -1,7 +1,11 @@ +const { hasCookie } = require('./index') + const createOption = (query, crypto = '', checkToken = false) => { return { crypto: query.crypto || crypto || '', - cookie: query.cookie || process.env.NETEASE_COOKIE, + cookie: hasCookie(query.cookie) + ? query.cookie + : process.env.NETEASE_COOKIE, ua: query.ua || '', proxy: query.proxy, realIP: query.realIP, From 29c48e2ef98eb0a61e91a8d0fa41f65cf7ebb97c Mon Sep 17 00:00:00 2001 From: 70CentsApple <70centsapple@gmail.com> Date: Mon, 19 Oct 2026 14:23:57 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20cookie=20?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E5=99=A8=E5=B9=B6=E4=B9=9F=E5=B0=9D=E8=AF=95?= =?UTF-8?q?=E4=BB=8E=E8=AF=B7=E6=B1=82=E5=A4=B4=E8=AF=BB=20cookie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- interface.d.ts | 1 + module/login_qr_create.js | 13 +++++++++++-- module/scrobble.js | 7 +++++-- module/scrobble_v1.js | 7 +++++-- server.js | 39 +++++++++++++++++++++++---------------- util/index.js | 28 ++++++++++++++++++++++++---- util/option.js | 8 ++++++-- util/request.js | 10 +++++++++- 8 files changed, 84 insertions(+), 29 deletions(-) diff --git a/interface.d.ts b/interface.d.ts index 28c8226..bb67d7b 100644 --- a/interface.d.ts +++ b/interface.d.ts @@ -1,5 +1,6 @@ export interface RequestBaseConfig { cookie?: string + headers?: Record realIP?: string // IPv4/IPv6 filled in X-Real-IP proxy?: string // HTTP proxy randomCNIP?: boolean // Whether to use a random Chinese IP address filled in X-Real-IP diff --git a/module/login_qr_create.js b/module/login_qr_create.js index 5562099..5678430 100644 --- a/module/login_qr_create.js +++ b/module/login_qr_create.js @@ -1,10 +1,19 @@ const QRCode = require('qrcode') -const { generateChainId, hasCookie } = require('../util/index') +const { + generateChainId, + getCookieHeader, + hasCookie, +} = require('../util/index') module.exports = (query) => { return new Promise(async (resolve) => { const platform = query.platform || 'pc' - const cookie = hasCookie(query.cookie) ? query.cookie : '' + const headerCookie = getCookieHeader(query.headers) + const cookie = hasCookie(query.cookie) + ? query.cookie + : hasCookie(headerCookie) + ? headerCookie + : '' // 构建基础URL let url = `https://music.163.com/login?codekey=${query.key}` diff --git a/module/scrobble.js b/module/scrobble.js index e2ed226..2f19ffe 100644 --- a/module/scrobble.js +++ b/module/scrobble.js @@ -1,14 +1,17 @@ // 听歌打卡 const createOption = require('../util/option.js') -const { hasCookie } = require('../util/index') +const { getCookieHeader, hasCookie } = require('../util/index') const { APP_CONF } = require('../util/config.json') const DOMAIN = APP_CONF.clDomian module.exports = async (query, request) => { // 注入 os=osx 的 cookie + const headerCookie = getCookieHeader(query.headers) let cookie = hasCookie(query.cookie) ? query.cookie - : process.env.NETEASE_COOKIE || '' + : hasCookie(headerCookie) + ? headerCookie + : process.env.NETEASE_COOKIE || '' if (typeof cookie === 'object') { cookie = Object.assign({ os: 'osx' }, cookie) } else if (typeof cookie === 'string') { diff --git a/module/scrobble_v1.js b/module/scrobble_v1.js index 0351baa..5c2f60a 100644 --- a/module/scrobble_v1.js +++ b/module/scrobble_v1.js @@ -13,7 +13,7 @@ const { buildMetaJson, doUpload, } = require('../util/ncbl') -const { hasCookie } = require('../util/index') +const { getCookieHeader, hasCookie } = require('../util/index') module.exports = async (query, request) => { // --- 参数校验 --- @@ -33,9 +33,12 @@ module.exports = async (query, request) => { const sourceName = query.source || 'list' // --- 解析认证上下文 --- + const headerCookie = getCookieHeader(query.headers) const rawCookie = hasCookie(query.cookie) ? query.cookie - : process.env.NETEASE_COOKIE || '' + : hasCookie(headerCookie) + ? headerCookie + : process.env.NETEASE_COOKIE || '' const cookieObj = parseCookie(rawCookie) cookieObj.os = 'pc' const ctx = extractContext(cookieObj) diff --git a/server.js b/server.js index 1c72cf8..7af7f6a 100644 --- a/server.js +++ b/server.js @@ -6,7 +6,7 @@ const request = require('./util/request') const packageJSON = require('./package.json') const exec = require('child_process').exec const cache = require('./util/apicache').middleware -const { cookieToJson } = require('./util/index') +const { cookieToJson, getCookieHeader, hasCookie } = require('./util/index') const fileUpload = require('express-fileupload') const decode = require('safe-decode-uri-component') const logger = require('./util/logger.js') @@ -225,14 +225,15 @@ async function constructServer(moduleDefs) { */ app.use((req, _, next) => { req.cookies = {} - //;(req.headers.cookie || '').split(/\s*;\s*/).forEach((pair) => { // Polynomial regular expression // - ;(req.headers.cookie || '').split(/;\s+|(? { - let crack = pair.indexOf('=') - if (crack < 1 || crack == pair.length - 1) return - req.cookies[decode(pair.slice(0, crack)).trim()] = decode( - pair.slice(crack + 1), - ).trim() - }) + getCookieHeader(req.headers) + .split(';') + .forEach((pair) => { + let crack = pair.indexOf('=') + if (crack < 1 || crack == pair.length - 1) return + req.cookies[decode(pair.slice(0, crack)).trim()] = decode( + pair.slice(crack + 1), + ).trim() + }) next() }) @@ -291,13 +292,19 @@ async function constructServer(moduleDefs) { } }) - let query = Object.assign( - {}, - { cookie: req.cookies }, - req.query, - req.body, - req.files, - ) + const queryCookie = req.query && req.query.cookie + const bodyCookie = req.body && req.body.cookie + const fileCookie = req.files && req.files.cookie + const cookie = hasCookie(fileCookie) + ? fileCookie + : hasCookie(bodyCookie) + ? bodyCookie + : hasCookie(queryCookie) + ? queryCookie + : req.cookies + const query = Object.assign({}, req.query, req.body, req.files, { + cookie, + }) try { let usedCrypto = '' diff --git a/util/index.js b/util/index.js index e253912..11e91cd 100644 --- a/util/index.js +++ b/util/index.js @@ -94,10 +94,12 @@ module.exports = { // 优化:使用for循环替代forEach,性能更好 for (let i = 0, len = cookieArr.length; i < len; i++) { let item = cookieArr[i] - let arr = item.split('=') - // 优化:使用严格等于 - if (arr.length === 2) { - obj[arr[0].trim()] = arr[1].trim() + let separator = item.indexOf('=') + // 只按第一个等号拆分,保留 Cookie 值中的等号 + if (separator > 0) { + obj[item.slice(0, separator).trim()] = item + .slice(separator + 1) + .trim() } } return obj @@ -112,6 +114,24 @@ module.exports = { ) }, + getCookieHeader(headers) { + if (!headers || typeof headers !== 'object') return '' + + if (typeof headers.get === 'function') { + const cookie = headers.get('cookie') + if (typeof cookie === 'string') return cookie + } + + const headerName = Object.keys(headers).find( + (name) => name.toLowerCase() === 'cookie', + ) + if (!headerName) return '' + + const cookie = headers[headerName] + if (Array.isArray(cookie)) return cookie.join('; ') + return typeof cookie === 'string' ? cookie : '' + }, + cookieObjToString(cookie) { // 优化:使用预绑定的keys函数和for循环 const cookieKeys = keys(cookie) diff --git a/util/option.js b/util/option.js index e10078f..317e40d 100644 --- a/util/option.js +++ b/util/option.js @@ -1,11 +1,15 @@ -const { hasCookie } = require('./index') +const { getCookieHeader, hasCookie } = require('./index') const createOption = (query, crypto = '', checkToken = false) => { + const headerCookie = getCookieHeader(query.headers) + return { crypto: query.crypto || crypto || '', cookie: hasCookie(query.cookie) ? query.cookie - : process.env.NETEASE_COOKIE, + : hasCookie(headerCookie) + ? headerCookie + : process.env.NETEASE_COOKIE, ua: query.ua || '', proxy: query.proxy, realIP: query.realIP, diff --git a/util/request.js b/util/request.js index a0c9020..2bfd35d 100644 --- a/util/request.js +++ b/util/request.js @@ -13,6 +13,8 @@ const tmpPath = require('os').tmpdir() const { cookieToJson, cookieObjToString, + getCookieHeader, + hasCookie, toBoolean, generateRandomChineseIP, } = require('./index') @@ -243,13 +245,19 @@ const createRequest = async (uri, data, options) => { headers['X-Forwarded-For'] = ip } - let cookie = options.cookie || {} + let cookie = hasCookie(options.cookie) + ? options.cookie + : getCookieHeader(options.headers) + if (!hasCookie(cookie)) cookie = {} if (typeof cookie === 'string') { cookie = cookieToJson(cookie) } if (typeof cookie === 'object') { cookie = processCookieObject(cookie, crypto) + Object.keys(headers).forEach((name) => { + if (name.toLowerCase() === 'cookie') delete headers[name] + }) headers['Cookie'] = cookieObjToString(cookie) } let url = '' From f1acc2fda3a06750944483e2093b8d69dc767f68 Mon Sep 17 00:00:00 2001 From: 70CentsApple <70centsapple@gmail.com> Date: Fri, 23 Oct 2026 19:40:11 +0800 Subject: [PATCH 3/3] fix: prettier --- main.js | 4 +--- module/login_qr_create.js | 6 +----- util/index.js | 4 +--- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/main.js b/main.js index bb5505c..dacceb6 100644 --- a/main.js +++ b/main.js @@ -25,9 +25,7 @@ moduleFiles.forEach((file) => { obj[fn] = function (data = {}) { const cookie = - typeof data.cookie === 'string' - ? cookieToJson(data.cookie) - : data.cookie + typeof data.cookie === 'string' ? cookieToJson(data.cookie) : data.cookie return fileModule( { diff --git a/module/login_qr_create.js b/module/login_qr_create.js index 5678430..709d5ee 100644 --- a/module/login_qr_create.js +++ b/module/login_qr_create.js @@ -1,9 +1,5 @@ const QRCode = require('qrcode') -const { - generateChainId, - getCookieHeader, - hasCookie, -} = require('../util/index') +const { generateChainId, getCookieHeader, hasCookie } = require('../util/index') module.exports = (query) => { return new Promise(async (resolve) => { diff --git a/util/index.js b/util/index.js index 11e91cd..d87dd94 100644 --- a/util/index.js +++ b/util/index.js @@ -97,9 +97,7 @@ module.exports = { let separator = item.indexOf('=') // 只按第一个等号拆分,保留 Cookie 值中的等号 if (separator > 0) { - obj[item.slice(0, separator).trim()] = item - .slice(separator + 1) - .trim() + obj[item.slice(0, separator).trim()] = item.slice(separator + 1).trim() } } return obj