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 = ''