forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			117 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			117 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 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 = <string>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<void> {
 | |
|         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()
 |