@atproto/xrpc-server 0.3.1 → 0.3.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.
@@ -5,13 +5,15 @@ export declare type RateLimiterOpts = {
5
5
  durationMs: number;
6
6
  points: number;
7
7
  bypassSecret?: string;
8
+ bypassIps?: string[];
8
9
  calcKey?: CalcKeyFn;
9
10
  calcPoints?: CalcPointsFn;
10
11
  failClosed?: boolean;
11
12
  };
12
13
  export declare class RateLimiter implements RateLimiterI {
13
14
  limiter: RateLimiterAbstract;
14
- private byPassSecret?;
15
+ private bypassSecret?;
16
+ private bypassIps?;
15
17
  private failClosed?;
16
18
  calcKey: CalcKeyFn;
17
19
  calcPoints: CalcPointsFn;
package/package.json CHANGED
@@ -1,13 +1,19 @@
1
1
  {
2
2
  "name": "@atproto/xrpc-server",
3
- "version": "0.3.1",
4
- "main": "dist/index.js",
3
+ "version": "0.3.2",
5
4
  "license": "MIT",
5
+ "description": "atproto HTTP API (XRPC) server library",
6
+ "keywords": [
7
+ "atproto",
8
+ "xrpc"
9
+ ],
10
+ "homepage": "https://atproto.com",
6
11
  "repository": {
7
12
  "type": "git",
8
- "url": "https://github.com/bluesky-social/atproto.git",
13
+ "url": "https://github.com/bluesky-social/atproto",
9
14
  "directory": "packages/xrpc-server"
10
15
  },
16
+ "main": "dist/index.js",
11
17
  "dependencies": {
12
18
  "cbor-x": "^1.5.1",
13
19
  "express": "^4.17.2",
@@ -17,9 +23,9 @@
17
23
  "uint8arrays": "3.0.0",
18
24
  "ws": "^8.12.0",
19
25
  "zod": "^3.21.4",
20
- "@atproto/common": "^0.3.0",
26
+ "@atproto/common": "^0.3.1",
21
27
  "@atproto/crypto": "^0.2.2",
22
- "@atproto/lexicon": "^0.2.1"
28
+ "@atproto/lexicon": "^0.2.2"
23
29
  },
24
30
  "devDependencies": {
25
31
  "@types/express": "^4.17.13",
@@ -29,7 +35,7 @@
29
35
  "get-port": "^6.1.2",
30
36
  "multiformats": "^9.9.0",
31
37
  "@atproto/crypto": "^0.2.2",
32
- "@atproto/xrpc": "^0.3.1"
38
+ "@atproto/xrpc": "^0.3.2"
33
39
  },
34
40
  "scripts": {
35
41
  "test": "jest",
@@ -20,6 +20,7 @@ export type RateLimiterOpts = {
20
20
  durationMs: number
21
21
  points: number
22
22
  bypassSecret?: string
23
+ bypassIps?: string[]
23
24
  calcKey?: CalcKeyFn
24
25
  calcPoints?: CalcPointsFn
25
26
  failClosed?: boolean
@@ -27,14 +28,16 @@ export type RateLimiterOpts = {
27
28
 
28
29
  export class RateLimiter implements RateLimiterI {
29
30
  public limiter: RateLimiterAbstract
30
- private byPassSecret?: string
31
+ private bypassSecret?: string
32
+ private bypassIps?: string[]
31
33
  private failClosed?: boolean
32
34
  public calcKey: CalcKeyFn
33
35
  public calcPoints: CalcPointsFn
34
36
 
35
37
  constructor(limiter: RateLimiterAbstract, opts: RateLimiterOpts) {
36
38
  this.limiter = limiter
37
- this.byPassSecret = opts.bypassSecret
39
+ this.bypassSecret = opts.bypassSecret
40
+ this.bypassIps = opts.bypassIps
38
41
  this.calcKey = opts.calcKey ?? defaultKey
39
42
  this.calcPoints = opts.calcPoints ?? defaultPoints
40
43
  }
@@ -63,11 +66,14 @@ export class RateLimiter implements RateLimiterI {
63
66
  opts?: { calcKey?: CalcKeyFn; calcPoints?: CalcPointsFn },
64
67
  ): Promise<RateLimiterStatus | RateLimitExceededError | null> {
65
68
  if (
66
- this.byPassSecret &&
67
- ctx.req.header('x-ratelimit-bypass') === this.byPassSecret
69
+ this.bypassSecret &&
70
+ ctx.req.header('x-ratelimit-bypass') === this.bypassSecret
68
71
  ) {
69
72
  return null
70
73
  }
74
+ if (this.bypassIps && this.bypassIps.includes(ctx.req.ip)) {
75
+ return null
76
+ }
71
77
  const key = opts?.calcKey ? opts.calcKey(ctx) : this.calcKey(ctx)
72
78
  const points = opts?.calcPoints
73
79
  ? opts.calcPoints(ctx)
package/src/server.ts CHANGED
@@ -405,7 +405,8 @@ export class Server {
405
405
  ? config.rateLimit
406
406
  : [config.rateLimit]
407
407
  this.routeRateLimiterFns[nsid] = []
408
- for (const limit of limits) {
408
+ for (let i = 0; i < limits.length; i++) {
409
+ const limit = limits[i]
409
410
  const { calcKey, calcPoints } = limit
410
411
  if (isShared(limit)) {
411
412
  const rateLimiter = this.sharedRateLimiters[limit.name]
@@ -420,7 +421,7 @@ export class Server {
420
421
  } else {
421
422
  const { durationMs, points } = limit
422
423
  const rateLimiter = this.options.rateLimits?.creator({
423
- keyPrefix: nsid,
424
+ keyPrefix: `nsid-${i}`,
424
425
  durationMs,
425
426
  points,
426
427
  calcKey,
package/src/types.ts CHANGED
@@ -201,7 +201,13 @@ export class XRPCError extends Error {
201
201
  }
202
202
 
203
203
  export function isHandlerError(v: unknown): v is HandlerError {
204
- return handlerError.safeParse(v).success
204
+ return (
205
+ !!v &&
206
+ typeof v === 'object' &&
207
+ typeof v['status'] === 'number' &&
208
+ (v['error'] === undefined || typeof v['error'] === 'string') &&
209
+ (v['message'] === undefined || typeof v['message'] === 'string')
210
+ )
205
211
  }
206
212
 
207
213
  export class InvalidRequestError extends XRPCError {