// 单元测试:thought_lab 路由鉴权行为 // 运行:node dev_test_scripts/unit/test_thought_lab_api.js // 断言: // 1) GET /api/thought_lab/labs 无 cookie -> 200 且返回 5 个 lab(白名单公开元数据) // 2) lab 页面:无 cookie 无 Referer(直链/外站) -> 401 // 3) lab 页面:无 cookie 但同源 Referer(首页导航进入) -> 200 // 4) lab 页面:带 nav_gate -> 200 const http = require('http') const path = require('path') const express = require(path.join(process.cwd(), 'node_modules', 'express')) const thoughtLab = require(path.join(process.cwd(), 'src', 'server', 'thought_lab')) const app = express() thoughtLab.bindRoutes(app) const server = app.listen(0, async () => { const port = server.address().port const get = (p, headers) => new Promise((resolve, reject) => { const req = http.get({ host: '127.0.0.1', port, path: p, headers: headers || {} }, res => { let body = '' res.on('data', c => { body += c }) res.on('end', () => resolve({ status: res.statusCode, body })) }) req.on('error', reject) }) let fail = 0 const check = (name, cond, extra) => { console.log(`${cond ? 'PASS' : 'FAIL'} - ${name}${extra ? ' | ' + extra : ''}`) if (!cond) fail++ } try { const r1 = await get('/api/thought_lab/labs') let labs = [] try { labs = JSON.parse(r1.body).labs || [] } catch {} check('labs 列表无 cookie 应 200', r1.status === 200, `status=${r1.status}`) check('labs 列表应包含 5 个 lab', labs.length === 5, `count=${labs.length}`) const page = '/tools/thought_lab/labs/blackhole_sim/index.html' const host = `127.0.0.1:${port}` const r2 = await get(page) check('lab 页面直链(无 cookie 无 Referer)应 401', r2.status === 401, `status=${r2.status}`) const r3 = await get(page, { referer: `http://${host}/`, host }) check('lab 页面同源 Referer(导航进入)应 200', r3.status === 200, `status=${r3.status}`) const r4 = await get(page, { cookie: 'nav_gate=1', host }) check('lab 页面带 nav_gate 应 200', r4.status === 200, `status=${r4.status}`) const r5 = await get(page, { referer: 'https://evil.example.com/', host }) check('lab 页面外站 Referer 应 401', r5.status === 401, `status=${r5.status}`) } catch (e) { fail++ console.log('FAIL - 请求异常 |', e.message) } server.close() console.log(fail === 0 ? 'ALL PASS' : `${fail} FAILED`) process.exit(fail === 0 ? 0 : 1) })