37 lines
3.1 KiB
JavaScript
37 lines
3.1 KiB
JavaScript
// Loopback-only, read-only preview. Private downloaded files stay outside Git.
|
|
// H5_PRIVATE_CASE_DIR=/private/case node h5/test/private-case-preview.mjs
|
|
import http from 'node:http';import fs from 'node:fs';import path from 'node:path';
|
|
import{fileURLToPath}from'node:url';
|
|
const dir=process.env.H5_PRIVATE_CASE_DIR;
|
|
if(!dir)throw Error('Set H5_PRIVATE_CASE_DIR to the explicitly downloaded private case');
|
|
const root=fileURLToPath(new URL('../',import.meta.url));
|
|
const raw=JSON.parse(fs.readFileSync(path.join(dir,'raw.json')));
|
|
const photos=['front','left','right'].map(k=>'data:image/jpeg;base64,'+fs.readFileSync(path.join(dir,k+'.jpg')).toString('base64'));
|
|
const fixture={result:raw.result,side:{left:raw.left_side_result,right:raw.right_side_result},face_rectangle:raw.face_rectangle,photos,
|
|
realAge:Number(process.env.H5_CASE_REAL_AGE||26),skinType:process.env.H5_CASE_SKIN_TYPE||'干性肌肤'};
|
|
fixture.wrinkle_views={version:'independent-side-wrinkles-v1'};
|
|
for(const view of ['left','right']){
|
|
try{const data=JSON.parse(fs.readFileSync(path.join(dir,view+'-wrinkles.json')));fixture.wrinkle_views[view]={status:'ready',result:data.result,face_rectangle:data.face_rectangle};}catch{}
|
|
}
|
|
const mime={'.html':'text/html; charset=utf-8','.js':'application/javascript; charset=utf-8','.css':'text/css; charset=utf-8','.json':'application/json','.png':'image/png','.jpg':'image/jpeg','.svg':'image/svg+xml','.woff2':'font/woff2','.webp':'image/webp','.mp3':'audio/mpeg'};
|
|
const server=http.createServer((req,res)=>{
|
|
res.setHeader('Cache-Control','no-store');res.setHeader('X-Robots-Tag','noindex, nofollow');
|
|
if(req.method!=='GET'){res.writeHead(405);return res.end();}
|
|
let pathname;try{pathname=decodeURIComponent(new URL(req.url,'http://localhost').pathname);}catch{res.writeHead(400);return res.end();}
|
|
if(pathname==='/api/auth/session'||pathname==='/api/auth/config'){
|
|
res.setHeader('Content-Type','application/json');return res.end(JSON.stringify({ok:true,wechat:false,user:{id:'private-case-preview',kind:'browser'}}));
|
|
}
|
|
if(pathname==='/assets/mock/report-fixture.js'){
|
|
res.setHeader('Content-Type',mime['.js']);return res.end('window.MOCK_FIXTURE='+JSON.stringify(fixture)+';');
|
|
}
|
|
const file=path.resolve(root,'.'+(pathname==='/'?'/index.html':pathname));
|
|
if(!file.startsWith(root)||/^\/(data|api|test|lib)(\/|$)/.test(pathname)||pathname==='/server.js'||pathname.split('/').some(s=>s.startsWith('.'))){res.writeHead(404);return res.end();}
|
|
const type=mime[path.extname(file)];if(!type){res.writeHead(404);return res.end();}
|
|
try{
|
|
let data=fs.readFileSync(file);
|
|
if(pathname==='/js/app.js')data=data.toString().replace("realAge: +($('#f-age').value || 0) || 28",'realAge: window.MOCK_FIXTURE.realAge').replace("skinType: SKINS[skinIndex].name\n }), fx ?",'skinType: window.MOCK_FIXTURE.skinType\n }), fx ?');
|
|
res.setHeader('Content-Type',type);res.end(data);
|
|
}catch{res.writeHead(404);res.end();}
|
|
});
|
|
server.listen(Number(process.env.PORT||18125),'127.0.0.1',()=>console.log('Private case preview ready on loopback port '+server.address().port+'; GET only; no upstream calls or writes'));
|