HTTP request logging format 2

This commit is contained in:
peter
2020-10-02 20:22:20 +02:00
parent 7e2c1d5761
commit f9008e67bd
4 changed files with 122 additions and 35 deletions
+62
View File
@@ -93,12 +93,29 @@
} }
} }
}, },
"@types/body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
"requires": {
"@types/connect": "*",
"@types/node": "*"
}
},
"@types/color-name": { "@types/color-name": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
"dev": true "dev": true
}, },
"@types/connect": {
"version": "3.4.33",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
"integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
"requires": {
"@types/node": "*"
}
},
"@types/engine.io": { "@types/engine.io": {
"version": "3.1.4", "version": "3.1.4",
"resolved": "https://registry.npmjs.org/@types/engine.io/-/engine.io-3.1.4.tgz", "resolved": "https://registry.npmjs.org/@types/engine.io/-/engine.io-3.1.4.tgz",
@@ -107,6 +124,27 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/express": {
"version": "4.17.8",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz",
"integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==",
"requires": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "*",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"@types/express-serve-static-core": {
"version": "4.17.13",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz",
"integrity": "sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA==",
"requires": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*"
}
},
"@types/fs-extra": { "@types/fs-extra": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.0.tgz", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.0.tgz",
@@ -133,6 +171,11 @@
"@types/lodash": "*" "@types/lodash": "*"
} }
}, },
"@types/mime": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz",
"integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q=="
},
"@types/mocha": { "@types/mocha": {
"version": "5.2.7", "version": "5.2.7",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
@@ -151,6 +194,25 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/qs": {
"version": "6.9.5",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz",
"integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ=="
},
"@types/range-parser": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
},
"@types/serve-static": {
"version": "1.13.5",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.5.tgz",
"integrity": "sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ==",
"requires": {
"@types/express-serve-static-core": "*",
"@types/mime": "*"
}
},
"@types/socket.io": { "@types/socket.io": {
"version": "2.1.10", "version": "2.1.10",
"resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.10.tgz", "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.10.tgz",
+1
View File
@@ -25,6 +25,7 @@
"author": "frontblock.me", "author": "frontblock.me",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@types/express": "^4.17.8",
"@types/mocha": "^5.2.7", "@types/mocha": "^5.2.7",
"@types/node": "^14.0.27", "@types/node": "^14.0.27",
"bsert": "0.0.10", "bsert": "0.0.10",
+39 -24
View File
@@ -15,12 +15,14 @@ import { CharacterManager } from '../Components/Character/CharacterManager';
import { UserManager } from '../Components/User/UserManager'; import { UserManager } from '../Components/User/UserManager';
import { RootComponent } from '../Injector/ServiceDecorator'; import { RootComponent } from '../Injector/ServiceDecorator';
import { TableDefinitionExporter } from '../Types/Interfaces'; import { TableDefinitionExporter } from '../Types/Interfaces';
import { AdminConf, TableDefiniton } from '../Types/Types'; import { AdminConf, TableDefiniton, SomeOf } from '../Types/Types';
import { RPCConfigLoader } from '../Components/RPCConfigLoader'; import { RPCConfigLoader } from '../Components/RPCConfigLoader';
import { FrontworkComponent } from '../Types/FrontworkComponent'; import { FrontworkComponent } from '../Types/FrontworkComponent';
import { IAdmin } from './Interface'; import { IAdmin } from './Interface';
import { Injector } from '../Injector/Injector'; import { Injector } from '../Injector/Injector';
import { PubSub } from '../Components/PubSub/PubSub'; import { PubSub } from '../Components/PubSub/PubSub';
import { BurstyRateLimiter, RateLimiterMemory, RateLimiterAbstract } from 'rate-limiter-flexible'
@RootComponent({ @RootComponent({
injectable: IAdmin, injectable: IAdmin,
@@ -67,13 +69,24 @@ export class FrontworkAdmin
async start() { async start() {
let port: number = this.config.getConfig().httpPort let port: number = this.config.getConfig().httpPort
const rateLimiter = new BurstyRateLimiter(
new RateLimiterMemory({
points: 2,
duration: 1,
}),
new RateLimiterMemory({
keyPrefix: 'burst',
points: 60,
duration: 60,
})
)
await this.makeKnex() await this.makeKnex()
const app = await this.makeExpress() const app = await this.makeExpress(rateLimiter)
const httpServer = new http.Server(app) const httpServer = new http.Server(app)
await this.startWebsocket(httpServer) await this.startWebsocket(httpServer)
httpServer.listen(port) httpServer.listen(port)
await this.attachAngularSSR(app) await this.attachAngularSSR(app, rateLimiter)
getLogger('Admin#startWebsocket').debug("Webserver up on", port) getLogger('Admin#startWebsocket').debug("Webserver up on", port)
await Promise.all(this.frontworkComponents.map(c => c.initialize ? c.initialize() : undefined)) await Promise.all(this.frontworkComponents.map(c => c.initialize ? c.initialize() : undefined))
@@ -125,51 +138,53 @@ export class FrontworkAdmin
} }
], { ], {
errorHandler: (sock, err, rpc, args) => { errorHandler: (sock, err, rpc, args) => {
console.log("RPC", rpc) getLogger("startWebsocket#errorHandler").error("RPC", rpc)
console.log("ERR", err) getLogger("startWebsocket#errorHandler").error("ERR", err)
console.log("ARGS", args) getLogger("startWebsocket#errorHandler").error("ARGS", args)
} }
}) })
.attach(httpServer) .attach(httpServer)
} }
private async makeExpress() { private async makeExpress(rateLimiter : SomeOf<RateLimiterAbstract> = new RateLimiterMemory({ points: 6, duration: 3 })) {
if (this.httpServer != null || this.express != null) { if (this.httpServer != null || this.express != null) {
getLogger('Admin#startWebserver').warn("Webserver is already running") getLogger('Admin#startWebserver').warn("Webserver is already running")
return return
} }
this.express = express() this.express = express()
const distFolder = "../../../../dist" const distFolder = "../../../../dist"
this.express.get('*.*', (req, res) => { this.express.get('*.*', (req, res) => {
//console.log('*.*', req.path); rateLimiter.consume(req.ip)
try{ .then(_ => {
const filepath = Path.join(__dirname, distFolder, 'browser', decodeURIComponent(req.path)) const filepath = Path.join(__dirname, distFolder, 'browser', decodeURIComponent(req.path))
if(!existsSync(filepath)){ if(!existsSync(filepath)){
throw new Error("FAILED REQUEST "+filepath+ " FROM "+req.ip) getLogger('Admin#startWebserver#serveFile').error(String(new Error("404 BAD REQUEST "+filepath+ " FROM "+req.ip)))
} res.send("404 Not found")
res.sendFile(filepath) res.status(404)
res.status(200) return
}catch(e){ }
getLogger('Admin#startWebserver#serveFile').error(String(e)) res.sendFile(filepath)
res.send("404 NOT FOUND") res.status(200)
res.status(404) })
} .catch(_ => {
getLogger('Admin#startWebserver#serveFile').error(String(new Error("429 BAD REQUEST "+req.path+" FROM "+req.ip)))
res.send('429 Too many requests')
res.status(429)
})
}) })
return this.express return this.express
} }
attachAngularSSR = async (express : express.Application) => { attachAngularSSR = async (express : express.Application, rateLimiter : SomeOf<RateLimiterAbstract> = new RateLimiterMemory({ points: 6, duration: 3 })) => {
const distFolder = "../../../../dist" const distFolder = "../../../../dist"
const ngExpressServer = Path.join(__dirname, distFolder, 'server.js') const ngExpressServer = Path.join(__dirname, distFolder, 'server.js')
let port: number = this.config.getConfig().httpPort let port: number = this.config.getConfig().httpPort
try { try {
const req = require(distFolder + "/server.js") const req = require(distFolder + "/server.js")
await req.attachExpress(express, './dist', getLogger('angularSSR#')) await req.attachExpress(express, './dist', getLogger('angularSSR#'), rateLimiter)
getLogger('Admin#startWebserver').debug('Frontend from ' + ngExpressServer + " loaded") getLogger('Admin#startWebserver').debug('Frontend from ' + ngExpressServer + " loaded")
} catch (e) { } catch (e) {
getLogger('Admin#startWebserver').error(e) getLogger('Admin#startWebserver').error(e)
+20 -11
View File
@@ -15,15 +15,21 @@ global['alert'] = console.log
global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest; global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
global['fetch'] = fetch.default; global['fetch'] = fetch.default;
/**
* Function to attach this SSR application to an express server. Exported as function due to webpack inconsistencies.
export async function attachExpress(app, staticDir = "./dist", logger = console) { *
* @param app express.Application to run on
* @param staticDir Where the static website content is (i.e. ./dist)
* @param logger A loggerservice or console
* @param rateLimiter a rate-limiter-flexible instance
*/
export async function attachExpress(app, staticDir, logger, rateLimiter) {
const STATIC_FOLDER = resolve(process.cwd(), staticDir); const STATIC_FOLDER = resolve(process.cwd(), staticDir);
enableProdMode(); enableProdMode();
const loggerService = { const loggerService = {
warn: (...args) => logger.error(...args), warn: (...args) => logger.warn(...args),
error: (...args) => logger.warn(...args), error: (...args) => logger.error(...args),
log: (...args) => logger.info(...args), log: (...args) => logger.info(...args),
table: (...args) => logger.info(...args), table: (...args) => logger.info(...args),
collapsed: (msg, type, ...args) => loggerService[type](msg, ...args) collapsed: (msg, type, ...args) => loggerService[type](msg, ...args)
@@ -57,11 +63,14 @@ export async function attachExpress(app, staticDir = "./dist", logger = console)
); );
app.get('*', (req, res) => { app.get('*', (req, res) => {
loggerService.log("REQUEST "+req.path +" FROM "+ req.ip) rateLimiter.consume(req.ip, 3)
try{ .then(_ => {
res.render(resolve(STATIC_FOLDER, 'browser/index'), { req, res }) res.render(resolve(STATIC_FOLDER, 'browser/index'), { req, res })
}catch(e){ })
loggerService.error(e) .catch(_ => {
} loggerService.error(String(new Error("429 BAD REQUEST "+req.path+" FROM "+req.ip)))
}); res.send("429 Too many requests")
res.status(429)
})
})
} }