forked from MapComplete/MapComplete
		
	Better documentation of server configuration, add error reporting server
This commit is contained in:
		
							parent
							
								
									cd0d275965
								
							
						
					
					
						commit
						13ea16317f
					
				
					 5 changed files with 127 additions and 15 deletions
				
			
		|  | @ -17,7 +17,7 @@ countrycoder.mapcomplete.org { | ||||||
| 
 | 
 | ||||||
| report.mapcomplete.org { | report.mapcomplete.org { | ||||||
| 	reverse_proxy { | 	reverse_proxy { | ||||||
| 		to http://127.0.0.1:2600 | 		to http://127.0.0.1:2348 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,11 +2,49 @@ | ||||||
| 
 | 
 | ||||||
| This server hosts the studio files and is used for expermintal builds. | This server hosts the studio files and is used for expermintal builds. | ||||||
| 
 | 
 | ||||||
| For used hosts, see the Caddyfile | For used ports, see the Caddyfile | ||||||
|  | 
 | ||||||
|  | To update caddy | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  |     cp Caddyfile /etc/caddy/ | ||||||
|  |     # If caddy was running via a console instead of as a service, do `caddy stop` now | ||||||
|  |     systemctl reload caddy | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Debug logs with: `journalctl -u caddy --no-pager | less +G` | ||||||
|  | 
 | ||||||
|  | Services: | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ## Cache forwarding | ### studio + theme sync | ||||||
| 
 | 
 | ||||||
| As the ISP of Nerdlab is a bit picky, we use SSH-port-forwarding on the cache server: | The studio server, handling those requests. | ||||||
| 
 | 
 | ||||||
| `ssh -R 5445:127.0.0.1:5445 hetzner` | `npm run server:studio` | ||||||
|  | 
 | ||||||
|  | Additionally, this runs syncthing to make a backup of all theme files. | ||||||
|  | 
 | ||||||
|  | ### LOD-server | ||||||
|  | 
 | ||||||
|  | A server scraping other websites. | ||||||
|  | 
 | ||||||
|  | `npm run server:ldjson` | ||||||
|  | 
 | ||||||
|  | ### Error report server | ||||||
|  | 
 | ||||||
|  | A simple server logging everything it receives | ||||||
|  | 
 | ||||||
|  | `npm run server:errorreport` | ||||||
|  | 
 | ||||||
|  | ### geo-ip | ||||||
|  | 
 | ||||||
|  | Provides geolocation based on | ||||||
|  | 
 | ||||||
|  |     ``` | ||||||
|  |     git clone https://github.com/pietervdvn/geoip-server | ||||||
|  |     cd geoip-server | ||||||
|  |     mkdir data | ||||||
|  |     # Drop the databases from https://lite.ip2location.com/ in the data dir | ||||||
|  |     npm run start | ||||||
|  |     ``` | ||||||
|  |  | ||||||
|  | @ -114,8 +114,10 @@ | ||||||
|     "dloadVelopark": "vite-node scripts/velopark/veloParkToGeojson.ts ", |     "dloadVelopark": "vite-node scripts/velopark/veloParkToGeojson.ts ", | ||||||
|     "compareVelopark": "vite-node scripts/velopark/compare.ts -- velopark_nonsynced_.geojson ~/Projecten/OSM/Fietsberaad/2024-02-02\\ Fietsenstallingen_OSM_met_velopark_ref.geojson\n", |     "compareVelopark": "vite-node scripts/velopark/compare.ts -- velopark_nonsynced_.geojson ~/Projecten/OSM/Fietsberaad/2024-02-02\\ Fietsenstallingen_OSM_met_velopark_ref.geojson\n", | ||||||
|     "scrapeWebsites": "vite-node scripts/importscripts/compareWebsiteData.ts -- ~/Downloads/ShopsWithWebsiteNodes.csv ~/data/scraped_websites/", |     "scrapeWebsites": "vite-node scripts/importscripts/compareWebsiteData.ts -- ~/Downloads/ShopsWithWebsiteNodes.csv ~/data/scraped_websites/", | ||||||
|     "summary-server": "vite-node scripts/osm2pgsql/tilecountServer.ts", |     "server:summary": "vite-node scripts/osm2pgsql/tilecountServer.ts", | ||||||
|     "ldjson-server": "vite-node scripts/serverLdScrape.ts", |     "server:ldjson": "vite-node scripts/serverLdScrape.ts", | ||||||
|  |     "sever:studio": "vite-node scripts/studioServer -- /root/git/MapComplete/assets", | ||||||
|  |     "server:errorreport": "vite-node scripts/serverErrorReport.ts -- /root/error_reports/", | ||||||
|     "generate:buildDbScript": "vite-node scripts/osm2pgsql/generateBuildDbScript.ts" |     "generate:buildDbScript": "vite-node scripts/osm2pgsql/generateBuildDbScript.ts" | ||||||
|   }, |   }, | ||||||
|   "keywords": [ |   "keywords": [ | ||||||
|  |  | ||||||
|  | @ -1,17 +1,36 @@ | ||||||
| import http from "node:http" | import http from "node:http" | ||||||
| 
 | 
 | ||||||
|  | export interface Handler { | ||||||
|  |     mustMatch: string | RegExp | ||||||
|  |     mimetype: string | ||||||
|  |     addHeaders?: Record<string, string> | ||||||
|  |     handle: (path: string, queryParams: URLSearchParams, req: http.IncomingMessage) => Promise<string> | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class ServerUtils { | ||||||
|  | 
 | ||||||
|  |     public static getBody(req: http.IncomingMessage): Promise<string> { | ||||||
|  |         return new Promise<string>((resolve) => { | ||||||
|  |             let body = ''; | ||||||
|  |             req.on('data', (chunk) => { | ||||||
|  |                 body += chunk; | ||||||
|  |             }); | ||||||
|  |             req.on('end', () => { | ||||||
|  |                 resolve(body) | ||||||
|  |             }); | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export class Server { | export class Server { | ||||||
|     constructor( |     constructor( | ||||||
|         port: number, |         port: number, | ||||||
|         options: { |         options: { | ||||||
|             ignorePathPrefix?: string[] |             ignorePathPrefix?: string[] | ||||||
|         }, |         }, | ||||||
|         handle: { |         handle: Handler[] | ||||||
|             mustMatch: string | RegExp |  | ||||||
|             mimetype: string |  | ||||||
|             addHeaders?: Record<string, string> |  | ||||||
|             handle: (path: string, queryParams: URLSearchParams) => Promise<string> |  | ||||||
|         }[] |  | ||||||
|     ) { |     ) { | ||||||
|         handle.push({ |         handle.push({ | ||||||
|             mustMatch: "", |             mustMatch: "", | ||||||
|  | @ -81,8 +100,9 @@ export class Server { | ||||||
|                     res.end() |                     res.end() | ||||||
|                     return |                     return | ||||||
|                 } |                 } | ||||||
|  |                 let body = undefined | ||||||
|                 if (req.method === "POST" || req.method === "UPDATE") { |                 if (req.method === "POST" || req.method === "UPDATE") { | ||||||
|                     return |                     body = await ServerUtils.getBody(req) | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 if (req.method === "DELETE") { |                 if (req.method === "DELETE") { | ||||||
|  | @ -90,7 +110,7 @@ export class Server { | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 try { |                 try { | ||||||
|                     const result = await handler.handle(path, url.searchParams) |                     const result = await handler.handle(path, url.searchParams, req, body) | ||||||
|                     if (result === undefined) { |                     if (result === undefined) { | ||||||
|                         res.writeHead(500) |                         res.writeHead(500) | ||||||
|                         res.write("Could not fetch this website, probably blocked by them") |                         res.write("Could not fetch this website, probably blocked by them") | ||||||
|  |  | ||||||
							
								
								
									
										52
									
								
								scripts/serverErrorReport.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								scripts/serverErrorReport.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,52 @@ | ||||||
|  | import { Handler, Server } from "./server" | ||||||
|  | import Script from "./Script" | ||||||
|  | import { appendFileSync, existsSync, mkdirSync, writeFileSync } from "fs" | ||||||
|  | import { mkdir } from "node:fs" | ||||||
|  | import ScriptUtils from "./ScriptUtils" | ||||||
|  | 
 | ||||||
|  | class ServerErrorReport extends Script { | ||||||
|  |     constructor() { | ||||||
|  |         super("A server which receives and logs error reports") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     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") | ||||||
|  |         } | ||||||
|  |         let errorReport = 0 | ||||||
|  |         new Server(2348, {}, | ||||||
|  |             [<Handler>{ | ||||||
|  |                 mustMatch: "report", | ||||||
|  |                 mimetype: "application/json", | ||||||
|  |                 handle: async (_, queryParams, req, body) => { | ||||||
|  |                     if (!body) { | ||||||
|  |                         throw "{\"error\": \"No body; use a post request\"}" | ||||||
|  |                     } | ||||||
|  |                     console.log(body) | ||||||
|  |                     const ip = <string>req.headers["x-forwarded-for"] | ||||||
|  |                     const d = new Date() | ||||||
|  |                     const date = d.toISOString() | ||||||
|  |                     const file = logDirectory + "/" + d.getUTCFullYear() + "_" + d.getUTCMonth() + "_" + d.getUTCDay() + ".lines.json" | ||||||
|  |                     try{ | ||||||
|  |                         body = JSON.parse(body) | ||||||
|  |                     }catch (e) { | ||||||
|  |                         // could not parse, we'll save it as is
 | ||||||
|  |                     } | ||||||
|  |                     const contents = "\n"+JSON.stringify({ ip, index: errorReport, date, message: body }) | ||||||
|  |                     if (!existsSync(file)) { | ||||||
|  |                         writeFileSync(file, contents) | ||||||
|  |                     } else { | ||||||
|  |                         appendFileSync(file, contents) | ||||||
|  |                     } | ||||||
|  |                     errorReport++ | ||||||
|  |                     return `{"status":"ok", "nr": ${errorReport}}` | ||||||
|  |                 }, | ||||||
|  | 
 | ||||||
|  |             }]) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | new ServerErrorReport().run() | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue