import { Handler, Server } from "./server" import Script from "./Script" import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs" import { mkdir } from "node:fs" import ScriptUtils from "./ScriptUtils" import { IncomingMessage } from "node:http" class ServerErrorReport extends Script { private errorReport = 0 constructor() { super("A server which receives and logs error reports") } private getFilename(logDirectory: string, d: Date): string { return ( logDirectory + "/" + d.getUTCFullYear() + "_" + (d.getUTCMonth() + 1) + "_" + d.getUTCDate() + ".lines.json" ) } public reportError( path: string, queryParams: URLSearchParams, req: IncomingMessage, body: string | undefined, logDirectory: string ): string { if (!body) { throw '{"error": "No body; use a post request"}' } console.log(body) const ip = req.headers["x-forwarded-for"] try { body = JSON.parse(body) } catch (e) { // could not parse, we'll save it as is } const d = new Date() const file = this.getFilename(logDirectory, d) const date = d.toISOString() const contents = "\n" + JSON.stringify({ ip, index: this.errorReport, date, message: body }) if (!existsSync(file)) { writeFileSync(file, contents) } else { appendFileSync(file, contents) } this.errorReport++ return `{"status":"ok", "nr": ${this.errorReport}}` } async main(args: string[]): Promise { const logDirectory = args[0] ?? "./error_logs" console.log("Logging to directory", logDirectory) if (!existsSync(logDirectory)) { mkdirSync(logDirectory) console.log("Created this directory") } if (!existsSync(logDirectory + "/csp")) { mkdirSync(logDirectory + "/csp") console.log("Created this directory") } new Server(2348, {}, [ { mustMatch: "status", mimetype: "application/json", handle: async () => { const filename = this.getFilename(logDirectory, new Date()) let errorsToday = 0 if (existsSync(filename)) { const contents = readFileSync(filename, "utf8") errorsToday = contents.split("\n").length } return JSON.stringify({ online: true, errors_today: errorsToday, }) }, }, { mustMatch: "report", mimetype: "application/json", handle: async ( path: string, queryParams: URLSearchParams, req: IncomingMessage, body: string | undefined ) => { return this.reportError(path, queryParams, req, body, logDirectory) }, }, { mustMatch: "csp", mimetype: "application/json", handle: async ( path: string, queryParams: URLSearchParams, req: IncomingMessage, body: string | undefined ) => { return this.reportError(path, queryParams, req, body, logDirectory + "/csp") }, }, ]) } } new ServerErrorReport().run()