30 lines
1.8 KiB
JavaScript
30 lines
1.8 KiB
JavaScript
import http from 'node:http';
|
|
import { readFile } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { readDocument } from './file-access.mjs';
|
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
const projectRoot = path.resolve(here, '../../..');
|
|
const port = Number(process.env.PORT || 4178);
|
|
const server = http.createServer(async (req,res) => {
|
|
res.setHeader('X-Content-Type-Options','nosniff');
|
|
res.setHeader('Cache-Control','no-store');
|
|
res.setHeader('Content-Security-Policy',"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self'; connect-src 'self'; frame-ancestors 'self'");
|
|
if (!['localhost:'+port,'127.0.0.1:'+port].includes(req.headers.host)) {res.writeHead(403);res.end();return;}
|
|
if (req.method !== 'GET' && req.method !== 'HEAD') {res.writeHead(405);res.end();return;}
|
|
try {
|
|
const url = new URL(req.url,'http://localhost:'+port);
|
|
let data, mime;
|
|
if (url.pathname === '/api/file') {
|
|
data = JSON.stringify(await readDocument(projectRoot, url.searchParams.get('path')));mime='application/json; charset=utf-8';
|
|
} else {
|
|
const files = {'/':['index.html','text/html; charset=utf-8'],'/app.js':['app.js','text/javascript; charset=utf-8'],'/app.css':['app.css','text/css; charset=utf-8']};
|
|
const entry = files[url.pathname];
|
|
if (!entry) {res.writeHead(404);res.end();return;}
|
|
data=await readFile(path.join(here,'dist',entry[0]));mime=entry[1];
|
|
}
|
|
res.writeHead(200,{'Content-Type':mime});res.end(req.method === 'HEAD' ? undefined : data);
|
|
} catch (error) {res.writeHead(error.status === 403 ? 403 : 404);res.end(error.status === 403 ? 'File not allowed' : 'File not found');}
|
|
});
|
|
server.listen(port,'127.0.0.1',()=>console.log('Research map: http://localhost:'+port));
|