@fluojs/throttler 1.0.0-beta.4 → 1.0.0-beta.5
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.ko.md +16 -0
- package/README.md +16 -0
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +2 -0
- package/package.json +5 -5
package/README.ko.md
CHANGED
|
@@ -76,6 +76,7 @@ import { ThrottlerModule, RedisThrottlerStore } from '@fluojs/throttler';
|
|
|
76
76
|
import { REDIS_CLIENT } from '@fluojs/redis';
|
|
77
77
|
|
|
78
78
|
// 프로바이더 또는 모듈 팩토리 내부에서
|
|
79
|
+
const redisClient = await container.resolve(REDIS_CLIENT);
|
|
79
80
|
const redisStore = new RedisThrottlerStore(redisClient);
|
|
80
81
|
|
|
81
82
|
ThrottlerModule.forRoot({
|
|
@@ -85,10 +86,14 @@ ThrottlerModule.forRoot({
|
|
|
85
86
|
});
|
|
86
87
|
```
|
|
87
88
|
|
|
89
|
+
`ThrottlerStore` 계약을 구현한 객체도 `store` 옵션으로 직접 전달할 수 있습니다.
|
|
90
|
+
|
|
88
91
|
### 커스텀 키 생성
|
|
89
92
|
|
|
90
93
|
기본적으로 throttler는 raw socket `remoteAddress`만으로 클라이언트 식별자를 해석합니다. 배포가 `Forwarded`, `X-Forwarded-For`, `X-Real-IP`를 덮어쓰는 신뢰 가능한 리버스 프록시 뒤에 있다면 `trustProxyHeaders: true`로 명시적으로 opt-in 하세요. 신뢰 가능한 소켓 식별자나 프록시 식별자가 없으면 서로 다른 호출자를 같은 버킷으로 합치지 않도록 예외를 던집니다. API 키나 사용자 ID 등 다른 식별자를 사용하도록 커스터마이징할 수도 있습니다.
|
|
91
94
|
|
|
95
|
+
카운터는 route identity와 client identity로 구분됩니다. route 부분에는 method, path, version, handler identity가 포함되므로 서로 다른 핸들러가 실수로 같은 버킷을 공유하지 않습니다. 요청이 거부되면 `ThrottlerGuard`는 `429`를 반환하고 `Retry-After`를 설정합니다.
|
|
96
|
+
|
|
92
97
|
```typescript
|
|
93
98
|
ThrottlerModule.forRoot({
|
|
94
99
|
ttl: 60,
|
|
@@ -120,6 +125,8 @@ ThrottlerModule.forRoot({
|
|
|
120
125
|
- `ThrottlerModule.forRoot(options)`: throttler 옵션, 저장소, `ThrottlerGuard`를 모듈 그래프에 제공합니다.
|
|
121
126
|
- 패키지 수준 등록은 `ThrottlerModule.forRoot(options)`를 통해 지원합니다. 내부 프로바이더 조합 헬퍼는 공개 계약에 포함되지 않습니다.
|
|
122
127
|
|
|
128
|
+
`ttl`과 `limit`은 양의 finite integer여야 합니다. `store`, `trustProxyHeaders`, `keyGenerator`로 persistence와 client identity를 조정할 수 있습니다.
|
|
129
|
+
|
|
123
130
|
### 데코레이터
|
|
124
131
|
- `@Throttle({ ttl, limit })`: 클래스나 메서드에 특정 속도 제한을 설정합니다.
|
|
125
132
|
- `@SkipThrottle()`: 클래스나 메서드에 대해 속도 제한을 비활성화합니다.
|
|
@@ -130,6 +137,13 @@ ThrottlerModule.forRoot({
|
|
|
130
137
|
### 저장소(Store)
|
|
131
138
|
- `createMemoryThrottlerStore()`: 간단한 메모리 내 저장소를 생성합니다 (기본값).
|
|
132
139
|
- `RedisThrottlerStore`: Redis용 저장소 어댑터입니다.
|
|
140
|
+
- `ThrottlerStore`: custom store를 위한 공개 계약입니다.
|
|
141
|
+
|
|
142
|
+
### status와 diagnostics
|
|
143
|
+
- `createThrottlerPlatformStatusSnapshot(...)`: 플랫폼 status snapshot을 생성합니다.
|
|
144
|
+
- `createThrottlerPlatformDiagnosticIssues(...)`: 잘못된 throttler 상태에 대한 diagnostic issue를 생성합니다.
|
|
145
|
+
|
|
146
|
+
메서드 수준 `@Throttle(...)`은 클래스 수준 설정보다 우선하고, 클래스 수준 설정은 모듈 기본값보다 우선합니다. `@SkipThrottle()`은 클래스나 메서드 수준 모두에서 throttling을 우회합니다.
|
|
133
147
|
|
|
134
148
|
## 관련 패키지
|
|
135
149
|
|
|
@@ -140,3 +154,5 @@ ThrottlerModule.forRoot({
|
|
|
140
154
|
|
|
141
155
|
- `packages/throttler/src/module.test.ts`: 모듈 설정 및 데코레이터 오버라이드 테스트.
|
|
142
156
|
- `packages/throttler/src/guard.ts`: 요청 제한 및 헤더 관리 코어 로직.
|
|
157
|
+
- `packages/throttler/src/redis-store.test.ts`: Redis store 계약과 server-time 동작.
|
|
158
|
+
- `packages/throttler/src/status.test.ts`: status 및 diagnostic helper 동작.
|
package/README.md
CHANGED
|
@@ -76,6 +76,7 @@ import { ThrottlerModule, RedisThrottlerStore } from '@fluojs/throttler';
|
|
|
76
76
|
import { REDIS_CLIENT } from '@fluojs/redis';
|
|
77
77
|
|
|
78
78
|
// Inside a provider or module factory
|
|
79
|
+
const redisClient = await container.resolve(REDIS_CLIENT);
|
|
79
80
|
const redisStore = new RedisThrottlerStore(redisClient);
|
|
80
81
|
|
|
81
82
|
ThrottlerModule.forRoot({
|
|
@@ -85,10 +86,14 @@ ThrottlerModule.forRoot({
|
|
|
85
86
|
});
|
|
86
87
|
```
|
|
87
88
|
|
|
89
|
+
You can also pass any object that implements the `ThrottlerStore` contract through the `store` option.
|
|
90
|
+
|
|
88
91
|
### Custom Key Generation
|
|
89
92
|
|
|
90
93
|
By default, the throttler resolves client identity from the raw socket `remoteAddress` only. If your deployment sits behind a trusted reverse proxy that rewrites `Forwarded`, `X-Forwarded-For`, or `X-Real-IP`, opt in with `trustProxyHeaders: true`. If no trusted socket or proxy identity is available, it throws instead of collapsing unrelated callers into a shared bucket. You can also customize this to use API keys, user IDs, or other identifiers.
|
|
91
94
|
|
|
95
|
+
Counters are scoped by route identity and client identity. The route portion includes method, path, version, and handler identity so different handlers do not share buckets accidentally. When a request is rejected, `ThrottlerGuard` returns `429` and sets `Retry-After`.
|
|
96
|
+
|
|
92
97
|
```typescript
|
|
93
98
|
ThrottlerModule.forRoot({
|
|
94
99
|
ttl: 60,
|
|
@@ -120,6 +125,8 @@ ThrottlerModule.forRoot({
|
|
|
120
125
|
- `ThrottlerModule.forRoot(options)`: Provides throttler options, storage, and `ThrottlerGuard` to the module graph.
|
|
121
126
|
- Package-level registration is supported through `ThrottlerModule.forRoot(options)`. Internal provider-composition helpers are not part of the public contract.
|
|
122
127
|
|
|
128
|
+
`ttl` and `limit` must be positive finite integers. `store`, `trustProxyHeaders`, and `keyGenerator` customize persistence and client identity.
|
|
129
|
+
|
|
123
130
|
### Decorators
|
|
124
131
|
- `@Throttle({ ttl, limit })`: Sets a specific rate limit for a class or method.
|
|
125
132
|
- `@SkipThrottle()`: Disables throttling for a class or method.
|
|
@@ -130,6 +137,13 @@ ThrottlerModule.forRoot({
|
|
|
130
137
|
### Stores
|
|
131
138
|
- `createMemoryThrottlerStore()`: Creates a simple in-memory store (default).
|
|
132
139
|
- `RedisThrottlerStore`: Store adapter for Redis.
|
|
140
|
+
- `ThrottlerStore`: Public contract for custom stores.
|
|
141
|
+
|
|
142
|
+
### Status and diagnostics
|
|
143
|
+
- `createThrottlerPlatformStatusSnapshot(...)`: Creates a platform status snapshot.
|
|
144
|
+
- `createThrottlerPlatformDiagnosticIssues(...)`: Creates diagnostic issues for invalid throttler state.
|
|
145
|
+
|
|
146
|
+
Method-level `@Throttle(...)` overrides class-level settings, class-level settings override module defaults, and `@SkipThrottle()` bypasses throttling at either class or method level.
|
|
133
147
|
|
|
134
148
|
## Related Packages
|
|
135
149
|
|
|
@@ -140,3 +154,5 @@ ThrottlerModule.forRoot({
|
|
|
140
154
|
|
|
141
155
|
- `packages/throttler/src/module.test.ts`: Tests for module configuration and decorator overrides.
|
|
142
156
|
- `packages/throttler/src/guard.ts`: The core logic for request throttling and header management.
|
|
157
|
+
- `packages/throttler/src/redis-store.test.ts`: Redis store contract and server-time behavior.
|
|
158
|
+
- `packages/throttler/src/status.test.ts`: Status and diagnostic helper behavior.
|
package/dist/decorators.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAG1D,0FAA0F;AAC1F,eAAO,MAAM,wBAAwB,eAAoC,CAAC;AAM1E,KAAK,mBAAmB,GAAG,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AACxD,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACjG,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAC1F,KAAK,0BAA0B,GAAG,wBAAwB,GAAG,yBAAyB,CAAC;AAkCvF;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,uBAAuB,GAAG,0BAA0B,CAUrF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,0BAA0B,CAUzD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,GAAG,uBAAuB,GAAG,SAAS,CAGjG;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAEzE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,mBAAmB,GAAG,uBAAuB,GAAG,SAAS,CAGtG;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAE9E"}
|
package/dist/decorators.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ensureMetadataSymbol } from '@fluojs/core/internal';
|
|
1
2
|
import { validateThrottleOptions } from './validation.js';
|
|
2
3
|
|
|
3
4
|
/** Shared controller metadata key used to store per-route throttling metadata records. */
|
|
@@ -6,6 +7,7 @@ const throttleKey = Symbol.for('fluo.throttler.throttle');
|
|
|
6
7
|
const skipThrottleKey = Symbol.for('fluo.throttler.skip');
|
|
7
8
|
const classThrottleKey = Symbol.for('fluo.throttler.class-throttle');
|
|
8
9
|
const classSkipThrottleKey = Symbol.for('fluo.throttler.class-skip');
|
|
10
|
+
ensureMetadataSymbol();
|
|
9
11
|
function getMetadataBag(metadata) {
|
|
10
12
|
return metadata;
|
|
11
13
|
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"redis",
|
|
10
10
|
"decorator"
|
|
11
11
|
],
|
|
12
|
-
"version": "1.0.0-beta.
|
|
12
|
+
"version": "1.0.0-beta.5",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@fluojs/core": "^1.0.0-beta.
|
|
40
|
-
"@fluojs/di": "^1.0.0-beta.
|
|
41
|
-
"@fluojs/
|
|
42
|
-
"@fluojs/
|
|
39
|
+
"@fluojs/core": "^1.0.0-beta.4",
|
|
40
|
+
"@fluojs/di": "^1.0.0-beta.6",
|
|
41
|
+
"@fluojs/http": "^1.0.0-beta.10",
|
|
42
|
+
"@fluojs/runtime": "^1.0.0-beta.11"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"ioredis": "^5.0.0",
|