@moxon/api 6.1.0 → 6.2.0
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 +21 -14
- package/dist/app.js +5 -3
- package/dist/app.js.map +1 -1
- package/dist/constants.d.ts +22 -0
- package/dist/constants.js +22 -0
- package/dist/constants.js.map +1 -1
- package/dist/middleware/cors.d.ts +15 -0
- package/dist/middleware/cors.js +25 -6
- package/dist/middleware/cors.js.map +1 -1
- package/dist/middleware/ratelimit.d.ts +53 -1
- package/dist/middleware/ratelimit.js +180 -71
- package/dist/middleware/ratelimit.js.map +1 -1
- package/dist/modules/v4/barcode.d.ts +1 -1
- package/dist/modules/v4/barcode.js +9 -2
- package/dist/modules/v4/barcode.js.map +1 -1
- package/dist/modules/v4/captcha.d.ts +1 -1
- package/dist/modules/v4/captcha.js +5 -1
- package/dist/modules/v4/captcha.js.map +1 -1
- package/dist/modules/v4/chat.js +61 -12
- package/dist/modules/v4/chat.js.map +1 -1
- package/dist/modules/v4/cron.js +20 -2
- package/dist/modules/v4/cron.js.map +1 -1
- package/dist/modules/v4/hyperplanning.d.ts +11 -0
- package/dist/modules/v4/hyperplanning.js +30 -29
- package/dist/modules/v4/hyperplanning.js.map +1 -1
- package/dist/modules/v4/qrcode.d.ts +10 -0
- package/dist/modules/v4/qrcode.js +138 -14
- package/dist/modules/v4/qrcode.js.map +1 -1
- package/dist/modules/v4/regex.d.ts +1 -1
- package/dist/modules/v4/regex.js +67 -22
- package/dist/modules/v4/regex.js.map +1 -1
- package/dist/modules/v4/tic_tac_toe.js +56 -15
- package/dist/modules/v4/tic_tac_toe.js.map +1 -1
- package/dist/modules/v5/asymmetric.d.ts +15 -0
- package/dist/modules/v5/asymmetric.js +67 -5
- package/dist/modules/v5/asymmetric.js.map +1 -1
- package/dist/modules/v5/barcode.d.ts +1 -1
- package/dist/modules/v5/barcode.js +9 -2
- package/dist/modules/v5/barcode.js.map +1 -1
- package/dist/modules/v5/captcha.d.ts +12 -4
- package/dist/modules/v5/captcha.js +25 -8
- package/dist/modules/v5/captcha.js.map +1 -1
- package/dist/modules/v5/chat.js +66 -17
- package/dist/modules/v5/chat.js.map +1 -1
- package/dist/modules/v5/cron.d.ts +26 -0
- package/dist/modules/v5/cron.js +356 -0
- package/dist/modules/v5/cron.js.map +1 -0
- package/dist/modules/v5/pow.js +1 -1
- package/dist/modules/v5/pow.js.map +1 -1
- package/dist/modules/v5/tic_tac_toe.js +61 -20
- package/dist/modules/v5/tic_tac_toe.js.map +1 -1
- package/dist/modules/v5.d.ts +3 -2
- package/dist/modules/v5.js +3 -2
- package/dist/modules/v5.js.map +1 -1
- package/dist/routes/post.js +12 -5
- package/dist/routes/post.js.map +1 -1
- package/dist/storage/index.js +9 -8
- package/dist/storage/index.js.map +1 -1
- package/dist/types/storage.d.ts +4 -0
- package/dist/utils/challenge.d.ts +5 -3
- package/dist/utils/challenge.js +52 -6
- package/dist/utils/challenge.js.map +1 -1
- package/dist/utils/helpers.d.ts +18 -0
- package/dist/utils/helpers.js +35 -1
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/remote.d.ts +42 -0
- package/dist/utils/remote.js +313 -0
- package/dist/utils/remote.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,15 +75,15 @@ console.log(user.username);
|
|
|
75
75
|
|
|
76
76
|
## What's inside
|
|
77
77
|
|
|
78
|
-
| Domain | Exports
|
|
79
|
-
| ------------------ |
|
|
80
|
-
| **Crypto** | `asymmetric` `symmetric` `hash` `jwt` `otp` `token` `password` `captcha`
|
|
81
|
-
| **Math & data** | **`matrix`** **`algorithms`** `evaluate` `statistics` `convert` `csv`
|
|
82
|
-
| **Text** | **`text`** **`encode`** **`validate`** `caseConvert` `levenshtein` `regex` `parseUrl`
|
|
83
|
-
| **Graphics** | **`chart`** `barcode` `qrcode` `avatar` `placeholder` `color` `palette`
|
|
84
|
-
| **Fake data** | `personal` `address` `credit` `username` `dice` `domain` `agent`
|
|
85
|
-
| **Network & time** | `ip` `geo` `time` `cron` `hyperplanning`
|
|
86
|
-
| **Stateful** | `chat` `tic_tac_toe`
|
|
78
|
+
| Domain | Exports |
|
|
79
|
+
| ------------------ | ------------------------------------------------------------------------------------------ |
|
|
80
|
+
| **Crypto** | `asymmetric` `asymmetricAsync` `symmetric` `hash` `jwt` `otp` `token` `password` `captcha` |
|
|
81
|
+
| **Math & data** | **`matrix`** **`algorithms`** `evaluate` `statistics` `convert` `csv` |
|
|
82
|
+
| **Text** | **`text`** **`encode`** **`validate`** `caseConvert` `levenshtein` `regex` `parseUrl` |
|
|
83
|
+
| **Graphics** | **`chart`** `barcode` `qrcode` `avatar` `placeholder` `color` `palette` |
|
|
84
|
+
| **Fake data** | `personal` `address` `credit` `username` `dice` `domain` `agent` |
|
|
85
|
+
| **Network & time** | `ip` `geo` `time` `cron` `hyperplanning` |
|
|
86
|
+
| **Stateful** | `chat` `tic_tac_toe` |
|
|
87
87
|
|
|
88
88
|
The six names in **bold** are namespaces — they group related functions, called as `namespace.method()`:
|
|
89
89
|
|
|
@@ -112,6 +112,7 @@ Two names differ from their HTTP endpoint, because `case` is a reserved word and
|
|
|
112
112
|
```js
|
|
113
113
|
import {
|
|
114
114
|
asymmetric,
|
|
115
|
+
asymmetricAsync,
|
|
115
116
|
caseConvert,
|
|
116
117
|
chart,
|
|
117
118
|
csv,
|
|
@@ -130,6 +131,10 @@ const { result: encrypted } = asymmetric('encrypt', { text: 'secret message', pu
|
|
|
130
131
|
const { result: decrypted } = asymmetric('decrypt', { text: encrypted, privateKey });
|
|
131
132
|
console.log(decrypted); // 'secret message'
|
|
132
133
|
|
|
134
|
+
// Same result, but the key pair is generated off the main thread
|
|
135
|
+
const keys = await asymmetricAsync('keygen', { modulusLength: 4096 });
|
|
136
|
+
console.log(keys.modulusLength); // 4096
|
|
137
|
+
|
|
133
138
|
// AES-256-GCM symmetric encryption, key derived with scrypt
|
|
134
139
|
const { result: blob } = symmetric('encrypt', 'secret message', 'a-strong-key');
|
|
135
140
|
const { result: plain } = symmetric('decrypt', blob, 'a-strong-key');
|
|
@@ -214,13 +219,13 @@ $ npm run build && npm start
|
|
|
214
219
|
```
|
|
215
220
|
|
|
216
221
|
```console
|
|
217
|
-
> @moxon/api@6.
|
|
222
|
+
> @moxon/api@6.2.0 build
|
|
218
223
|
> npm run clean && tsc
|
|
219
224
|
|
|
220
|
-
> @moxon/api@6.
|
|
225
|
+
> @moxon/api@6.2.0 clean
|
|
221
226
|
> node -e "require('node:fs').rmSync('dist', { recursive: true, force: true })"
|
|
222
227
|
|
|
223
|
-
> @moxon/api@6.
|
|
228
|
+
> @moxon/api@6.2.0 start
|
|
224
229
|
> node dist/app.js
|
|
225
230
|
|
|
226
231
|
API is running on
|
|
@@ -248,7 +253,7 @@ Every setting is optional and read from the environment; a `.env` file at the pr
|
|
|
248
253
|
| `INSTANCE_CREATED` | — | Launch date reported by `/:version/infos` |
|
|
249
254
|
| `LOGS_TOKEN` | — | Value required in the `X-Logs-Token` header to read `/logs`; the route answers 404 while unset |
|
|
250
255
|
| `CHALLENGE_SECRET` | random | Key signing the captcha and proof-of-work tokens; a random one is generated at startup while unset |
|
|
251
|
-
| `TRUSTED_PROXIES` | one hop | CIDR blocks
|
|
256
|
+
| `TRUSTED_PROXIES` | one hop | CIDR blocks or `loopback` / `linklocal` / `uniquelocal`, space or comma separated; unset, exactly one reverse proxy is assumed and a warning is logged |
|
|
252
257
|
| `GLOBAL_LIMIT` | `50000` | Requests per hour accepted across the whole instance |
|
|
253
258
|
| `DEFAULT_LIMIT` | `2000` | Per-client requests per hour |
|
|
254
259
|
| `DEFAULT_BURST` | `50` | Per-client requests per 10-second window |
|
|
@@ -257,7 +262,9 @@ The three metadata variables are omitted from responses when unset, so an instan
|
|
|
257
262
|
|
|
258
263
|
Higher quotas can be granted per client: `ADVANCED_`, `PRO_` and `BUSINESS_` variants of `_LIMIT` and `_BURST` define the tiers, and the matching `*_TOKEN_LIST` variables hold the space-separated bearer tokens that map to them. A client's tier and quota are reported by `GET /auth`.
|
|
259
264
|
|
|
260
|
-
> _Rate-limit counters live in process memory, so each instance of a multi-instance deployment counts separately._
|
|
265
|
+
> _Rate-limit counters live in process memory, so each instance of a multi-instance deployment counts separately. Clients are counted by address: an IPv4-mapped IPv6 address counts as its IPv4 form and any other IPv6 address as its `/64` block, while all the `/64` blocks of one `/48` network share four times the per-client hourly quota. A forwarded address that is not an IP address counts as the connecting peer. Only requests the per-client limits let through use the `GLOBAL_LIMIT` budget._
|
|
266
|
+
|
|
267
|
+
> _The one-hop default reads the client address from the last `X-Forwarded-For` entry, which is right behind a single reverse proxy such as nginx or Caddy. Exposed directly, callers can forge that header and pick their own address; behind several hops, every caller is counted as the nearest proxy. Set `TRUSTED_PROXIES` to match the actual chain._
|
|
261
268
|
|
|
262
269
|
> _Captcha and proof-of-work tokens are signed with `CHALLENGE_SECRET`. While it is unset each process invents its own key, so tokens stop verifying after a restart and are rejected by sibling instances — set it explicitly for any deployment running more than one process, with a full-entropy value such as `openssl rand -hex 32`._
|
|
263
270
|
|
package/dist/app.js
CHANGED
|
@@ -2,7 +2,7 @@ import express from 'express';
|
|
|
2
2
|
import { env } from './config/env.js';
|
|
3
3
|
import { endpoints } from './endpoints/index.js';
|
|
4
4
|
import { build } from './endpoints/router.js';
|
|
5
|
-
import { setupCors } from './middleware/cors.js';
|
|
5
|
+
import { setupCors, setupParsers } from './middleware/cors.js';
|
|
6
6
|
import { errorHandler } from './middleware/error.js';
|
|
7
7
|
import { jsonResponseMiddleware } from './middleware/json.js';
|
|
8
8
|
import { loggerMiddleware } from './middleware/logger.js';
|
|
@@ -15,12 +15,14 @@ import patchRoutes from './routes/patch.js';
|
|
|
15
15
|
import postRoutes from './routes/post.js';
|
|
16
16
|
import { error } from './utils/response.js';
|
|
17
17
|
const app = express();
|
|
18
|
-
//
|
|
18
|
+
// Security headers, CORS, static files
|
|
19
19
|
setupCors(app);
|
|
20
20
|
// Custom JSON response
|
|
21
21
|
app.use(jsonResponseMiddleware);
|
|
22
|
-
// Rate limiting
|
|
22
|
+
// Rate limiting, ahead of body parsing so malformed bodies are counted too
|
|
23
23
|
app.use(rateLimitMiddleware);
|
|
24
|
+
// Body parsing
|
|
25
|
+
setupParsers(app);
|
|
24
26
|
// Request logging
|
|
25
27
|
app.use(loggerMiddleware);
|
|
26
28
|
// Root routes (before version check)
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,OAAqD,MAAM,SAAS,CAAC;AAE5E,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
export declare const APP_VERSION: string;
|
|
2
2
|
export declare const DEFAULT_PORT = 3000;
|
|
3
3
|
export declare const START_TIME: number;
|
|
4
|
+
export declare const CHALLENGE_MAX_ATTEMPTS = 5;
|
|
4
5
|
export declare const CHALLENGE_TTL = 300000;
|
|
5
6
|
export declare const GAME_CLEANUP_TTL = 600000;
|
|
6
7
|
export declare const MAX_LOG_ENTRIES = 1000;
|
|
8
|
+
export declare const RATE_LIMIT_IPV6_NETWORK = 48;
|
|
9
|
+
export declare const RATE_LIMIT_IPV6_PREFIX = 64;
|
|
10
|
+
export declare const RATE_LIMIT_NETWORK_FACTOR = 4;
|
|
7
11
|
export declare const RATE_LIMIT_WINDOW = 10000;
|
|
8
12
|
export declare const RATE_LIMIT_MAX = 50;
|
|
9
13
|
export declare const SESSION_TTL = 3600000;
|
|
10
14
|
export declare const STATUS_MESSAGES: Record<number, string>;
|
|
11
15
|
export declare const EARTH_RADIUS_KM = 6371;
|
|
12
16
|
export declare const MAX_ADDRESS_COUNT = 10;
|
|
17
|
+
export declare const MAX_BARCODE_DATA_LENGTH = 128;
|
|
13
18
|
export declare const MAX_BASE_VALUE_LENGTH = 100;
|
|
19
|
+
export declare const MAX_CAPTCHA_TEXT_LENGTH = 32;
|
|
14
20
|
export declare const MAX_CHART_DATASETS = 5;
|
|
15
21
|
export declare const MAX_CHART_LABELS = 20;
|
|
22
|
+
export declare const MAX_CHAT_MESSAGES = 200;
|
|
16
23
|
export declare const MAX_CSV_LENGTH = 50000;
|
|
17
24
|
export declare const MAX_CSV_ROWS = 1000;
|
|
18
25
|
export declare const MAX_CREDIT_COUNT = 10;
|
|
26
|
+
export declare const MAX_CONCURRENT_KEYGENS = 2;
|
|
19
27
|
export declare const MAX_COUNTDOWN_YEARS = 100;
|
|
28
|
+
export declare const MAX_CRON_DURATION = 250;
|
|
29
|
+
export declare const MAX_CRON_DURATION_V4 = 1000;
|
|
30
|
+
export declare const MAX_CRON_GAP: number;
|
|
20
31
|
export declare const MAX_CRON_ITERATIONS: number;
|
|
21
32
|
export declare const MAX_CRON_RESULTS = 20;
|
|
22
33
|
export declare const MAX_DIFF_LENGTH = 10000;
|
|
@@ -25,6 +36,10 @@ export declare const MAX_EXPR_DEPTH = 100;
|
|
|
25
36
|
export declare const MAX_EXPR_LENGTH = 500;
|
|
26
37
|
export declare const MAX_FACTORIAL = 170;
|
|
27
38
|
export declare const MAX_GCD_VALUE = 100000;
|
|
39
|
+
export declare const ICS_FETCH_TIMEOUT = 10000;
|
|
40
|
+
export declare const MAX_ICS_BYTES: number;
|
|
41
|
+
export declare const MAX_ICS_EVENTS = 5000;
|
|
42
|
+
export declare const MAX_ID_LENGTH = 256;
|
|
28
43
|
export declare const MAX_JWT_LENGTH = 8192;
|
|
29
44
|
export declare const MAX_LEVENSHTEIN_LENGTH = 1000;
|
|
30
45
|
export declare const MIN_PASSWORD_LENGTH = 8;
|
|
@@ -34,15 +49,22 @@ export declare const MAX_MATRIX_SIZE = 20;
|
|
|
34
49
|
export declare const MAX_PATTERN_LENGTH = 200;
|
|
35
50
|
export declare const MAX_POW_DIFFICULTY = 6;
|
|
36
51
|
export declare const MAX_PRIME_LIST = 10000;
|
|
52
|
+
export declare const MAX_PRIVATE_CHATS = 1000;
|
|
37
53
|
export declare const POW_DEFAULT_DIFFICULTY = 4;
|
|
54
|
+
export declare const MAX_QRCODE_ICON_PIXELS = 16000000;
|
|
38
55
|
export declare const MAX_QRCODE_LOGO_BYTES: number;
|
|
56
|
+
export declare const QRCODE_ICON_TIMEOUT = 5000;
|
|
39
57
|
export declare const MAX_READ_LENGTH = 50000;
|
|
40
58
|
export declare const MAX_REGEX_MATCHES = 100;
|
|
59
|
+
export declare const REGEX_TIMEOUT = 25;
|
|
60
|
+
export declare const MAX_REMOTE_REDIRECTS = 10;
|
|
41
61
|
export declare const MAX_RSA_MODULUS = 4096;
|
|
42
62
|
export declare const MAX_SEMVER_LENGTH = 256;
|
|
43
63
|
export declare const MAX_STRING_LENGTH = 1000;
|
|
64
|
+
export declare const MAX_TIMESTAMP_LENGTH = 128;
|
|
44
65
|
export declare const MIN_TOKEN_LENGTH = 12;
|
|
45
66
|
export declare const MAX_TOKEN_LENGTH = 4096;
|
|
46
67
|
export declare const MAX_URL_LENGTH = 2048;
|
|
68
|
+
export declare const MAX_USERNAME_LENGTH = 100;
|
|
47
69
|
export declare const MAX_UUID_COUNT = 50;
|
|
48
70
|
export declare const ROMAN_VALUES: [number, string][];
|
package/dist/constants.js
CHANGED
|
@@ -4,9 +4,13 @@ export const APP_VERSION = pkg.version;
|
|
|
4
4
|
export const DEFAULT_PORT = 3000;
|
|
5
5
|
export const START_TIME = Date.now();
|
|
6
6
|
// Server
|
|
7
|
+
export const CHALLENGE_MAX_ATTEMPTS = 5;
|
|
7
8
|
export const CHALLENGE_TTL = 300_000;
|
|
8
9
|
export const GAME_CLEANUP_TTL = 600_000;
|
|
9
10
|
export const MAX_LOG_ENTRIES = 1000;
|
|
11
|
+
export const RATE_LIMIT_IPV6_NETWORK = 48;
|
|
12
|
+
export const RATE_LIMIT_IPV6_PREFIX = 64;
|
|
13
|
+
export const RATE_LIMIT_NETWORK_FACTOR = 4;
|
|
10
14
|
export const RATE_LIMIT_WINDOW = 10_000;
|
|
11
15
|
export const RATE_LIMIT_MAX = 50;
|
|
12
16
|
export const SESSION_TTL = 3_600_000;
|
|
@@ -22,13 +26,20 @@ export const STATUS_MESSAGES = {
|
|
|
22
26
|
// Modules
|
|
23
27
|
export const EARTH_RADIUS_KM = 6371;
|
|
24
28
|
export const MAX_ADDRESS_COUNT = 10;
|
|
29
|
+
export const MAX_BARCODE_DATA_LENGTH = 128;
|
|
25
30
|
export const MAX_BASE_VALUE_LENGTH = 100;
|
|
31
|
+
export const MAX_CAPTCHA_TEXT_LENGTH = 32;
|
|
26
32
|
export const MAX_CHART_DATASETS = 5;
|
|
27
33
|
export const MAX_CHART_LABELS = 20;
|
|
34
|
+
export const MAX_CHAT_MESSAGES = 200;
|
|
28
35
|
export const MAX_CSV_LENGTH = 50_000;
|
|
29
36
|
export const MAX_CSV_ROWS = 1000;
|
|
30
37
|
export const MAX_CREDIT_COUNT = 10;
|
|
38
|
+
export const MAX_CONCURRENT_KEYGENS = 2;
|
|
31
39
|
export const MAX_COUNTDOWN_YEARS = 100;
|
|
40
|
+
export const MAX_CRON_DURATION = 250;
|
|
41
|
+
export const MAX_CRON_DURATION_V4 = 1000;
|
|
42
|
+
export const MAX_CRON_GAP = 401 * 366 * 86_400_000;
|
|
32
43
|
export const MAX_CRON_ITERATIONS = 365 * 24 * 60;
|
|
33
44
|
export const MAX_CRON_RESULTS = 20;
|
|
34
45
|
export const MAX_DIFF_LENGTH = 10_000;
|
|
@@ -37,6 +48,10 @@ export const MAX_EXPR_DEPTH = 100;
|
|
|
37
48
|
export const MAX_EXPR_LENGTH = 500;
|
|
38
49
|
export const MAX_FACTORIAL = 170;
|
|
39
50
|
export const MAX_GCD_VALUE = 100_000;
|
|
51
|
+
export const ICS_FETCH_TIMEOUT = 10_000;
|
|
52
|
+
export const MAX_ICS_BYTES = 1024 * 1024;
|
|
53
|
+
export const MAX_ICS_EVENTS = 5000;
|
|
54
|
+
export const MAX_ID_LENGTH = 256;
|
|
40
55
|
export const MAX_JWT_LENGTH = 8192;
|
|
41
56
|
export const MAX_LEVENSHTEIN_LENGTH = 1000;
|
|
42
57
|
export const MIN_PASSWORD_LENGTH = 8;
|
|
@@ -46,16 +61,23 @@ export const MAX_MATRIX_SIZE = 20;
|
|
|
46
61
|
export const MAX_PATTERN_LENGTH = 200;
|
|
47
62
|
export const MAX_POW_DIFFICULTY = 6;
|
|
48
63
|
export const MAX_PRIME_LIST = 10_000;
|
|
64
|
+
export const MAX_PRIVATE_CHATS = 1000;
|
|
49
65
|
export const POW_DEFAULT_DIFFICULTY = 4;
|
|
66
|
+
export const MAX_QRCODE_ICON_PIXELS = 16_000_000;
|
|
50
67
|
export const MAX_QRCODE_LOGO_BYTES = 2 * 1024 * 1024;
|
|
68
|
+
export const QRCODE_ICON_TIMEOUT = 5000;
|
|
51
69
|
export const MAX_READ_LENGTH = 50_000;
|
|
52
70
|
export const MAX_REGEX_MATCHES = 100;
|
|
71
|
+
export const REGEX_TIMEOUT = 25;
|
|
72
|
+
export const MAX_REMOTE_REDIRECTS = 10;
|
|
53
73
|
export const MAX_RSA_MODULUS = 4096;
|
|
54
74
|
export const MAX_SEMVER_LENGTH = 256;
|
|
55
75
|
export const MAX_STRING_LENGTH = 1000;
|
|
76
|
+
export const MAX_TIMESTAMP_LENGTH = 128;
|
|
56
77
|
export const MIN_TOKEN_LENGTH = 12;
|
|
57
78
|
export const MAX_TOKEN_LENGTH = 4096;
|
|
58
79
|
export const MAX_URL_LENGTH = 2048;
|
|
80
|
+
export const MAX_USERNAME_LENGTH = 100;
|
|
59
81
|
export const MAX_UUID_COUNT = 50;
|
|
60
82
|
export const ROMAN_VALUES = [
|
|
61
83
|
[1000, 'M'],
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,17 @@
|
|
|
1
1
|
import { type Express } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Applies the proxy setting, the security headers, CORS and the robots.txt route.
|
|
4
|
+
*
|
|
5
|
+
* The security headers come first so that every response carries them,
|
|
6
|
+
* preflights and errors included. Body parsing is mounted separately by
|
|
7
|
+
* setupParsers, after the rate limiter.
|
|
8
|
+
*
|
|
9
|
+
* @param app - Express application to configure
|
|
10
|
+
*/
|
|
2
11
|
export declare function setupCors(app: Express): void;
|
|
12
|
+
/**
|
|
13
|
+
* Mounts the URL-encoded and JSON body parsers, both capped at 10 KB.
|
|
14
|
+
*
|
|
15
|
+
* @param app - Express application to configure
|
|
16
|
+
*/
|
|
17
|
+
export declare function setupParsers(app: Express): void;
|
package/dist/middleware/cors.js
CHANGED
|
@@ -5,8 +5,25 @@ import { fileURLToPath } from 'url';
|
|
|
5
5
|
import { env } from '../config/env.js';
|
|
6
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
7
|
const __dirname = dirname(__filename);
|
|
8
|
+
/**
|
|
9
|
+
* Applies the proxy setting, the security headers, CORS and the robots.txt route.
|
|
10
|
+
*
|
|
11
|
+
* The security headers come first so that every response carries them,
|
|
12
|
+
* preflights and errors included. Body parsing is mounted separately by
|
|
13
|
+
* setupParsers, after the rate limiter.
|
|
14
|
+
*
|
|
15
|
+
* @param app - Express application to configure
|
|
16
|
+
*/
|
|
8
17
|
export function setupCors(app) {
|
|
9
18
|
app.set('trust proxy', env.TRUSTED_PROXIES ?? 1);
|
|
19
|
+
if (!env.TRUSTED_PROXIES && process.env.NODE_ENV !== 'test') {
|
|
20
|
+
console.warn('TRUSTED_PROXIES is unset: client addresses are read assuming exactly one reverse proxy in front of the API.');
|
|
21
|
+
}
|
|
22
|
+
app.use((_req, res, next) => {
|
|
23
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
24
|
+
res.setHeader('X-Frame-Options', 'DENY');
|
|
25
|
+
next();
|
|
26
|
+
});
|
|
10
27
|
app.use(cors({
|
|
11
28
|
methods: ['GET', 'POST', 'PATCH', 'DELETE', 'OPTIONS'],
|
|
12
29
|
exposedHeaders: [
|
|
@@ -18,13 +35,15 @@ export function setupCors(app) {
|
|
|
18
35
|
'Retry-After',
|
|
19
36
|
],
|
|
20
37
|
}));
|
|
38
|
+
app.use('/robots.txt', express.static(join(__dirname, '..', '..', 'robots.txt')));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Mounts the URL-encoded and JSON body parsers, both capped at 10 KB.
|
|
42
|
+
*
|
|
43
|
+
* @param app - Express application to configure
|
|
44
|
+
*/
|
|
45
|
+
export function setupParsers(app) {
|
|
21
46
|
app.use(express.urlencoded({ extended: true, limit: '10kb' }));
|
|
22
47
|
app.use(express.json({ limit: '10kb' }));
|
|
23
|
-
app.use((_req, res, next) => {
|
|
24
|
-
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
25
|
-
res.setHeader('X-Frame-Options', 'DENY');
|
|
26
|
-
next();
|
|
27
|
-
});
|
|
28
|
-
app.use('/robots.txt', express.static(join(__dirname, '..', '..', 'robots.txt')));
|
|
29
48
|
}
|
|
30
49
|
//# sourceMappingURL=cors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,OAAyB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,UAAU,SAAS,CAAC,GAAY;IAClC,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,OAAyB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,GAAY;IAClC,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC1D,OAAO,CAAC,IAAI,CACR,6GAA6G,CAChH,CAAC;IACN,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAC;QACnD,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QACzC,IAAI,EAAE,CAAC;IACX,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CACH,IAAI,CAAC;QACD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC;QACtD,cAAc,EAAE;YACZ,gBAAgB;YAChB,iBAAiB;YACjB,mBAAmB;YACnB,uBAAuB;YACvB,mBAAmB;YACnB,aAAa;SAChB;KACJ,CAAC,CACL,CAAC;IAEF,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;AACtF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAAY;IACrC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/D,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -1,2 +1,54 @@
|
|
|
1
1
|
import type { NextFunction, Request, Response } from 'express';
|
|
2
|
-
|
|
2
|
+
import type { IpLimits } from '../types/storage.js';
|
|
3
|
+
export interface RateLimiterOptions {
|
|
4
|
+
now?: () => number;
|
|
5
|
+
burst?: boolean;
|
|
6
|
+
global?: number;
|
|
7
|
+
limits?: IpLimits;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Derives the key a client is rate limited under.
|
|
11
|
+
*
|
|
12
|
+
* An IPv4-mapped IPv6 address counts as its IPv4 form, so a dual-stack socket
|
|
13
|
+
* and a proxy header naming the same caller share one quota. Any other IPv6
|
|
14
|
+
* address counts as its /64 prefix, the block a single subscriber is usually
|
|
15
|
+
* handed, so rotating addresses inside it does not reset the quota.
|
|
16
|
+
*
|
|
17
|
+
* @param ip - Client address as resolved by Express
|
|
18
|
+
* @returns The IPv4 address, the IPv6 prefix, or the input unchanged when it is not an IP address
|
|
19
|
+
*/
|
|
20
|
+
export declare function clientKey(ip: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Derives the IPv6 network a client belongs to, the largest block one subscriber is usually handed.
|
|
23
|
+
*
|
|
24
|
+
* @param ip - Client address as resolved by Express
|
|
25
|
+
* @returns The /48 prefix of an IPv6 address, or null for IPv4, IPv4-mapped and non-IP input
|
|
26
|
+
*/
|
|
27
|
+
export declare function networkKey(ip: string): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Drops the hourly counters left from past hours and the burst timestamps outside the window.
|
|
30
|
+
*
|
|
31
|
+
* @param limits - Hourly counters, keyed by client
|
|
32
|
+
* @param bursts - Timestamps of recent requests, keyed by client
|
|
33
|
+
* @param now - Current time in milliseconds
|
|
34
|
+
* @param networks - Admitted requests per IPv6 network, with the epoch hour they were counted in
|
|
35
|
+
*/
|
|
36
|
+
export declare function sweep(limits: IpLimits, bursts: Map<string, number[]>, now: number, networks?: Map<string, {
|
|
37
|
+
hour: number;
|
|
38
|
+
count: number;
|
|
39
|
+
}>): void;
|
|
40
|
+
/**
|
|
41
|
+
* Builds a rate limiting middleware with its own counters.
|
|
42
|
+
*
|
|
43
|
+
* A request is checked against the instance-wide hourly budget, then against
|
|
44
|
+
* the burst window and the hourly quota of its plan for its client key, and an
|
|
45
|
+
* IPv6 client also against a larger quota for its whole /48 network. Only a
|
|
46
|
+
* request that passes every check uses the instance-wide and network budgets,
|
|
47
|
+
* so a client being refused cannot exhaust them for everybody else. A forged
|
|
48
|
+
* proxy header that is not an IP address counts as the socket peer instead.
|
|
49
|
+
*
|
|
50
|
+
* @param options - Clock, burst switch, instance-wide budget and hourly store, each with a production default
|
|
51
|
+
* @returns An Express middleware enforcing the limits
|
|
52
|
+
*/
|
|
53
|
+
export declare function createRateLimiter(options?: RateLimiterOptions): (req: Request, res: Response, next: NextFunction) => void;
|
|
54
|
+
export declare const rateLimitMiddleware: (req: Request, res: Response, next: NextFunction) => void;
|