Pārlūkot izejas kodu

HTTP request logging format 2

master
peter 5 gadus atpakaļ
vecāks
revīzija
f9008e67bd
4 mainītis faili ar 122 papildinājumiem un 35 dzēšanām
  1. 62
    0
      package-lock.json
  2. 1
    0
      package.json
  3. 39
    24
      src/backend/Admin/Admin.ts
  4. 20
    11
      src/frontend/server.ts

+ 62
- 0
package-lock.json Parādīt failu

@@ -93,12 +93,29 @@
93 93
         }
94 94
       }
95 95
     },
96
+    "@types/body-parser": {
97
+      "version": "1.19.0",
98
+      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
99
+      "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
100
+      "requires": {
101
+        "@types/connect": "*",
102
+        "@types/node": "*"
103
+      }
104
+    },
96 105
     "@types/color-name": {
97 106
       "version": "1.1.1",
98 107
       "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
99 108
       "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
100 109
       "dev": true
101 110
     },
111
+    "@types/connect": {
112
+      "version": "3.4.33",
113
+      "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
114
+      "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
115
+      "requires": {
116
+        "@types/node": "*"
117
+      }
118
+    },
102 119
     "@types/engine.io": {
103 120
       "version": "3.1.4",
104 121
       "resolved": "https://registry.npmjs.org/@types/engine.io/-/engine.io-3.1.4.tgz",
@@ -107,6 +124,27 @@
107 124
         "@types/node": "*"
108 125
       }
109 126
     },
127
+    "@types/express": {
128
+      "version": "4.17.8",
129
+      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz",
130
+      "integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==",
131
+      "requires": {
132
+        "@types/body-parser": "*",
133
+        "@types/express-serve-static-core": "*",
134
+        "@types/qs": "*",
135
+        "@types/serve-static": "*"
136
+      }
137
+    },
138
+    "@types/express-serve-static-core": {
139
+      "version": "4.17.13",
140
+      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz",
141
+      "integrity": "sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA==",
142
+      "requires": {
143
+        "@types/node": "*",
144
+        "@types/qs": "*",
145
+        "@types/range-parser": "*"
146
+      }
147
+    },
110 148
     "@types/fs-extra": {
111 149
       "version": "8.0.0",
112 150
       "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.0.0.tgz",
@@ -133,6 +171,11 @@
133 171
         "@types/lodash": "*"
134 172
       }
135 173
     },
174
+    "@types/mime": {
175
+      "version": "2.0.3",
176
+      "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz",
177
+      "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q=="
178
+    },
136 179
     "@types/mocha": {
137 180
       "version": "5.2.7",
138 181
       "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
@@ -151,6 +194,25 @@
151 194
         "@types/node": "*"
152 195
       }
153 196
     },
197
+    "@types/qs": {
198
+      "version": "6.9.5",
199
+      "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz",
200
+      "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ=="
201
+    },
202
+    "@types/range-parser": {
203
+      "version": "1.2.3",
204
+      "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
205
+      "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
206
+    },
207
+    "@types/serve-static": {
208
+      "version": "1.13.5",
209
+      "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.5.tgz",
210
+      "integrity": "sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ==",
211
+      "requires": {
212
+        "@types/express-serve-static-core": "*",
213
+        "@types/mime": "*"
214
+      }
215
+    },
154 216
     "@types/socket.io": {
155 217
       "version": "2.1.10",
156 218
       "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.10.tgz",

+ 1
- 0
package.json Parādīt failu

@@ -25,6 +25,7 @@
25 25
   "author": "frontblock.me",
26 26
   "license": "ISC",
27 27
   "dependencies": {
28
+    "@types/express": "^4.17.8",
28 29
     "@types/mocha": "^5.2.7",
29 30
     "@types/node": "^14.0.27",
30 31
     "bsert": "0.0.10",

+ 39
- 24
src/backend/Admin/Admin.ts Parādīt failu

@@ -15,12 +15,14 @@ import { CharacterManager } from '../Components/Character/CharacterManager';
15 15
 import { UserManager } from '../Components/User/UserManager';
16 16
 import { RootComponent } from '../Injector/ServiceDecorator';
17 17
 import { TableDefinitionExporter } from '../Types/Interfaces';
18
-import { AdminConf, TableDefiniton } from '../Types/Types';
18
+import { AdminConf, TableDefiniton, SomeOf } from '../Types/Types';
19 19
 import { RPCConfigLoader } from '../Components/RPCConfigLoader';
20 20
 import { FrontworkComponent } from '../Types/FrontworkComponent';
21 21
 import { IAdmin } from './Interface';
22 22
 import { Injector } from '../Injector/Injector';
23 23
 import { PubSub } from '../Components/PubSub/PubSub';
24
+import { BurstyRateLimiter, RateLimiterMemory, RateLimiterAbstract } from 'rate-limiter-flexible'
25
+
24 26
 
25 27
 @RootComponent({
26 28
     injectable: IAdmin,
@@ -67,13 +69,24 @@ export class FrontworkAdmin
67 69
 
68 70
     async start() {
69 71
         let port: number = this.config.getConfig().httpPort
72
+        const rateLimiter = new BurstyRateLimiter(
73
+            new RateLimiterMemory({
74
+              points: 2,
75
+              duration: 1,
76
+            }),
77
+            new RateLimiterMemory({
78
+              keyPrefix: 'burst',
79
+              points: 60,
80
+              duration: 60,
81
+            })
82
+          )
70 83
 
71 84
         await this.makeKnex()
72
-        const app = await this.makeExpress()
85
+        const app = await this.makeExpress(rateLimiter)
73 86
         const httpServer = new http.Server(app)
74 87
         await this.startWebsocket(httpServer)
75 88
         httpServer.listen(port)
76
-        await this.attachAngularSSR(app)
89
+        await this.attachAngularSSR(app, rateLimiter)
77 90
         getLogger('Admin#startWebsocket').debug("Webserver up on", port)
78 91
 
79 92
         await Promise.all(this.frontworkComponents.map(c => c.initialize ? c.initialize() : undefined))
@@ -125,51 +138,53 @@ export class FrontworkAdmin
125 138
             }
126 139
         ], {
127 140
             errorHandler: (sock, err, rpc, args) => {
128
-                console.log("RPC", rpc)
129
-                console.log("ERR", err)
130
-                console.log("ARGS", args)
141
+                getLogger("startWebsocket#errorHandler").error("RPC", rpc)
142
+                getLogger("startWebsocket#errorHandler").error("ERR", err)
143
+                getLogger("startWebsocket#errorHandler").error("ARGS", args)
131 144
             }
132 145
         })
133 146
         .attach(httpServer)
134 147
     }
135 148
 
136
-    private async makeExpress() {
149
+    private async makeExpress(rateLimiter : SomeOf<RateLimiterAbstract> = new RateLimiterMemory({ points: 6, duration: 3 })) {
137 150
         if (this.httpServer != null || this.express != null) {
138 151
             getLogger('Admin#startWebserver').warn("Webserver is already running")
139 152
             return
140 153
         }
141 154
 
142 155
         this.express = express()
143
-
144 156
         const distFolder = "../../../../dist"
145
-
146 157
         this.express.get('*.*', (req, res) => {
147
-            //console.log('*.*', req.path);
148
-            try{
149
-                const filepath = Path.join(__dirname, distFolder, 'browser', decodeURIComponent(req.path))
150
-                if(!existsSync(filepath)){
151
-                    throw new Error("FAILED REQUEST "+filepath+ " FROM "+req.ip)
152
-                }
153
-                res.sendFile(filepath)
154
-                res.status(200)
155
-            }catch(e){
156
-                getLogger('Admin#startWebserver#serveFile').error(String(e))
157
-                res.send("404 NOT FOUND")
158
-                res.status(404)
159
-            }
158
+            rateLimiter.consume(req.ip)
159
+            .then(_ => {
160
+                    const filepath = Path.join(__dirname, distFolder, 'browser', decodeURIComponent(req.path))
161
+                    if(!existsSync(filepath)){
162
+                        getLogger('Admin#startWebserver#serveFile').error(String(new Error("404 BAD REQUEST "+filepath+ " FROM "+req.ip)))
163
+                        res.send("404 Not found")
164
+                        res.status(404)
165
+                        return
166
+                    }
167
+                    res.sendFile(filepath)
168
+                    res.status(200)
169
+            })
170
+            .catch(_ => {
171
+                getLogger('Admin#startWebserver#serveFile').error(String(new Error("429 BAD REQUEST "+req.path+" FROM "+req.ip)))
172
+                res.send('429 Too many requests')
173
+                res.status(429)
174
+            })
160 175
         })
161 176
 
162 177
         return this.express
163 178
     }
164 179
 
165
-    attachAngularSSR = async (express : express.Application) => {
180
+    attachAngularSSR = async (express : express.Application, rateLimiter : SomeOf<RateLimiterAbstract> = new RateLimiterMemory({ points: 6, duration: 3 })) => {
166 181
         const distFolder = "../../../../dist"
167 182
         const ngExpressServer = Path.join(__dirname, distFolder, 'server.js')
168 183
         let port: number = this.config.getConfig().httpPort
169 184
 
170 185
         try {
171 186
             const req = require(distFolder + "/server.js")
172
-            await req.attachExpress(express, './dist', getLogger('angularSSR#'))
187
+            await req.attachExpress(express, './dist', getLogger('angularSSR#'), rateLimiter)
173 188
             getLogger('Admin#startWebserver').debug('Frontend from ' + ngExpressServer + " loaded")
174 189
         } catch (e) {
175 190
             getLogger('Admin#startWebserver').error(e)

+ 20
- 11
src/frontend/server.ts Parādīt failu

@@ -15,15 +15,21 @@ global['alert'] = console.log
15 15
 global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
16 16
 global['fetch'] = fetch.default;
17 17
 
18
-
19
-
20
-export async function attachExpress(app, staticDir = "./dist", logger = console) {
18
+/**
19
+ * Function to attach this SSR application to an express server. Exported as function due to webpack inconsistencies.
20
+ * 
21
+ * @param app express.Application to run on
22
+ * @param staticDir Where the static website content is (i.e. ./dist)
23
+ * @param logger A loggerservice or console
24
+ * @param rateLimiter a rate-limiter-flexible instance
25
+ */
26
+export async function attachExpress(app, staticDir, logger, rateLimiter) {
21 27
   const STATIC_FOLDER = resolve(process.cwd(), staticDir);
22 28
   enableProdMode();
23 29
 
24 30
   const loggerService = {
25
-    warn: (...args) => logger.error(...args),
26
-    error: (...args) => logger.warn(...args),
31
+    warn: (...args) => logger.warn(...args),
32
+    error: (...args) => logger.error(...args),
27 33
     log: (...args) => logger.info(...args),
28 34
     table: (...args) => logger.info(...args),
29 35
     collapsed: (msg, type, ...args) => loggerService[type](msg, ...args)
@@ -57,11 +63,14 @@ export async function attachExpress(app, staticDir = "./dist", logger = console)
57 63
   );
58 64
 
59 65
   app.get('*', (req, res) => {
60
-    loggerService.log("REQUEST "+req.path +" FROM "+ req.ip)
61
-    try{
66
+    rateLimiter.consume(req.ip, 3)
67
+    .then(_ => {
62 68
       res.render(resolve(STATIC_FOLDER, 'browser/index'), { req, res })
63
-    }catch(e){
64
-      loggerService.error(e)
65
-    }
66
-  });
69
+    })
70
+    .catch(_ => {
71
+      loggerService.error(String(new Error("429 BAD REQUEST "+req.path+" FROM "+req.ip)))
72
+      res.send("429 Too many requests")
73
+      res.status(429)
74
+    })
75
+  })
67 76
 }

Notiek ielāde…
Atcelt
Saglabāt