@cap-js-community/common 0.1.0 → 0.1.1
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/README.md
CHANGED
|
@@ -136,7 +136,7 @@ Options can be passed to migration check via CDS environment via `cds.migrationC
|
|
|
136
136
|
### Usage
|
|
137
137
|
|
|
138
138
|
```cds
|
|
139
|
-
@cds.
|
|
139
|
+
@cds.rateLimiting
|
|
140
140
|
service BookshopService {
|
|
141
141
|
entity Books @readonly as projection on test.Books;
|
|
142
142
|
}
|
|
@@ -144,10 +144,10 @@ service BookshopService {
|
|
|
144
144
|
|
|
145
145
|
### Annotations
|
|
146
146
|
|
|
147
|
-
- `@cds.
|
|
148
|
-
- `@cds.
|
|
149
|
-
- `@cds.
|
|
150
|
-
- `@cds.
|
|
147
|
+
- `@cds.rateLimiting: Boolean`: Activate rate limit for service
|
|
148
|
+
- `@cds.rateLimiting.maxConcurrent: Number`: Maximum number of concurrent requests per service and tenant
|
|
149
|
+
- `@cds.rateLimiting.maxInWindow: Number`: Maximum number of requests in defined window per service and tenant
|
|
150
|
+
- `@cds.rateLimiting.window: Number`: Window length in milliseconds
|
|
151
151
|
|
|
152
152
|
### Options
|
|
153
153
|
|
package/cds-plugin.js
CHANGED
|
@@ -10,9 +10,9 @@ const TIMEOUT_SHUTDOWN = 2500;
|
|
|
10
10
|
if (cds.env.rateLimiting.plugin) {
|
|
11
11
|
cds.on("serving", async (service) => {
|
|
12
12
|
if (
|
|
13
|
-
service.definition["@cds.
|
|
13
|
+
service.definition["@cds.rateLimiting"] ||
|
|
14
14
|
Object.keys(service.definition).find((name) => {
|
|
15
|
-
return name.startsWith("@cds.
|
|
15
|
+
return name.startsWith("@cds.rateLimiting.");
|
|
16
16
|
})
|
|
17
17
|
) {
|
|
18
18
|
const rateLimiting = new RateLimiting(service);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cap-js-community/common",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "CAP Node.js Community Common",
|
|
5
5
|
"homepage": "https://cap.cloud.sap/",
|
|
6
6
|
"engines": {
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@cap-js/sqlite": "^1.10.0",
|
|
48
|
+
"commander": "^13.1.0",
|
|
48
49
|
"redis": "^4.7.0",
|
|
49
50
|
"verror": "^1.10.1"
|
|
50
51
|
},
|
|
@@ -54,7 +55,6 @@
|
|
|
54
55
|
"@sap/cds": "^8.9.1",
|
|
55
56
|
"@sap/cds-common-content": "^2.1.0",
|
|
56
57
|
"@sap/cds-dk": "^8.9.1",
|
|
57
|
-
"commander": "^13.1.0",
|
|
58
58
|
"eslint": "9.24.0",
|
|
59
59
|
"eslint-config-prettier": "10.1.1",
|
|
60
60
|
"eslint-plugin-jest": "28.11.0",
|
|
@@ -200,16 +200,25 @@ class MigrationCheck {
|
|
|
200
200
|
if (admin) {
|
|
201
201
|
result.adminHash = messageHash;
|
|
202
202
|
}
|
|
203
|
-
if (this.options.adminHash
|
|
204
|
-
|
|
205
|
-
|
|
203
|
+
if (this.options.adminHash) {
|
|
204
|
+
if (this.options.adminHash === messageHash) {
|
|
205
|
+
for (const message of result.messages) {
|
|
206
|
+
message.severity = message.severity === "error" ? "warning" : message.severity;
|
|
207
|
+
}
|
|
208
|
+
messages.push({
|
|
209
|
+
code: "AcceptedByAdmin",
|
|
210
|
+
text: "Migration check errors accepted by admin",
|
|
211
|
+
severity: "info",
|
|
212
|
+
});
|
|
213
|
+
result.success = true;
|
|
214
|
+
} else {
|
|
215
|
+
messages.push({
|
|
216
|
+
code: "AdminHashInvalid",
|
|
217
|
+
text: "Admin hash is not valid for current migration check state",
|
|
218
|
+
severity: "error",
|
|
219
|
+
});
|
|
220
|
+
result.success = false;
|
|
206
221
|
}
|
|
207
|
-
messages.push({
|
|
208
|
-
code: "AcceptedByAdmin",
|
|
209
|
-
text: "Migration check errors accepted by admin",
|
|
210
|
-
severity: "info",
|
|
211
|
-
});
|
|
212
|
-
result.success = true;
|
|
213
222
|
} else {
|
|
214
223
|
result.success = false;
|
|
215
224
|
}
|
|
@@ -17,10 +17,10 @@ class RateLimiting {
|
|
|
17
17
|
this.resetTime = null;
|
|
18
18
|
this.tenantCounts = {}; // [<tenant>: {concurrent: 0, window: 0}]
|
|
19
19
|
this.maxConcurrent =
|
|
20
|
-
maxConcurrent || service.definition["@cds.
|
|
20
|
+
maxConcurrent || service.definition["@cds.rateLimiting.maxConcurrent"] || cds.env.rateLimiting.maxConcurrent;
|
|
21
21
|
this.maxInWindow =
|
|
22
|
-
maxInWindow || service.definition["@cds.
|
|
23
|
-
this.window = window || service.definition["@cds.
|
|
22
|
+
maxInWindow || service.definition["@cds.rateLimiting.maxInWindow"] || cds.env.rateLimiting.maxInWindow;
|
|
23
|
+
this.window = window || service.definition["@cds.rateLimiting.window"] || cds.env.rateLimiting.window;
|
|
24
24
|
this.redisActive = cds.env.rateLimiting.redis;
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -181,18 +181,21 @@ class RateLimiting {
|
|
|
181
181
|
req.error({
|
|
182
182
|
code: "TOO_MANY_REQUESTS",
|
|
183
183
|
status: 429,
|
|
184
|
+
statusCode: 429,
|
|
184
185
|
message: `Too many requests in time window (max ${this.maxInWindow}), please try again later.`,
|
|
185
186
|
});
|
|
186
187
|
} else if (status.exceeds?.concurrent) {
|
|
187
188
|
req.error({
|
|
188
189
|
code: "TOO_MANY_REQUESTS",
|
|
189
190
|
status: 429,
|
|
191
|
+
statusCode: 429,
|
|
190
192
|
message: `Too many concurrent requests (max ${this.maxConcurrent}), please try again later.`,
|
|
191
193
|
});
|
|
192
194
|
} else {
|
|
193
195
|
req.error({
|
|
194
196
|
code: "TOO_MANY_REQUESTS",
|
|
195
197
|
status: 429,
|
|
198
|
+
statusCode: 429,
|
|
196
199
|
message: "Too many requests, please try again later.",
|
|
197
200
|
});
|
|
198
201
|
}
|