@atproto/xrpc-server 0.11.0 → 0.11.2
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 +27 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/rate-limiter-http.d.ts +24 -0
- package/dist/rate-limiter-http.d.ts.map +1 -0
- package/dist/rate-limiter-http.js +49 -0
- package/dist/rate-limiter-http.js.map +1 -0
- package/dist/rate-limiter.d.ts +32 -42
- package/dist/rate-limiter.d.ts.map +1 -1
- package/dist/rate-limiter.js +29 -75
- package/dist/rate-limiter.js.map +1 -1
- package/dist/server.d.ts +4 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +26 -7
- package/dist/server.js.map +1 -1
- package/dist/stream/frames.d.ts +3 -3
- package/dist/stream/frames.d.ts.map +1 -1
- package/dist/stream/logger.d.ts.map +1 -1
- package/dist/stream/server.d.ts.map +1 -1
- package/dist/stream/stream.d.ts +1 -1
- package/dist/stream/subscription.d.ts.map +1 -1
- package/dist/stream/subscription.js.map +1 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js.map +1 -1
- package/package.json +15 -16
- package/src/rate-limiter-http.ts +82 -0
- package/src/rate-limiter.ts +68 -156
- package/src/server.ts +49 -13
- package/tsconfig.build.json +2 -2
- package/tsconfig.build.tsbuildinfo +1 -1
- package/tsconfig.json +2 -2
- package/tsconfig.tests.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @atproto/xrpc-server
|
|
2
2
|
|
|
3
|
+
## 0.11.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#4967](https://github.com/bluesky-social/atproto/pull/4967) [`9fc720c`](https://github.com/bluesky-social/atproto/commit/9fc720ce75f3ee88a5e48a9be919b07c7647f6f5) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Use TypeScript 7 to build package
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`9fc720c`](https://github.com/bluesky-social/atproto/commit/9fc720ce75f3ee88a5e48a9be919b07c7647f6f5)]:
|
|
10
|
+
- @atproto/lex-client@0.1.4
|
|
11
|
+
- @atproto/lex-schema@0.1.4
|
|
12
|
+
- @atproto/lex-cbor@0.1.1
|
|
13
|
+
- @atproto/lex-data@0.1.2
|
|
14
|
+
- @atproto/lex-json@0.1.1
|
|
15
|
+
- @atproto/ws-client@0.1.1
|
|
16
|
+
- @atproto/lexicon@0.7.2
|
|
17
|
+
- @atproto/common@0.6.3
|
|
18
|
+
- @atproto/crypto@0.5.1
|
|
19
|
+
- @atproto/xrpc@0.8.1
|
|
20
|
+
|
|
21
|
+
## 0.11.1
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- [#4969](https://github.com/bluesky-social/atproto/pull/4969) [`57ecbda`](https://github.com/bluesky-social/atproto/commit/57ecbdac3eb14fdbc853456371e84a5098e91c4b) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Uses the http res's log Pino logger upon rate limit computation error, allowing to log the failure in the context of an http request
|
|
26
|
+
|
|
27
|
+
- Updated dependencies [[`482767c`](https://github.com/bluesky-social/atproto/commit/482767c4bcce95aa390b2992b028fd8e27d162b2)]:
|
|
28
|
+
- @atproto/lex-client@0.1.2
|
|
29
|
+
|
|
3
30
|
## 0.11.0
|
|
4
31
|
|
|
5
32
|
### Minor Changes
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAe,MAAM,qBAAqB,CAAA;AAG5D,KAAK,gBAAgB,GAAG;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAA;CACxB,CAAA;AAMD,KAAK,iBAAiB,GAAG;IACvB,GAAG,EAAE,SAAS,GAAG,GAAG,SAAS,IAAI,MAAM,EAAE,CAAA;IACzC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAe,MAAM,qBAAqB,CAAA;AAG5D,KAAK,gBAAgB,GAAG;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAA;CACxB,CAAA;AAMD,KAAK,iBAAiB,GAAG;IACvB,GAAG,EAAE,SAAS,GAAG,GAAG,SAAS,IAAI,MAAM,EAAE,CAAA;IACzC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,eAAO,MAAM,gBAAgB,WACnB,gBAAgB,KACvB,OAAO,CAAC,MAAM,CAsBhB,CAAA;AAED,eAAO,MAAM,wBAAwB,WAAkB,gBAAgB;;QAGxD,aAAa;;EAE3B,CAAA;AAMD,MAAM,MAAM,wBAAwB,GAAG,CACrC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,UAAU,EACpB,GAAG,EAAE,MAAM,KACR,OAAO,CAAC,OAAO,CAAC,CAAA;AAErB,eAAO,MAAM,SAAS,WACZ,MAAM,UACN,MAAM,GAAG,IAAI,EAAE,4CAA4C;KAC9D,MAAM,GAAG,IAAI,EAAE,uCAAuC;eAC5C,CACb,GAAG,EAAE,SAAS,GAAG,GAAG,SAAS,IAAI,MAAM,EAAE,EACzC,YAAY,EAAE,OAAO,KAClB,OAAO,CAAC,MAAM,CAAC,2BACI,wBAAwB,KAC/C,OAAO,CAAC,iBAAiB,CA+F3B,CAAA;AAED,eAAO,MAAM,4BAA4B,EAAE,wBAU1C,CAAA"}
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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","sourcesContent":["import * as common from '@atproto/common'\nimport { MINUTE } from '@atproto/common'\nimport * as crypto from '@atproto/crypto'\nimport { DidString, isDidString } from '@atproto/lex-schema'\nimport { AuthRequiredError } from './errors.js'\n\ntype ServiceJwtParams = {\n iss: string\n aud: string\n iat?: number\n exp?: number\n lxm: string | null\n keypair: crypto.Keypair\n}\n\ntype ServiceJwtHeaders = {\n alg: string\n} & Record<string, unknown>\n\ntype ServiceJwtPayload = {\n iss: DidString | `${DidString}#${string}`\n aud: string\n exp: number\n lxm?: string\n jti?: string\n}\n\nexport const createServiceJwt = async (\n params: ServiceJwtParams,\n): Promise<string> => {\n const { iss, aud, keypair } = params\n const iat = params.iat ?? Math.floor(Date.now() / 1e3)\n const exp = params.exp ?? iat + MINUTE / 1e3\n const lxm = params.lxm ?? undefined\n const jti = await crypto.randomStr(16, 'hex')\n const header = {\n typ: 'JWT',\n alg: keypair.jwtAlg,\n }\n const payload = common.noUndefinedVals({\n iat,\n iss,\n aud,\n exp,\n lxm,\n jti,\n })\n const toSignStr = `${jsonToB64Url(header)}.${jsonToB64Url(payload)}`\n const toSign = Buffer.from(toSignStr, 'utf8')\n const sig = Buffer.from(await keypair.sign(toSign))\n return `${toSignStr}.${sig.toString('base64url')}`\n}\n\nexport const createServiceAuthHeaders = async (params: ServiceJwtParams) => {\n const jwt = await createServiceJwt(params)\n return {\n headers: { authorization: `Bearer ${jwt}` },\n }\n}\n\nconst jsonToB64Url = (json: Record<string, unknown>): string => {\n return Buffer.from(JSON.stringify(json)).toString('base64url')\n}\n\nexport type VerifySignatureWithKeyFn = (\n key: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => Promise<boolean>\n\nexport const verifyJwt = async (\n jwtStr: string,\n ownDid: string | null, // null indicates to skip the audience check\n lxm: string | null, // null indicates to skip the lxm check\n getSigningKey: (\n iss: DidString | `${DidString}#${string}`,\n forceRefresh: boolean,\n ) => Promise<string>,\n verifySignatureWithKey: VerifySignatureWithKeyFn = cryptoVerifySignatureWithKey,\n): Promise<ServiceJwtPayload> => {\n const parts = jwtStr.split('.')\n if (parts.length !== 3) {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n\n const header = parseHeader(parts[0])\n\n // The spec does not describe what to do with the \"typ\" claim. We can,\n // however, forbid some values that are not compatible with our use case.\n if (\n // service tokens are not OAuth 2.0 access tokens\n // https://datatracker.ietf.org/doc/html/rfc9068\n header['typ'] === 'at+jwt' ||\n // \"refresh+jwt\" is a non-standard type used by the @atproto packages\n header['typ'] === 'refresh+jwt' ||\n // \"DPoP\" proofs are not meant to be used as service tokens\n // https://datatracker.ietf.org/doc/html/rfc9449\n header['typ'] === 'dpop+jwt'\n ) {\n throw new AuthRequiredError(\n `Invalid jwt type \"${header['typ']}\"`,\n 'BadJwtType',\n )\n }\n\n const payload = parsePayload(parts[1])\n const sig = parts[2]\n\n if (Date.now() / 1000 > payload.exp) {\n throw new AuthRequiredError('jwt expired', 'JwtExpired')\n }\n if (ownDid !== null && payload.aud !== ownDid) {\n throw new AuthRequiredError(\n 'jwt audience does not match service did',\n 'BadJwtAudience',\n )\n }\n if (lxm !== null && payload.lxm !== lxm) {\n throw new AuthRequiredError(\n payload.lxm !== undefined\n ? `bad jwt lexicon method (\"lxm\"). must match: ${lxm}`\n : `missing jwt lexicon method (\"lxm\"). must match: ${lxm}`,\n 'BadJwtLexiconMethod',\n )\n }\n if (!payload.iss || !isDidStringOrService(payload.iss)) {\n throw new AuthRequiredError('jwt iss is not a valid did', 'BadJwtIss')\n }\n\n const msgBytes = Buffer.from(parts.slice(0, 2).join('.'), 'utf8')\n const sigBytes = Buffer.from(sig, 'base64url')\n\n const signingKey = await getSigningKey(payload.iss, false)\n const { alg } = header\n\n let validSig: boolean\n try {\n validSig = await verifySignatureWithKey(signingKey, msgBytes, sigBytes, alg)\n } catch (err) {\n throw new AuthRequiredError(\n 'could not verify jwt signature',\n 'BadJwtSignature',\n )\n }\n\n if (!validSig) {\n // get fresh signing key in case it failed due to a recent rotation\n const freshSigningKey = await getSigningKey(payload.iss, true)\n try {\n validSig =\n freshSigningKey !== signingKey\n ? await verifySignatureWithKey(\n freshSigningKey,\n msgBytes,\n sigBytes,\n alg,\n )\n : false\n } catch (err) {\n throw new AuthRequiredError(\n 'could not verify jwt signature',\n 'BadJwtSignature',\n )\n }\n }\n\n if (!validSig) {\n throw new AuthRequiredError(\n 'jwt signature does not match jwt issuer',\n 'BadJwtSignature',\n )\n }\n\n return payload\n}\n\nexport const cryptoVerifySignatureWithKey: VerifySignatureWithKeyFn = async (\n key: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => {\n return crypto.verifySignature(key, msgBytes, sigBytes, {\n jwtAlg: alg,\n allowMalleableSig: true,\n })\n}\n\nconst parseB64UrlToJson = (b64: string) => {\n return JSON.parse(Buffer.from(b64, 'base64url').toString('utf8'))\n}\n\nconst parseHeader = (b64: string): ServiceJwtHeaders => {\n const header = parseB64UrlToJson(b64)\n if (!header || typeof header !== 'object' || typeof header.alg !== 'string') {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n return header\n}\n\nconst parsePayload = (b64: string): ServiceJwtPayload => {\n const payload = parseB64UrlToJson(b64)\n if (\n !payload ||\n typeof payload !== 'object' ||\n typeof payload.iss !== 'string' ||\n typeof payload.aud !== 'string' ||\n typeof payload.exp !== 'number' ||\n (payload.lxm && typeof payload.lxm !== 'string') ||\n (payload.nonce && typeof payload.nonce !== 'string')\n ) {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n return payload\n}\n\nfunction isDidStringOrService(\n value: string,\n): value is DidString | `${DidString}#${string}` {\n const hashIdx = value.indexOf('#')\n if (hashIdx === -1) {\n return isDidString(value)\n }\n\n // basic validation of the fragment part\n const fragmentLen = value.length - hashIdx - 1\n if (fragmentLen < 1 || value.includes('#', hashIdx + 1)) {\n return false\n }\n\n // Validate the did part\n const didPart = value.slice(0, hashIdx)\n return isDidString(didPart)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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","sourcesContent":["import * as common from '@atproto/common'\nimport { MINUTE } from '@atproto/common'\nimport * as crypto from '@atproto/crypto'\nimport { DidString, isDidString } from '@atproto/lex-schema'\nimport { AuthRequiredError } from './errors.js'\n\ntype ServiceJwtParams = {\n iss: string\n aud: string\n iat?: number\n exp?: number\n lxm: string | null\n keypair: crypto.Keypair\n}\n\ntype ServiceJwtHeaders = {\n alg: string\n} & Record<string, unknown>\n\ntype ServiceJwtPayload = {\n iss: DidString | `${DidString}#${string}`\n aud: string\n exp: number\n lxm?: string\n jti?: string\n}\n\nexport const createServiceJwt = async (\n params: ServiceJwtParams,\n): Promise<string> => {\n const { iss, aud, keypair } = params\n const iat = params.iat ?? Math.floor(Date.now() / 1e3)\n const exp = params.exp ?? iat + MINUTE / 1e3\n const lxm = params.lxm ?? undefined\n const jti = await crypto.randomStr(16, 'hex')\n const header = {\n typ: 'JWT',\n alg: keypair.jwtAlg,\n }\n const payload = common.noUndefinedVals({\n iat,\n iss,\n aud,\n exp,\n lxm,\n jti,\n })\n const toSignStr = `${jsonToB64Url(header)}.${jsonToB64Url(payload)}`\n const toSign = Buffer.from(toSignStr, 'utf8')\n const sig = Buffer.from(await keypair.sign(toSign))\n return `${toSignStr}.${sig.toString('base64url')}`\n}\n\nexport const createServiceAuthHeaders = async (params: ServiceJwtParams) => {\n const jwt = await createServiceJwt(params)\n return {\n headers: { authorization: `Bearer ${jwt}` },\n }\n}\n\nconst jsonToB64Url = (json: Record<string, unknown>): string => {\n return Buffer.from(JSON.stringify(json)).toString('base64url')\n}\n\nexport type VerifySignatureWithKeyFn = (\n key: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => Promise<boolean>\n\nexport const verifyJwt = async (\n jwtStr: string,\n ownDid: string | null, // null indicates to skip the audience check\n lxm: string | null, // null indicates to skip the lxm check\n getSigningKey: (\n iss: DidString | `${DidString}#${string}`,\n forceRefresh: boolean,\n ) => Promise<string>,\n verifySignatureWithKey: VerifySignatureWithKeyFn = cryptoVerifySignatureWithKey,\n): Promise<ServiceJwtPayload> => {\n const parts = jwtStr.split('.')\n if (parts.length !== 3) {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n\n const header = parseHeader(parts[0])\n\n // The spec does not describe what to do with the \"typ\" claim. We can,\n // however, forbid some values that are not compatible with our use case.\n if (\n // service tokens are not OAuth 2.0 access tokens\n // https://datatracker.ietf.org/doc/html/rfc9068\n header['typ'] === 'at+jwt' ||\n // \"refresh+jwt\" is a non-standard type used by the @atproto packages\n header['typ'] === 'refresh+jwt' ||\n // \"DPoP\" proofs are not meant to be used as service tokens\n // https://datatracker.ietf.org/doc/html/rfc9449\n header['typ'] === 'dpop+jwt'\n ) {\n throw new AuthRequiredError(\n `Invalid jwt type \"${header['typ']}\"`,\n 'BadJwtType',\n )\n }\n\n const payload = parsePayload(parts[1])\n const sig = parts[2]\n\n if (Date.now() / 1000 > payload.exp) {\n throw new AuthRequiredError('jwt expired', 'JwtExpired')\n }\n if (ownDid !== null && payload.aud !== ownDid) {\n throw new AuthRequiredError(\n 'jwt audience does not match service did',\n 'BadJwtAudience',\n )\n }\n if (lxm !== null && payload.lxm !== lxm) {\n throw new AuthRequiredError(\n payload.lxm !== undefined\n ? `bad jwt lexicon method (\"lxm\"). must match: ${lxm}`\n : `missing jwt lexicon method (\"lxm\"). must match: ${lxm}`,\n 'BadJwtLexiconMethod',\n )\n }\n if (!payload.iss || !isDidStringOrService(payload.iss)) {\n throw new AuthRequiredError('jwt iss is not a valid did', 'BadJwtIss')\n }\n\n const msgBytes = Buffer.from(parts.slice(0, 2).join('.'), 'utf8')\n const sigBytes = Buffer.from(sig, 'base64url')\n\n const signingKey = await getSigningKey(payload.iss, false)\n const { alg } = header\n\n let validSig: boolean\n try {\n validSig = await verifySignatureWithKey(signingKey, msgBytes, sigBytes, alg)\n } catch (err) {\n throw new AuthRequiredError(\n 'could not verify jwt signature',\n 'BadJwtSignature',\n )\n }\n\n if (!validSig) {\n // get fresh signing key in case it failed due to a recent rotation\n const freshSigningKey = await getSigningKey(payload.iss, true)\n try {\n validSig =\n freshSigningKey !== signingKey\n ? await verifySignatureWithKey(\n freshSigningKey,\n msgBytes,\n sigBytes,\n alg,\n )\n : false\n } catch (err) {\n throw new AuthRequiredError(\n 'could not verify jwt signature',\n 'BadJwtSignature',\n )\n }\n }\n\n if (!validSig) {\n throw new AuthRequiredError(\n 'jwt signature does not match jwt issuer',\n 'BadJwtSignature',\n )\n }\n\n return payload\n}\n\nexport const cryptoVerifySignatureWithKey: VerifySignatureWithKeyFn = async (\n key: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => {\n return crypto.verifySignature(key, msgBytes, sigBytes, {\n jwtAlg: alg,\n allowMalleableSig: true,\n })\n}\n\nconst parseB64UrlToJson = (b64: string) => {\n return JSON.parse(Buffer.from(b64, 'base64url').toString('utf8'))\n}\n\nconst parseHeader = (b64: string): ServiceJwtHeaders => {\n const header = parseB64UrlToJson(b64)\n if (!header || typeof header !== 'object' || typeof header.alg !== 'string') {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n return header\n}\n\nconst parsePayload = (b64: string): ServiceJwtPayload => {\n const payload = parseB64UrlToJson(b64)\n if (\n !payload ||\n typeof payload !== 'object' ||\n typeof payload.iss !== 'string' ||\n typeof payload.aud !== 'string' ||\n typeof payload.exp !== 'number' ||\n (payload.lxm && typeof payload.lxm !== 'string') ||\n (payload.nonce && typeof payload.nonce !== 'string')\n ) {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n return payload\n}\n\nfunction isDidStringOrService(\n value: string,\n): value is DidString | `${DidString}#${string}` {\n const hashIdx = value.indexOf('#')\n if (hashIdx === -1) {\n return isDidString(value)\n }\n\n // basic validation of the fragment part\n const fragmentLen = value.length - hashIdx - 1\n if (fragmentLen < 1 || value.includes('#', hashIdx + 1)) {\n return false\n }\n\n // Validate the did part\n const didPart = value.slice(0, hashIdx)\n return isDidString(didPart)\n}\n"]}
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,qBAAqB,CAAA;AACvC,OAAO,EACL,YAAY,EAKb,MAAM,eAAe,CAAA;AAKtB,eAAO,MAAM,WAAW;;;;EAItB,CAAA;AACF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAErD,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAE1D;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAE5B,OAAO,CAAC,CAAC,EAAE,WAAW,CAAC,CACpC;AAED,OAAO,EAAE,YAAY,EAAE,CAAA;AAEvB,qBAAa,SAAU,SAAQ,KAAK;IAEzB,IAAI,EAAE,YAAY;IAClB,YAAY,CAAC,EAAE,MAAM;IACrB,eAAe,CAAC,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line import/default, import/no-named-as-default-member\nimport httpErrors from 'http-errors'\n// eslint-disable-next-line import/no-named-as-default-member\nconst { isHttpError } = httpErrors\nimport { LexError, XrpcError } from '@atproto/lex-client'\nimport { l } from '@atproto/lex-schema'\nimport {\n ResponseType,\n ResponseTypeStrings,\n XRPCError as XRPCClientError,\n httpResponseCodeToName,\n httpResponseCodeToString,\n} from '@atproto/xrpc'\n\n// @NOTE Do not depend (directly or indirectly) on \"./types\" here, as it would\n// create a circular dependency.\n\nexport const errorResult = l.object({\n status: l.integer({ minimum: 400 }),\n error: l.optional(l.string()),\n message: l.optional(l.string()),\n})\nexport type ErrorResult = l.Infer<typeof errorResult>\n\nexport function isErrorResult(v: unknown): v is ErrorResult {\n return errorResult.safeParse(v).success\n}\n\nexport function excludeErrorResult<V>(v: V) {\n if (isErrorResult(v)) throw XRPCError.fromErrorResult(v)\n return v as Exclude<V, ErrorResult>\n}\n\nexport { ResponseType }\n\nexport class XRPCError extends Error {\n constructor(\n public type: ResponseType,\n public errorMessage?: string,\n public customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(errorMessage, options)\n }\n\n get statusCode(): number {\n const { type } = this\n\n // Fool-proofing. `new XRPCError(123.5 as number, '')` does not generate a TypeScript error.\n // Because of this, we can end-up with any numeric value instead of an actual `ResponseType`.\n // For legacy reasons, the `type` argument is not checked in the constructor, so we check it here.\n if (type < 400 || type >= 600 || !Number.isFinite(type)) {\n return 500\n }\n\n return type\n }\n\n get error(): string | undefined {\n return this.customErrorName ?? this.typeName\n }\n\n get payload() {\n return {\n error: this.error,\n message:\n this.type === ResponseType.InternalServerError\n ? this.typeStr // Do not respond with error details for 500s\n : this.errorMessage || this.typeStr,\n }\n }\n\n get typeName(): string | undefined {\n return ResponseType[this.type]\n }\n\n get typeStr(): string | undefined {\n return ResponseTypeStrings[this.type]\n }\n\n static fromError(cause: unknown): XRPCError {\n if (cause instanceof XRPCError) {\n return cause\n }\n\n if (cause instanceof XRPCClientError) {\n const { error, message, type } = mapFromClientError(cause)\n return new XRPCError(type, message, error, { cause })\n }\n\n if (cause instanceof XrpcError) {\n const { status, body } = cause.toDownstreamError()\n return new XRPCError(status, body.message, body.error, { cause })\n }\n\n if (cause instanceof LexError) {\n const data = cause.toJSON()\n const type = ResponseType.InternalServerError\n return new XRPCError(type, data.message, data.error, { cause })\n }\n\n if (isHttpError(cause)) {\n return new XRPCError(cause.status, cause.message, cause.name, { cause })\n }\n\n if (isErrorResult(cause)) {\n return this.fromErrorResult(cause)\n }\n\n if (cause instanceof Error) {\n return new InternalServerError(cause.message, undefined, { cause })\n }\n\n return new InternalServerError(\n 'Unexpected internal server error',\n undefined,\n { cause },\n )\n }\n\n static fromErrorResult(err: ErrorResult): XRPCError {\n return new XRPCError(err.status, err.message, err.error, { cause: err })\n }\n}\n\nexport class InvalidRequestError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.InvalidRequest, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.InvalidRequest\n )\n }\n}\n\nexport class AuthRequiredError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.AuthenticationRequired,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.AuthenticationRequired\n )\n }\n}\n\nexport class ForbiddenError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.Forbidden, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError && instance.type === ResponseType.Forbidden\n )\n }\n}\n\nexport class InternalServerError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.InternalServerError,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.InternalServerError\n )\n }\n}\n\nexport class UpstreamFailureError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.UpstreamFailure, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.UpstreamFailure\n )\n }\n}\n\nexport class NotEnoughResourcesError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.NotEnoughResources,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.NotEnoughResources\n )\n }\n}\n\nexport class UpstreamTimeoutError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.UpstreamTimeout, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.UpstreamTimeout\n )\n }\n}\n\nexport class MethodNotImplementedError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.MethodNotImplemented,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.MethodNotImplemented\n )\n }\n}\n\n/**\n * Converts an upstream XRPC {@link ResponseType} into a downstream {@link ResponseType}.\n */\nfunction mapFromClientError(error: XRPCClientError): {\n error: string\n message: string\n type: ResponseType\n} {\n switch (error.status) {\n case ResponseType.InvalidResponse:\n // Upstream server returned an XRPC response that is not compatible with our internal lexicon definitions for that XRPC method.\n // @NOTE This could be reflected as both a 500 (\"we\" are at fault) and 502 (\"they\" are at fault). Let's be gents about it.\n return {\n error: httpResponseCodeToName(ResponseType.InternalServerError),\n message: httpResponseCodeToString(ResponseType.InternalServerError),\n type: ResponseType.InternalServerError,\n }\n case ResponseType.Unknown:\n // Typically a network error / unknown host\n return {\n error: httpResponseCodeToName(ResponseType.InternalServerError),\n message: httpResponseCodeToString(ResponseType.InternalServerError),\n type: ResponseType.InternalServerError,\n }\n default:\n return {\n error: error.error,\n message: error.message,\n type: error.status,\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line import/default, import/no-named-as-default-member\nimport httpErrors from 'http-errors'\n// eslint-disable-next-line import/no-named-as-default-member\nconst { isHttpError } = httpErrors\nimport { LexError, XrpcError } from '@atproto/lex-client'\nimport { l } from '@atproto/lex-schema'\nimport {\n ResponseType,\n ResponseTypeStrings,\n XRPCError as XRPCClientError,\n httpResponseCodeToName,\n httpResponseCodeToString,\n} from '@atproto/xrpc'\n\n// @NOTE Do not depend (directly or indirectly) on \"./types\" here, as it would\n// create a circular dependency.\n\nexport const errorResult = l.object({\n status: l.integer({ minimum: 400 }),\n error: l.optional(l.string()),\n message: l.optional(l.string()),\n})\nexport type ErrorResult = l.Infer<typeof errorResult>\n\nexport function isErrorResult(v: unknown): v is ErrorResult {\n return errorResult.safeParse(v).success\n}\n\nexport function excludeErrorResult<V>(v: V) {\n if (isErrorResult(v)) throw XRPCError.fromErrorResult(v)\n return v as Exclude<V, ErrorResult>\n}\n\nexport { ResponseType }\n\nexport class XRPCError extends Error {\n constructor(\n public type: ResponseType,\n public errorMessage?: string,\n public customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(errorMessage, options)\n }\n\n get statusCode(): number {\n const { type } = this\n\n // Fool-proofing. `new XRPCError(123.5 as number, '')` does not generate a TypeScript error.\n // Because of this, we can end-up with any numeric value instead of an actual `ResponseType`.\n // For legacy reasons, the `type` argument is not checked in the constructor, so we check it here.\n if (type < 400 || type >= 600 || !Number.isFinite(type)) {\n return 500\n }\n\n return type\n }\n\n get error(): string | undefined {\n return this.customErrorName ?? this.typeName\n }\n\n get payload() {\n return {\n error: this.error,\n message:\n this.type === ResponseType.InternalServerError\n ? this.typeStr // Do not respond with error details for 500s\n : this.errorMessage || this.typeStr,\n }\n }\n\n get typeName(): string | undefined {\n return ResponseType[this.type]\n }\n\n get typeStr(): string | undefined {\n return ResponseTypeStrings[this.type]\n }\n\n static fromError(cause: unknown): XRPCError {\n if (cause instanceof XRPCError) {\n return cause\n }\n\n if (cause instanceof XRPCClientError) {\n const { error, message, type } = mapFromClientError(cause)\n return new XRPCError(type, message, error, { cause })\n }\n\n if (cause instanceof XrpcError) {\n const { status, body } = cause.toDownstreamError()\n return new XRPCError(status, body.message, body.error, { cause })\n }\n\n if (cause instanceof LexError) {\n const data = cause.toJSON()\n const type = ResponseType.InternalServerError\n return new XRPCError(type, data.message, data.error, { cause })\n }\n\n if (isHttpError(cause)) {\n return new XRPCError(cause.status, cause.message, cause.name, { cause })\n }\n\n if (isErrorResult(cause)) {\n return this.fromErrorResult(cause)\n }\n\n if (cause instanceof Error) {\n return new InternalServerError(cause.message, undefined, { cause })\n }\n\n return new InternalServerError(\n 'Unexpected internal server error',\n undefined,\n { cause },\n )\n }\n\n static fromErrorResult(err: ErrorResult): XRPCError {\n return new XRPCError(err.status, err.message, err.error, { cause: err })\n }\n}\n\nexport class InvalidRequestError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.InvalidRequest, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.InvalidRequest\n )\n }\n}\n\nexport class AuthRequiredError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.AuthenticationRequired,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.AuthenticationRequired\n )\n }\n}\n\nexport class ForbiddenError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.Forbidden, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError && instance.type === ResponseType.Forbidden\n )\n }\n}\n\nexport class InternalServerError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.InternalServerError,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.InternalServerError\n )\n }\n}\n\nexport class UpstreamFailureError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.UpstreamFailure, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.UpstreamFailure\n )\n }\n}\n\nexport class NotEnoughResourcesError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.NotEnoughResources,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.NotEnoughResources\n )\n }\n}\n\nexport class UpstreamTimeoutError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.UpstreamTimeout, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.UpstreamTimeout\n )\n }\n}\n\nexport class MethodNotImplementedError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.MethodNotImplemented,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.MethodNotImplemented\n )\n }\n}\n\n/**\n * Converts an upstream XRPC {@link ResponseType} into a downstream {@link ResponseType}.\n */\nfunction mapFromClientError(error: XRPCClientError): {\n error: string\n message: string\n type: ResponseType\n} {\n switch (error.status) {\n case ResponseType.InvalidResponse:\n // Upstream server returned an XRPC response that is not compatible with our internal lexicon definitions for that XRPC method.\n // @NOTE This could be reflected as both a 500 (\"we\" are at fault) and 502 (\"they\" are at fault). Let's be gents about it.\n return {\n error: httpResponseCodeToName(ResponseType.InternalServerError),\n message: httpResponseCodeToString(ResponseType.InternalServerError),\n type: ResponseType.InternalServerError,\n }\n case ResponseType.Unknown:\n // Typically a network error / unknown host\n return {\n error: httpResponseCodeToName(ResponseType.InternalServerError),\n message: httpResponseCodeToString(ResponseType.InternalServerError),\n type: ResponseType.InternalServerError,\n }\n default:\n return {\n error: error.error,\n message: error.message,\n type: error.status,\n }\n }\n}\n"]}
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,eAAO,MAAM,WAAW,gBAAgB,CAAA;AAExC,eAAO,MAAM,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CACxB,CAAA;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,eAAO,MAAM,WAAW,gBAAgB,CAAA;AAExC,eAAO,MAAM,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CACxB,CAAA;eAEf,MAAM"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { RateLimiterConsume, RateLimiterI, RateLimiterReset, RateLimiterStatus } from './rate-limiter.js';
|
|
3
|
+
export interface HttpRateLimiterContext {
|
|
4
|
+
req: IncomingMessage;
|
|
5
|
+
res?: ServerResponse;
|
|
6
|
+
}
|
|
7
|
+
export type HttpRateLimiterOptions<C extends HttpRateLimiterContext = HttpRateLimiterContext> = {
|
|
8
|
+
bypass?: (ctx: C) => boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Wraps a {@link RateLimiterI} class with an {@link RateLimiterI}
|
|
12
|
+
* implementation that will apply the appropriate headers to the response if a
|
|
13
|
+
* limit is exceeded.
|
|
14
|
+
*/
|
|
15
|
+
export declare class HttpRateLimiter<C extends HttpRateLimiterContext = HttpRateLimiterContext> implements RateLimiterI<C> {
|
|
16
|
+
private readonly rateLimiter;
|
|
17
|
+
private readonly options;
|
|
18
|
+
constructor(rateLimiter: RateLimiterI<C>, options?: Readonly<HttpRateLimiterOptions<C>>);
|
|
19
|
+
handle(ctx: C): Promise<void>;
|
|
20
|
+
consume(...args: Parameters<RateLimiterConsume<C>>): Promise<RateLimiterStatus | null>;
|
|
21
|
+
reset(...args: Parameters<RateLimiterReset<C>>): Promise<void>;
|
|
22
|
+
static from<C extends HttpRateLimiterContext = HttpRateLimiterContext>(rateLimiters: readonly RateLimiterI<C>[], { bypass }?: HttpRateLimiterOptions<C>): HttpRateLimiter<C> | undefined;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=rate-limiter-http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter-http.d.ts","sourceRoot":"","sources":["../src/rate-limiter-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC3D,OAAO,EAGL,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,mBAAmB,CAAA;AAE1B,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,eAAe,CAAA;IACpB,GAAG,CAAC,EAAE,cAAc,CAAA;CACrB;AAED,MAAM,MAAM,sBAAsB,CAChC,CAAC,SAAS,sBAAsB,GAAG,sBAAsB,IACvD;IACF,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAA;CAC7B,CAAA;AAED;;;;GAIG;AACH,qBAAa,eAAe,CAC1B,CAAC,SAAS,sBAAsB,GAAG,sBAAsB,CACzD,YAAW,YAAY,CAAC,CAAC,CAAC;IAGxB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAF1B,YACmB,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,EAC5B,OAAO,GAAE,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAM,EAChE;IAEE,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBlC;IAEK,OAAO,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,qCAEvD;IAEK,KAAK,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,iBAEnD;IAED,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,sBAAsB,GAAG,sBAAsB,EACnE,YAAY,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,EAAE,EACxC,EAAE,MAAM,EAAE,GAAE,sBAAsB,CAAC,CAAC,CAAM,GACzC,eAAe,CAAC,CAAC,CAAC,GAAG,SAAS,CAKhC;CACF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CombinedRateLimiter, RateLimitExceededError, } from './rate-limiter.js';
|
|
2
|
+
/**
|
|
3
|
+
* Wraps a {@link RateLimiterI} class with an {@link RateLimiterI}
|
|
4
|
+
* implementation that will apply the appropriate headers to the response if a
|
|
5
|
+
* limit is exceeded.
|
|
6
|
+
*/
|
|
7
|
+
export class HttpRateLimiter {
|
|
8
|
+
constructor(rateLimiter, options = {}) {
|
|
9
|
+
this.rateLimiter = rateLimiter;
|
|
10
|
+
this.options = options;
|
|
11
|
+
}
|
|
12
|
+
async handle(ctx) {
|
|
13
|
+
const { bypass } = this.options;
|
|
14
|
+
if (bypass && bypass(ctx))
|
|
15
|
+
return;
|
|
16
|
+
try {
|
|
17
|
+
const result = await this.consume(ctx);
|
|
18
|
+
if (result != null) {
|
|
19
|
+
setStatusHeaders(ctx, result);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
if (err instanceof RateLimitExceededError) {
|
|
24
|
+
setStatusHeaders(ctx, err.status);
|
|
25
|
+
}
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async consume(...args) {
|
|
30
|
+
return this.rateLimiter.consume(...args);
|
|
31
|
+
}
|
|
32
|
+
async reset(...args) {
|
|
33
|
+
return this.rateLimiter.reset(...args);
|
|
34
|
+
}
|
|
35
|
+
static from(rateLimiters, { bypass } = {}) {
|
|
36
|
+
const rateLimiter = CombinedRateLimiter.from(rateLimiters);
|
|
37
|
+
if (!rateLimiter)
|
|
38
|
+
return undefined;
|
|
39
|
+
return new HttpRateLimiter(rateLimiter, { bypass });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function setStatusHeaders(ctx, status) {
|
|
43
|
+
const resetAt = Math.floor((Date.now() + status.msBeforeNext) / 1e3);
|
|
44
|
+
ctx.res?.setHeader('RateLimit-Limit', status.limit);
|
|
45
|
+
ctx.res?.setHeader('RateLimit-Reset', resetAt);
|
|
46
|
+
ctx.res?.setHeader('RateLimit-Remaining', status.remainingPoints);
|
|
47
|
+
ctx.res?.setHeader('RateLimit-Policy', `${status.limit};w=${status.duration}`);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=rate-limiter-http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter-http.js","sourceRoot":"","sources":["../src/rate-limiter-http.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,sBAAsB,GAKvB,MAAM,mBAAmB,CAAA;AAa1B;;;;GAIG;AACH,MAAM,OAAO,eAAe;IAI1B,YACmB,WAA4B,EAC5B,OAAO,GAAwC,EAAE;2BADjD,WAAW;uBACX,OAAO;IACvB,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAC,GAAM;QACjB,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QAC/B,IAAI,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC;YAAE,OAAM;QAEjC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YACtC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,sBAAsB,EAAE,CAAC;gBAC1C,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;YACnC,CAAC;YAED,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAG,IAAuC;QACtD,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;IAC1C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,GAAG,IAAqC;QAClD,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAA;IACxC,CAAC;IAED,MAAM,CAAC,IAAI,CACT,YAAwC,EACxC,EAAE,MAAM,EAAE,GAA8B,EAAE;QAE1C,MAAM,WAAW,GAAG,mBAAmB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;QAC1D,IAAI,CAAC,WAAW;YAAE,OAAO,SAAS,CAAA;QAElC,OAAO,IAAI,eAAe,CAAI,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;IACxD,CAAC;CACF;AAED,SAAS,gBAAgB,CAEvB,GAAM,EAAE,MAAyB;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,CAAA;IAEpE,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IACnD,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAA;IAC9C,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,qBAAqB,EAAE,MAAM,CAAC,eAAe,CAAC,CAAA;IACjE,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,kBAAkB,EAAE,GAAG,MAAM,CAAC,KAAK,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;AAChF,CAAC","sourcesContent":["import { IncomingMessage, ServerResponse } from 'node:http'\nimport {\n CombinedRateLimiter,\n RateLimitExceededError,\n RateLimiterConsume,\n RateLimiterI,\n RateLimiterReset,\n RateLimiterStatus,\n} from './rate-limiter.js'\n\nexport interface HttpRateLimiterContext {\n req: IncomingMessage\n res?: ServerResponse\n}\n\nexport type HttpRateLimiterOptions<\n C extends HttpRateLimiterContext = HttpRateLimiterContext,\n> = {\n bypass?: (ctx: C) => boolean\n}\n\n/**\n * Wraps a {@link RateLimiterI} class with an {@link RateLimiterI}\n * implementation that will apply the appropriate headers to the response if a\n * limit is exceeded.\n */\nexport class HttpRateLimiter<\n C extends HttpRateLimiterContext = HttpRateLimiterContext,\n> implements RateLimiterI<C>\n{\n constructor(\n private readonly rateLimiter: RateLimiterI<C>,\n private readonly options: Readonly<HttpRateLimiterOptions<C>> = {},\n ) {}\n\n async handle(ctx: C): Promise<void> {\n const { bypass } = this.options\n if (bypass && bypass(ctx)) return\n\n try {\n const result = await this.consume(ctx)\n if (result != null) {\n setStatusHeaders(ctx, result)\n }\n } catch (err) {\n if (err instanceof RateLimitExceededError) {\n setStatusHeaders(ctx, err.status)\n }\n\n throw err\n }\n }\n\n async consume(...args: Parameters<RateLimiterConsume<C>>) {\n return this.rateLimiter.consume(...args)\n }\n\n async reset(...args: Parameters<RateLimiterReset<C>>) {\n return this.rateLimiter.reset(...args)\n }\n\n static from<C extends HttpRateLimiterContext = HttpRateLimiterContext>(\n rateLimiters: readonly RateLimiterI<C>[],\n { bypass }: HttpRateLimiterOptions<C> = {},\n ): HttpRateLimiter<C> | undefined {\n const rateLimiter = CombinedRateLimiter.from(rateLimiters)\n if (!rateLimiter) return undefined\n\n return new HttpRateLimiter<C>(rateLimiter, { bypass })\n }\n}\n\nfunction setStatusHeaders<\n C extends HttpRateLimiterContext = HttpRateLimiterContext,\n>(ctx: C, status: RateLimiterStatus) {\n const resetAt = Math.floor((Date.now() + status.msBeforeNext) / 1e3)\n\n ctx.res?.setHeader('RateLimit-Limit', status.limit)\n ctx.res?.setHeader('RateLimit-Reset', resetAt)\n ctx.res?.setHeader('RateLimit-Remaining', status.remainingPoints)\n ctx.res?.setHeader('RateLimit-Policy', `${status.limit};w=${status.duration}`)\n}\n"]}
|
package/dist/rate-limiter.d.ts
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
1
|
import { RateLimiterAbstract, RateLimiterRes } from 'rate-limiter-flexible';
|
|
3
2
|
import { XRPCError } from './errors.js';
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export type CalcKeyFn<C extends RateLimiterContext = RateLimiterContext> = (ctx: C) => string | null;
|
|
9
|
-
export type CalcPointsFn<C extends RateLimiterContext = RateLimiterContext> = (ctx: C) => number;
|
|
10
|
-
export interface RateLimiterI<C extends RateLimiterContext = RateLimiterContext> {
|
|
3
|
+
export type { RateLimiterAbstract };
|
|
4
|
+
export type CalcKeyFn<C = unknown> = (ctx: C) => string | null;
|
|
5
|
+
export type CalcPointsFn<C = unknown> = (ctx: C) => number;
|
|
6
|
+
export interface RateLimiterI<C = unknown> {
|
|
11
7
|
consume: RateLimiterConsume<C>;
|
|
12
8
|
reset: RateLimiterReset<C>;
|
|
13
9
|
}
|
|
14
|
-
export type RateLimiterConsumeOptions<C
|
|
10
|
+
export type RateLimiterConsumeOptions<C = unknown> = {
|
|
15
11
|
calcKey?: CalcKeyFn<C>;
|
|
16
12
|
calcPoints?: CalcPointsFn<C>;
|
|
17
13
|
};
|
|
18
|
-
export type RateLimiterConsume<C
|
|
14
|
+
export type RateLimiterConsume<C = unknown> = (ctx: C, opts?: RateLimiterConsumeOptions<C>) => Promise<RateLimiterStatus | null>;
|
|
19
15
|
export type RateLimiterStatus = {
|
|
20
16
|
limit: number;
|
|
21
17
|
duration: number;
|
|
@@ -24,35 +20,45 @@ export type RateLimiterStatus = {
|
|
|
24
20
|
consumedPoints: number;
|
|
25
21
|
isFirstInDuration: boolean;
|
|
26
22
|
};
|
|
27
|
-
export type RateLimiterResetOptions<C
|
|
23
|
+
export type RateLimiterResetOptions<C = unknown> = {
|
|
28
24
|
calcKey?: CalcKeyFn<C>;
|
|
29
25
|
};
|
|
30
|
-
export type RateLimiterReset<C
|
|
31
|
-
export type
|
|
26
|
+
export type RateLimiterReset<C = unknown> = (ctx: C, opts?: RateLimiterResetOptions<C>) => Promise<void>;
|
|
27
|
+
export type RateLimiterErrorHandlerDetails = {
|
|
28
|
+
key: string;
|
|
29
|
+
points: number;
|
|
30
|
+
limiter: {
|
|
31
|
+
keyPrefix: string;
|
|
32
|
+
points: number;
|
|
33
|
+
duration: number;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export type RateLimiterErrorHandler<C = unknown> = (err: unknown, ctx: C, details: RateLimiterErrorHandlerDetails) => Promise<RateLimiterStatus | null>;
|
|
37
|
+
export type RateLimiterOptions<C = unknown> = {
|
|
32
38
|
keyPrefix: string;
|
|
33
39
|
durationMs: number;
|
|
34
40
|
points: number;
|
|
35
41
|
calcKey: CalcKeyFn<C>;
|
|
36
42
|
calcPoints: CalcPointsFn<C>;
|
|
37
|
-
|
|
43
|
+
onError?: RateLimiterErrorHandler<C>;
|
|
38
44
|
};
|
|
39
|
-
export declare class RateLimiter<C
|
|
45
|
+
export declare class RateLimiter<C = unknown> implements RateLimiterI<C> {
|
|
40
46
|
limiter: RateLimiterAbstract;
|
|
41
|
-
private readonly
|
|
47
|
+
private readonly onError?;
|
|
42
48
|
private readonly calcKey;
|
|
43
49
|
private readonly calcPoints;
|
|
44
50
|
constructor(limiter: RateLimiterAbstract, options: RateLimiterOptions<C>);
|
|
45
|
-
consume(ctx: C, opts?: RateLimiterConsumeOptions<C>): Promise<RateLimiterStatus |
|
|
51
|
+
consume(ctx: C, opts?: RateLimiterConsumeOptions<C>): Promise<RateLimiterStatus | null>;
|
|
46
52
|
reset(ctx: C, opts?: RateLimiterResetOptions<C>): Promise<void>;
|
|
47
53
|
}
|
|
48
|
-
export declare class MemoryRateLimiter<C
|
|
54
|
+
export declare class MemoryRateLimiter<C = unknown> extends RateLimiter<C> {
|
|
49
55
|
constructor(options: RateLimiterOptions<C>);
|
|
50
56
|
}
|
|
51
|
-
export declare class RedisRateLimiter<C
|
|
57
|
+
export declare class RedisRateLimiter<C = unknown> extends RateLimiter<C> {
|
|
52
58
|
constructor(storeClient: unknown, options: RateLimiterOptions<C>);
|
|
53
59
|
}
|
|
54
60
|
export declare const formatLimiterStatus: (limiter: RateLimiterAbstract, res: RateLimiterRes) => RateLimiterStatus;
|
|
55
|
-
export type WrappedRateLimiterOptions<C
|
|
61
|
+
export type WrappedRateLimiterOptions<C = unknown> = {
|
|
56
62
|
calcKey?: CalcKeyFn<C>;
|
|
57
63
|
calcPoints?: CalcPointsFn<C>;
|
|
58
64
|
};
|
|
@@ -60,13 +66,13 @@ export type WrappedRateLimiterOptions<C extends RateLimiterContext = RateLimiter
|
|
|
60
66
|
* Wraps a {@link RateLimiterI} instance with custom key and points calculation
|
|
61
67
|
* functions.
|
|
62
68
|
*/
|
|
63
|
-
export declare class WrappedRateLimiter<C
|
|
69
|
+
export declare class WrappedRateLimiter<C = unknown> implements RateLimiterI<C> {
|
|
64
70
|
private readonly rateLimiter;
|
|
65
71
|
private readonly options;
|
|
66
72
|
private constructor();
|
|
67
|
-
consume(ctx: C, opts?: RateLimiterConsumeOptions<C>): Promise<RateLimiterStatus |
|
|
73
|
+
consume(ctx: C, opts?: RateLimiterConsumeOptions<C>): Promise<RateLimiterStatus | null>;
|
|
68
74
|
reset(ctx: C, opts?: RateLimiterResetOptions<C>): Promise<void>;
|
|
69
|
-
static from<C
|
|
75
|
+
static from<C = unknown>(rateLimiter: RateLimiterI<C>, { calcKey, calcPoints }?: WrappedRateLimiterOptions<C>): RateLimiterI<C>;
|
|
70
76
|
}
|
|
71
77
|
/**
|
|
72
78
|
* Combines multiple rate limiters into one.
|
|
@@ -74,28 +80,12 @@ export declare class WrappedRateLimiter<C extends RateLimiterContext = RateLimit
|
|
|
74
80
|
* The combined rate limiter will return the tightest (most restrictive) of all
|
|
75
81
|
* the provided rate limiters.
|
|
76
82
|
*/
|
|
77
|
-
export declare class CombinedRateLimiter<C
|
|
83
|
+
export declare class CombinedRateLimiter<C = unknown> implements RateLimiterI<C> {
|
|
78
84
|
private readonly rateLimiters;
|
|
79
85
|
private constructor();
|
|
80
|
-
consume(ctx: C, opts?: RateLimiterConsumeOptions<C>): Promise<RateLimiterStatus |
|
|
86
|
+
consume(ctx: C, opts?: RateLimiterConsumeOptions<C>): Promise<RateLimiterStatus | null>;
|
|
81
87
|
reset(ctx: C, opts?: RateLimiterResetOptions<C>): Promise<void>;
|
|
82
|
-
static from<C
|
|
83
|
-
}
|
|
84
|
-
export type RouteRateLimiterOptions<C extends RateLimiterContext = RateLimiterContext> = {
|
|
85
|
-
bypass?: (ctx: C) => boolean;
|
|
86
|
-
};
|
|
87
|
-
/**
|
|
88
|
-
* Wraps a {@link RateLimiterI} interface into a class that will apply the
|
|
89
|
-
* appropriate headers to the response if a limit is exceeded.
|
|
90
|
-
*/
|
|
91
|
-
export declare class RouteRateLimiter<C extends RateLimiterContext = RateLimiterContext> implements RateLimiterI<C> {
|
|
92
|
-
private readonly rateLimiter;
|
|
93
|
-
private readonly options;
|
|
94
|
-
constructor(rateLimiter: RateLimiterI<C>, options?: Readonly<RouteRateLimiterOptions<C>>);
|
|
95
|
-
handle(ctx: C): Promise<RateLimiterStatus | null>;
|
|
96
|
-
consume(...args: Parameters<RateLimiterConsume<C>>): Promise<RateLimiterStatus | RateLimitExceededError | null>;
|
|
97
|
-
reset(...args: Parameters<RateLimiterReset<C>>): Promise<void>;
|
|
98
|
-
static from<C extends RateLimiterContext = RateLimiterContext>(rateLimiters: readonly RateLimiterI<C>[], { bypass }?: RouteRateLimiterOptions<C>): RouteRateLimiter<C> | undefined;
|
|
88
|
+
static from<C = unknown>(rateLimiters: readonly RateLimiterI<C>[]): RateLimiterI<C> | undefined;
|
|
99
89
|
}
|
|
100
90
|
export declare class RateLimitExceededError extends XRPCError {
|
|
101
91
|
status: RateLimiterStatus;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"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"}
|
package/dist/rate-limiter.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { RateLimiterMemory, RateLimiterRedis, RateLimiterRes, } from 'rate-limiter-flexible';
|
|
2
2
|
import { ResponseType, XRPCError } from './errors.js';
|
|
3
|
-
import { logger } from './logger.js';
|
|
4
3
|
export class RateLimiter {
|
|
5
4
|
constructor(limiter, options) {
|
|
6
5
|
this.limiter = limiter;
|
|
7
6
|
this.limiter = limiter;
|
|
8
|
-
this.
|
|
7
|
+
this.onError = options.onError;
|
|
9
8
|
this.calcKey = options.calcKey;
|
|
10
9
|
this.calcPoints = options.calcPoints;
|
|
11
10
|
}
|
|
@@ -20,27 +19,29 @@ export class RateLimiter {
|
|
|
20
19
|
if (points < 1) {
|
|
21
20
|
return null;
|
|
22
21
|
}
|
|
22
|
+
const { limiter } = this;
|
|
23
23
|
try {
|
|
24
|
-
const res = await
|
|
25
|
-
return formatLimiterStatus(
|
|
24
|
+
const res = await limiter.consume(key, points);
|
|
25
|
+
return formatLimiterStatus(limiter, res);
|
|
26
26
|
}
|
|
27
27
|
catch (err) {
|
|
28
|
-
// yes this library rejects with a res not an error
|
|
29
28
|
if (err instanceof RateLimiterRes) {
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
// Wrap rate-limiter-flexible error into our own error type
|
|
30
|
+
const status = formatLimiterStatus(limiter, err);
|
|
31
|
+
throw new RateLimitExceededError(status);
|
|
32
|
+
}
|
|
33
|
+
else if (err instanceof RateLimitExceededError) {
|
|
34
|
+
// Propagate RateLimitExceededError errors
|
|
35
|
+
throw err;
|
|
32
36
|
}
|
|
33
37
|
else {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
duration: this.limiter.duration,
|
|
42
|
-
}, 'rate limiter failed to consume points');
|
|
43
|
-
return null;
|
|
38
|
+
// Most likely a system error (failed to connect to Redis, etc). Allow
|
|
39
|
+
// the caller to decide how to handle it (fail open by allowing the
|
|
40
|
+
// request, fail closed by rejecting the request, etc).
|
|
41
|
+
const { onError } = this;
|
|
42
|
+
if (onError)
|
|
43
|
+
return onError(err, ctx, { key, points, limiter });
|
|
44
|
+
throw err;
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
}
|
|
@@ -128,7 +129,17 @@ export class CombinedRateLimiter {
|
|
|
128
129
|
const promises = [];
|
|
129
130
|
for (const rl of this.rateLimiters)
|
|
130
131
|
promises.push(rl.consume(ctx, opts));
|
|
131
|
-
|
|
132
|
+
const results = await Promise.all(promises);
|
|
133
|
+
// Compute the tightest rate limit status (the one with the least remaining points)
|
|
134
|
+
let lowest = null;
|
|
135
|
+
for (const resp of results) {
|
|
136
|
+
if (resp === null)
|
|
137
|
+
continue;
|
|
138
|
+
if (lowest === null || resp.remainingPoints < lowest.remainingPoints) {
|
|
139
|
+
lowest = resp;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return lowest;
|
|
132
143
|
}
|
|
133
144
|
async reset(ctx, opts) {
|
|
134
145
|
const promises = [];
|
|
@@ -144,63 +155,6 @@ export class CombinedRateLimiter {
|
|
|
144
155
|
return new CombinedRateLimiter(rateLimiters);
|
|
145
156
|
}
|
|
146
157
|
}
|
|
147
|
-
const getTightestLimit = (resps) => {
|
|
148
|
-
let lowest = null;
|
|
149
|
-
for (const resp of resps) {
|
|
150
|
-
if (resp === null)
|
|
151
|
-
continue;
|
|
152
|
-
if (resp instanceof RateLimitExceededError)
|
|
153
|
-
return resp;
|
|
154
|
-
if (lowest === null || resp.remainingPoints < lowest.remainingPoints) {
|
|
155
|
-
lowest = resp;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
return lowest;
|
|
159
|
-
};
|
|
160
|
-
/**
|
|
161
|
-
* Wraps a {@link RateLimiterI} interface into a class that will apply the
|
|
162
|
-
* appropriate headers to the response if a limit is exceeded.
|
|
163
|
-
*/
|
|
164
|
-
export class RouteRateLimiter {
|
|
165
|
-
constructor(rateLimiter, options = {}) {
|
|
166
|
-
this.rateLimiter = rateLimiter;
|
|
167
|
-
this.options = options;
|
|
168
|
-
}
|
|
169
|
-
async handle(ctx) {
|
|
170
|
-
const { bypass } = this.options;
|
|
171
|
-
if (bypass && bypass(ctx)) {
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
const result = await this.consume(ctx);
|
|
175
|
-
if (result instanceof RateLimitExceededError) {
|
|
176
|
-
setStatusHeaders(ctx, result.status);
|
|
177
|
-
throw result;
|
|
178
|
-
}
|
|
179
|
-
else if (result != null) {
|
|
180
|
-
setStatusHeaders(ctx, result);
|
|
181
|
-
}
|
|
182
|
-
return result;
|
|
183
|
-
}
|
|
184
|
-
async consume(...args) {
|
|
185
|
-
return this.rateLimiter.consume(...args);
|
|
186
|
-
}
|
|
187
|
-
async reset(...args) {
|
|
188
|
-
return this.rateLimiter.reset(...args);
|
|
189
|
-
}
|
|
190
|
-
static from(rateLimiters, { bypass } = {}) {
|
|
191
|
-
const rateLimiter = CombinedRateLimiter.from(rateLimiters);
|
|
192
|
-
if (!rateLimiter)
|
|
193
|
-
return undefined;
|
|
194
|
-
return new RouteRateLimiter(rateLimiter, { bypass });
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
function setStatusHeaders(ctx, status) {
|
|
198
|
-
const resetAt = Math.floor((Date.now() + status.msBeforeNext) / 1e3);
|
|
199
|
-
ctx.res?.setHeader('RateLimit-Limit', status.limit);
|
|
200
|
-
ctx.res?.setHeader('RateLimit-Reset', resetAt);
|
|
201
|
-
ctx.res?.setHeader('RateLimit-Remaining', status.remainingPoints);
|
|
202
|
-
ctx.res?.setHeader('RateLimit-Policy', `${status.limit};w=${status.duration}`);
|
|
203
|
-
}
|
|
204
158
|
export class RateLimitExceededError extends XRPCError {
|
|
205
159
|
constructor(status, errorMessage, customErrorName, options) {
|
|
206
160
|
super(ResponseType.RateLimitExceeded, errorMessage, customErrorName, options);
|