@adaptivestone/framework 5.0.0-beta.31 → 5.0.0-beta.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -2
- package/dist/services/http/middleware/IpDetector.d.ts +2 -0
- package/dist/services/http/middleware/IpDetector.js +7 -3
- package/dist/services/http/middleware/IpDetector.js.map +1 -1
- package/dist/services/http/middleware/RateLimiter.d.ts +8 -1
- package/dist/services/http/middleware/RateLimiter.js +15 -7
- package/dist/services/http/middleware/RateLimiter.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -25,6 +25,7 @@ Main feature of that release is full TypeScript support insluding mongoose model
|
|
|
25
25
|
- **[NEW]** `IpDetector` middleware for detecting proxies and `X-Forwarded-For` headers.
|
|
26
26
|
- **[NEW]** Test helpers getTestServerURL and serverInstance.
|
|
27
27
|
- **[NEW]** Rate limiter middleware - add consumeResult function to allow user middleware as a regular rate limiter
|
|
28
|
+
- **[NEW]** Ip detector middleware - add getIpAdressFromIncomingMessage function to allow user middleware as a detector of id adresses without middleware
|
|
28
29
|
|
|
29
30
|
### Breaking changes (please read carefully)
|
|
30
31
|
|
|
@@ -48,15 +49,26 @@ Main feature of that release is full TypeScript support insluding mongoose model
|
|
|
48
49
|
- **[BREAKING]** Mongoose v8. <https://mongoosejs.com/docs/migrating_to_8.html>.
|
|
49
50
|
|
|
50
51
|
|
|
52
|
+
|
|
51
53
|
---
|
|
52
54
|
|
|
53
|
-
## [5.0.0-beta.
|
|
55
|
+
## [5.0.0-beta.33]
|
|
54
56
|
|
|
55
|
-
- **[NEW]**
|
|
57
|
+
- **[NEW]** consumeResult changed to be more flexible
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## [5.0.0-beta.32]
|
|
56
62
|
|
|
63
|
+
- **[NEW]** Ip detector middleware - add getIpAdressFromIncomingMessage function to allow user middleware as a detector of id adresses without middleware
|
|
57
64
|
|
|
58
65
|
---
|
|
59
66
|
|
|
67
|
+
## [5.0.0-beta.31]
|
|
68
|
+
|
|
69
|
+
- **[NEW]** Rate limiter middleware - add consumeResult function to allow user middleware as a regular rate limiter
|
|
70
|
+
|
|
71
|
+
|
|
60
72
|
---
|
|
61
73
|
|
|
62
74
|
## [5.0.0-beta.30]
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IncomingMessage } from 'node:http';
|
|
1
2
|
import { BlockList } from 'node:net';
|
|
2
3
|
import type { NextFunction, Response } from 'express';
|
|
3
4
|
import type { IApp } from '../../../server.ts';
|
|
@@ -7,6 +8,7 @@ declare class IpDetector extends AbstractMiddleware {
|
|
|
7
8
|
static get description(): string;
|
|
8
9
|
blockList: BlockList;
|
|
9
10
|
constructor(app: IApp, params?: Record<string, unknown>);
|
|
11
|
+
getIpAdressFromIncomingMessage(req: IncomingMessage): string | undefined;
|
|
10
12
|
middleware(req: FrameworkRequest, _res: Response, next: NextFunction): Promise<void>;
|
|
11
13
|
}
|
|
12
14
|
export default IpDetector;
|
|
@@ -27,10 +27,10 @@ class IpDetector extends AbstractMiddleware {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
getIpAdressFromIncomingMessage(req) {
|
|
31
31
|
const { headers } = this.app.getConfig('ipDetector');
|
|
32
32
|
const initialIp = req.socket.remoteAddress;
|
|
33
|
-
|
|
33
|
+
let ip = initialIp;
|
|
34
34
|
const addressType = initialIp?.includes(':') ? 'ipv6' : 'ipv4';
|
|
35
35
|
if (this.blockList.check(initialIp ?? '', addressType)) {
|
|
36
36
|
// we can trust this source
|
|
@@ -39,11 +39,15 @@ class IpDetector extends AbstractMiddleware {
|
|
|
39
39
|
const ipHeader = req.headers[header.toLowerCase()];
|
|
40
40
|
if (ipHeader) {
|
|
41
41
|
const [firstIp] = ipHeader.split(',').map((ip) => ip.trim());
|
|
42
|
-
|
|
42
|
+
ip = firstIp;
|
|
43
43
|
break;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
return ip;
|
|
48
|
+
}
|
|
49
|
+
async middleware(req, _res, next) {
|
|
50
|
+
req.appInfo.ip = this.getIpAdressFromIncomingMessage(req);
|
|
47
51
|
next();
|
|
48
52
|
}
|
|
49
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IpDetector.js","sourceRoot":"","sources":["../../../../src/services/http/middleware/IpDetector.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"IpDetector.js","sourceRoot":"","sources":["../../../../src/services/http/middleware/IpDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,14 @@ declare class RateLimiter extends AbstractMiddleware {
|
|
|
13
13
|
constructor(app: IApp, params?: Record<string, unknown>);
|
|
14
14
|
initRedisLimiter(): RateLimiterRedis;
|
|
15
15
|
gerenateConsumeKey(req: FrameworkRequest & GetUserByTokenAppInfo): string;
|
|
16
|
-
consumeResult(consumeKey: string): Promise<
|
|
16
|
+
consumeResult(consumeKey: string, consumePoints?: number): Promise<{
|
|
17
|
+
msBeforeNext: number;
|
|
18
|
+
remainingPoints: number;
|
|
19
|
+
consumedPoints: number;
|
|
20
|
+
isFirstInDuration: boolean;
|
|
21
|
+
isAllowed: boolean;
|
|
22
|
+
retryAfter: number;
|
|
23
|
+
}>;
|
|
17
24
|
middleware(req: FrameworkRequest, res: Response, next: NextFunction): Promise<void | Response<any, Record<string, any>>>;
|
|
18
25
|
}
|
|
19
26
|
export default RateLimiter;
|
|
@@ -84,12 +84,17 @@ class RateLimiter extends AbstractMiddleware {
|
|
|
84
84
|
}
|
|
85
85
|
return key.join('_');
|
|
86
86
|
}
|
|
87
|
-
async consumeResult(consumeKey) {
|
|
88
|
-
|
|
89
|
-
.consume(consumeKey, this.finalOptions.consumePoints)
|
|
90
|
-
|
|
87
|
+
async consumeResult(consumeKey, consumePoints = 0) {
|
|
88
|
+
try {
|
|
89
|
+
const result = await this.limiter.consume(consumeKey, consumePoints || this.finalOptions.consumePoints);
|
|
90
|
+
return { isAllowed: true, retryAfter: 0, ...result };
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
91
93
|
this.logger?.warn(`Too many requests. Consume key: ${consumeKey}`);
|
|
92
|
-
|
|
94
|
+
const result = e;
|
|
95
|
+
const retryAfter = Math.round(result.msBeforeNext / 1000) || 1;
|
|
96
|
+
return { isAllowed: false, retryAfter, ...result };
|
|
97
|
+
}
|
|
93
98
|
}
|
|
94
99
|
async middleware(req, res, next) {
|
|
95
100
|
if (!this.limiter) {
|
|
@@ -99,10 +104,13 @@ class RateLimiter extends AbstractMiddleware {
|
|
|
99
104
|
const { namespace } = this.app.getConfig('redis');
|
|
100
105
|
const consumeKey = `${namespace}-${this.gerenateConsumeKey(req)}`;
|
|
101
106
|
const consumeResult = await this.consumeResult(consumeKey);
|
|
102
|
-
if (consumeResult) {
|
|
107
|
+
if (consumeResult.isAllowed) {
|
|
103
108
|
return next();
|
|
104
109
|
}
|
|
105
|
-
return res
|
|
110
|
+
return res
|
|
111
|
+
.status(429)
|
|
112
|
+
.header('Retry-After', String(consumeResult.retryAfter))
|
|
113
|
+
.json({ message: 'Too Many Requests' });
|
|
106
114
|
}
|
|
107
115
|
}
|
|
108
116
|
export default RateLimiter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../../../src/services/http/middleware/RateLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,MAAM,WAAW,CAAC;AAE9B,OAAO,QAAQ,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../../../src/services/http/middleware/RateLimiter.ts"],"names":[],"mappings":"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"}
|