'use strict'; const TaobaoAuth = require('./taobao-auth'); module.exports = function ({ accounts, wrinkleJobs, readBody, sendJson, handleAnalyze }) { const taobaoSessions = require('./taobao-session')({ session: accounts.taobaoSession }); return async function (req, res, pathname) { res.setHeader('Cache-Control', 'no-store'); // The cloud gateway requires its own envelope. H5 responses stay unchanged. const reply = (status, data) => sendJson(res, 200, { success: true, data: { ...data, http_status: status } }); if (req.method !== 'POST') return reply(405, { ok: false, message: '请求方法不支持' }); if (!accounts.sameOrigin(req)) return reply(403, { ok: false, message: '请求来源不匹配' }); try { const raw = (await readBody(req, pathname === '/api/taobao/photo' ? 70 * 1024 : 4096)).toString('utf8'); const body = JSON.parse(raw); if (pathname === '/api/taobao/challenge') { const challenge = taobaoSessions.challenge(req.socket.remoteAddress); return reply(challenge ? 200 : 429, challenge ? { ok: true, challenge } : { ok: false, message: '操作频繁,请稍后重试' }); } if (pathname === '/api/taobao/session') { if (body.consent !== true) return reply(400, { ok: false, message: '请先阅读并同意隐私协议' }); const identity = TaobaoAuth.verify(req.url, raw); if (!identity || !taobaoSessions.consume(body.challenge)) return reply(401, { ok: false, message: '淘宝身份校验失败,请重新授权登录' }); return reply(200, { ok: true, ...accounts.loginTaobao(identity.providerKey) }); } const owner = accounts.taobaoSession(req); if (!owner) return reply(401, { ok: false, message: '检测会话已失效,请重新登录' }); if (pathname === '/api/taobao/me') return reply(200, { ok: true, user: { id: owner.id, kind: owner.kind } }); if (pathname === '/api/taobao/photo') { const { status, ...data } = taobaoSessions.upload(req, body); return reply(status, { ok: status === 200, ...data }); } if (pathname === '/api/taobao/skin-analyze') { const photos = taobaoSessions.takePhotos(req, body.photo_refs); if (!photos) return reply(409, { ok: false, message: '照片上传未完成或检测进行中,请重试' }); // Start once and poll: cloud gateway requests have a maximum 10s timeout. const job = taobaoSessions.start(req, () => new Promise(resolve => { const response = { setHeader() {}, writeHead() {}, end(text, cb) { resolve(JSON.parse(text)); if (cb) cb(); } }; handleAnalyze(req, response, true, { ...body, ...photos }, owner).catch(() => resolve({ ok: false, message: '检测服务暂不可用,请重试' })); }), true); if (!job) { taobaoSessions.finish(req); return reply(429, { ok: false, message: '服务繁忙,请稍后再试' }); } return reply(202, { ok: true, job }); } if (pathname === '/api/taobao/analysis') { const result = taobaoSessions.result(req, body.job); return reply(result ? 200 : 404, result ? { ok: true, ...result } : { ok: false, message: '检测任务已失效,请查看历史报告或重新检测' }); } if (pathname === '/api/taobao/reports') { if (!body.id) return reply(200, { ok: true, total: accounts.reports(owner.id).length, items: accounts.reports(owner.id) }); const report = accounts.ownedReport(owner.id, body.id); return reply(report ? 200 : 404, report ? { ok: true, report } : { ok: false, message: '报告不存在' }); } if (pathname === '/api/taobao/logout') { taobaoSessions.revoke(req); accounts.taobaoLogout(req); return reply(200, { ok: true }); } if (pathname === '/api/taobao/wrinkle-views') { const job = taobaoSessions.start(req, async () => { const views = await wrinkleJobs.run(owner, body.token); return views ? { ok: true, wrinkle_views: views } : { ok: false, message: '标注任务已失效' }; }); return reply(job ? 202 : 429, job ? { ok: true, job } : { ok: false, message: '服务繁忙,请稍后再试' }); } return reply(404, { ok: false, message: '接口不存在' }); } catch (e) { const status = e.message === 'TOO_LARGE' ? 413 : e instanceof SyntaxError ? 400 : 500; return reply(status, { ok: false, message: status === 413 ? '请求数据过大' : status === 400 ? '请求数据异常' : '服务暂不可用,请稍后再试' }); } }; };