const { v4: uuid } = require("uuid"); var serve = require("koa-static"); const Koa = require("koa"); const Router = require("@koa/router"); const mount = require("koa-mount"); const qs = require("qs"); const { Readable } = require("stream"); const { spawn } = require("child_process"); const router = new Router(); // response const app = new Koa(); const static = new Koa(); static.use(serve("./static")); app.use(mount("/static", static)); function attach(docker_id, output_stream) { // to prevent browser timeout const interval = setInterval(() => output_stream.push(""), 500); const task = spawn("docker", ["logs", "-f", docker_id]); task.stdout.on("data", (d) => output_stream.push(d)); task.stdout.on("error", (d) => output_stream.push(d)); task.on("close", () => { const check = spawn("docker", ["ps", "--filter", `id=${docker_id}`]); let output = ""; check.on("data", (data) => (output += data)); check.on("close", () => { console.log("CHECK", output); clearInterval(interval); }); check.on("error", (error) => { console.error("error", error); clearInterval(interval); }); check.on("exit", (error) => { console.error("exit", error); clearInterval(interval); }); }); } router.get("/", async (ctx) => { const s = new Readable({ read() {} }); // stream data ctx.response.set("content-type", "txt/html"); ctx.type = "html"; // <-- THIS is the important step! ctx.body = s; ctx.body.push(""); const params = qs.parse(ctx.querystring); s.push(`Got request to screenshot ${params.url}
`); const id = uuid(); let docker_id = ""; const starter = spawn( "docker", [ "run", "-i", "-d", "-v", `${process.cwd()}/static:/opt/static`, "headless-fox", "./script3.sh", '{"url": "pearson.pl", "third_party_domains": ["hotjar.com", "cookielaw.org"]}', id, ], { cwd: process.cwd() } ); starter.stdout.on("data", (data) => { docker_id += data.toString().replace(/\n/g, ""); }); starter.on("close", () => { ctx.body.push("spawned " + docker_id); attach(docker_id, ctx.body); }); }); app.use(router.routes()).use(router.allowedMethods()); app.listen(3000);