feat(rednote): add isolated persistent browser H5 entry
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
const path = require('node:path'), { spawn } = require('node:child_process');
|
||||
const root = path.resolve(__dirname, '../..'), children = [];
|
||||
for (const mode of ['state', 'rednote']) {
|
||||
children.push(spawn(process.execPath, [path.join(__dirname, 'fixture-server.cjs')], {
|
||||
env: { ...process.env, JUZI_ENTRY_MODE: mode, PORT: mode === 'state' ? '18381' : '18382',
|
||||
PUBLIC_BASE_URL: 'http://127.0.0.1:18380/' + mode + '/', JUZI_DATA_ROOT: path.join(root, 'temp/rednote-local-data', mode) },
|
||||
stdio: 'inherit'
|
||||
}));
|
||||
}
|
||||
const proxy = require('./proxy.cjs')({ statePort: 18381, rednotePort: 18382 });
|
||||
proxy.listen(18380, '127.0.0.1', () => console.log('Samples only: http://127.0.0.1:18380/rednote/ and /state/; no external API calls'));
|
||||
let closing = false;
|
||||
function stop(code = 0) {
|
||||
if (closing) return; closing = true;
|
||||
children.forEach(child => { if (child.exitCode == null) child.kill(); });
|
||||
proxy.close(() => { process.exitCode = code; });
|
||||
}
|
||||
children.forEach(child => child.on('exit', code => { if (!closing) stop(code || 1); }));
|
||||
process.on('SIGINT', () => stop()); process.on('SIGTERM', () => stop());
|
||||
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
// Local test/dev runner only. The production service launches h5/server.js directly.
|
||||
const fs = require('node:fs'), path = require('node:path'), vm = require('node:vm');
|
||||
if (!process.env.JUZI_DATA_ROOT || !process.env.PUBLIC_BASE_URL) throw Error('Explicit isolated data root and public URL required');
|
||||
Object.assign(process.env, { NODE_ENV: 'test', HOST: '127.0.0.1', SKIN_API_KEY: 'fixture', SKIN_API_SECRET: 'fixture',
|
||||
WECHAT_APP_ID: '', WECHAT_APP_SECRET: '', TAOBAO_APP_KEY: '', TAOBAO_APP_SECRET: '' });
|
||||
const root = path.resolve(__dirname, '../..'), context = { window: {} };
|
||||
vm.runInNewContext(fs.readFileSync(path.join(root, 'h5/assets/mock/report-fixture.js'), 'utf8'), context);
|
||||
const fixture = context.window.MOCK_FIXTURE;
|
||||
global.fetch = async url => {
|
||||
if (!String(url).startsWith('https://api-cn.faceplusplus.com/')) throw Error('External requests disabled in fixture mode');
|
||||
if (process.env.FIXTURE_DELAY_MS) await new Promise(resolve => setTimeout(resolve, Number(process.env.FIXTURE_DELAY_MS)));
|
||||
return { ok: true, status: 200, json: async () => ({ request_id: 'fixture', result: structuredClone(fixture.result),
|
||||
face_rectangle: fixture.face_rectangle, left_side_result: fixture.side.left, right_side_result: fixture.side.right }) };
|
||||
};
|
||||
require('../../h5/server');
|
||||
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
const http = require('node:http');
|
||||
module.exports = function proxy({ statePort, rednotePort }) {
|
||||
return http.createServer((req, res) => {
|
||||
const mode = /^\/(state|rednote)(?:\/|\?|$)/.exec(req.url)?.[1];
|
||||
if (!mode) { res.writeHead(404); return res.end('Not Found'); }
|
||||
if (req.url === '/' + mode) { res.writeHead(301, { Location: '/' + mode + '/' }); return res.end(); }
|
||||
const upstream = http.request({ host: '127.0.0.1', port: mode === 'state' ? statePort : rednotePort,
|
||||
method: req.method, path: req.url.slice(mode.length + 1) || '/',
|
||||
headers: { ...req.headers, 'x-real-ip': '127.0.0.1', 'x-forwarded-proto': 'http' } }, reply => {
|
||||
res.writeHead(reply.statusCode, reply.headers); reply.pipe(res);
|
||||
});
|
||||
upstream.setTimeout(150000, () => upstream.destroy());
|
||||
upstream.on('error', () => { if (!res.headersSent) res.writeHead(502); res.end(); });
|
||||
req.pipe(upstream);
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user