| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- /*
- Minimal static file server for the Cine Studio E2E tests.
- Serves the ArozOS web root (src/web) so the app and its shared
- scripts (../script/*) load exactly as they do in production. The
- tests seed their own media as in-memory blobs and stub the ArozOS
- backend, so server-side AGI endpoints (/system/*, /media) are not
- needed here and simply 404 - which the app already handles.
- */
- "use strict";
- const http = require("http");
- const fs = require("fs");
- const path = require("path");
- const MIME = {
- ".html": "text/html; charset=utf-8",
- ".js": "text/javascript; charset=utf-8",
- ".css": "text/css; charset=utf-8",
- ".json": "application/json; charset=utf-8",
- ".png": "image/png",
- ".jpg": "image/jpeg",
- ".jpeg": "image/jpeg",
- ".gif": "image/gif",
- ".webp": "image/webp",
- ".svg": "image/svg+xml",
- ".ico": "image/x-icon",
- ".woff": "font/woff",
- ".woff2": "font/woff2",
- ".ttf": "font/ttf",
- ".map": "application/json; charset=utf-8"
- };
- // Create (but do not start) a server rooted at webRoot.
- function createServer(webRoot) {
- const root = path.resolve(webRoot);
- return http.createServer(function (req, res) {
- let urlPath;
- try {
- urlPath = decodeURIComponent(req.url.split("?")[0].split("#")[0]);
- } catch (e) {
- res.writeHead(400);
- res.end("bad request");
- return;
- }
- if (urlPath.endsWith("/")) { urlPath += "index.html"; }
- // Resolve within the web root, rejecting path traversal.
- const target = path.join(root, urlPath);
- if (target !== root && !target.startsWith(root + path.sep)) {
- res.writeHead(403);
- res.end("forbidden");
- return;
- }
- fs.stat(target, function (err, stat) {
- if (err || !stat.isFile()) {
- res.writeHead(404);
- res.end("not found");
- return;
- }
- res.writeHead(200, {
- "Content-Type": MIME[path.extname(target).toLowerCase()] || "application/octet-stream",
- "Cache-Control": "no-store"
- });
- fs.createReadStream(target).pipe(res);
- });
- });
- }
- // Start a server and resolve with { server, port, baseURL }.
- function start(webRoot, port) {
- return new Promise(function (resolve, reject) {
- const server = createServer(webRoot);
- server.on("error", reject);
- server.listen(port || 0, "127.0.0.1", function () {
- const actual = server.address().port;
- resolve({ server: server, port: actual, baseURL: "http://127.0.0.1:" + actual });
- });
- });
- }
- module.exports = { createServer, start };
|