@atproto/xrpc-server 0.4.4-next.0 → 0.4.4
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 +4 -6
- package/babel.config.js +1 -0
- package/build.js +14 -0
- package/dist/auth.d.ts +1 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +53682 -25
- package/dist/index.js.map +7 -1
- package/dist/logger.d.ts +0 -1
- package/dist/rate-limiter.d.ts +0 -1
- package/dist/server.d.ts +4 -5
- package/dist/stream/frames.d.ts +1 -2
- package/dist/stream/index.d.ts +0 -1
- package/dist/stream/logger.d.ts +0 -1
- package/dist/stream/server.d.ts +0 -2
- package/dist/stream/stream.d.ts +0 -1
- package/dist/stream/subscription.d.ts +0 -2
- package/dist/stream/types.d.ts +0 -1
- package/dist/stream/websocket-keepalive.d.ts +0 -2
- package/dist/types.d.ts +0 -2
- package/dist/util.d.ts +0 -1
- package/jest.config.js +3 -4
- package/package.json +11 -10
- package/src/auth.ts +1 -1
- package/src/server.ts +11 -11
- package/src/stream/frames.ts +1 -1
- package/src/stream/websocket-keepalive.ts +1 -2
- package/tests/bodies.test.ts +4 -4
- package/tests/errors.test.ts +1 -1
- package/tsconfig.build.json +2 -6
- package/tsconfig.json +11 -3
- package/dist/auth.d.ts.map +0 -1
- package/dist/auth.js +0 -124
- package/dist/auth.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -7
- package/dist/logger.js.map +0 -1
- package/dist/rate-limiter.d.ts.map +0 -1
- package/dist/rate-limiter.js +0 -166
- package/dist/rate-limiter.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -472
- package/dist/server.js.map +0 -1
- package/dist/stream/frames.d.ts.map +0 -1
- package/dist/stream/frames.js +0 -141
- package/dist/stream/frames.js.map +0 -1
- package/dist/stream/index.d.ts.map +0 -1
- package/dist/stream/index.js +0 -22
- package/dist/stream/index.js.map +0 -1
- package/dist/stream/logger.d.ts.map +0 -1
- package/dist/stream/logger.js +0 -7
- package/dist/stream/logger.js.map +0 -1
- package/dist/stream/server.d.ts.map +0 -1
- package/dist/stream/server.js +0 -70
- package/dist/stream/server.js.map +0 -1
- package/dist/stream/stream.d.ts.map +0 -1
- package/dist/stream/stream.js +0 -44
- package/dist/stream/stream.js.map +0 -1
- package/dist/stream/subscription.d.ts.map +0 -1
- package/dist/stream/subscription.js +0 -80
- package/dist/stream/subscription.js.map +0 -1
- package/dist/stream/types.d.ts.map +0 -1
- package/dist/stream/types.js +0 -47
- package/dist/stream/types.js.map +0 -1
- package/dist/stream/websocket-keepalive.d.ts.map +0 -1
- package/dist/stream/websocket-keepalive.js +0 -160
- package/dist/stream/websocket-keepalive.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -163
- package/dist/types.js.map +0 -1
- package/dist/util.d.ts.map +0 -1
- package/dist/util.js +0 -263
- package/dist/util.js.map +0 -1
- package/tsconfig.tests.json +0 -7
package/dist/rate-limiter.js
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getTightestLimit = exports.setResHeaders = exports.consumeMany = exports.formatLimiterStatus = exports.RateLimiter = void 0;
|
|
4
|
-
const rate_limiter_flexible_1 = require("rate-limiter-flexible");
|
|
5
|
-
const logger_1 = require("./logger");
|
|
6
|
-
const types_1 = require("./types");
|
|
7
|
-
class RateLimiter {
|
|
8
|
-
constructor(limiter, opts) {
|
|
9
|
-
Object.defineProperty(this, "limiter", {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
configurable: true,
|
|
12
|
-
writable: true,
|
|
13
|
-
value: void 0
|
|
14
|
-
});
|
|
15
|
-
Object.defineProperty(this, "bypassSecret", {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
configurable: true,
|
|
18
|
-
writable: true,
|
|
19
|
-
value: void 0
|
|
20
|
-
});
|
|
21
|
-
Object.defineProperty(this, "bypassIps", {
|
|
22
|
-
enumerable: true,
|
|
23
|
-
configurable: true,
|
|
24
|
-
writable: true,
|
|
25
|
-
value: void 0
|
|
26
|
-
});
|
|
27
|
-
Object.defineProperty(this, "failClosed", {
|
|
28
|
-
enumerable: true,
|
|
29
|
-
configurable: true,
|
|
30
|
-
writable: true,
|
|
31
|
-
value: void 0
|
|
32
|
-
});
|
|
33
|
-
Object.defineProperty(this, "calcKey", {
|
|
34
|
-
enumerable: true,
|
|
35
|
-
configurable: true,
|
|
36
|
-
writable: true,
|
|
37
|
-
value: void 0
|
|
38
|
-
});
|
|
39
|
-
Object.defineProperty(this, "calcPoints", {
|
|
40
|
-
enumerable: true,
|
|
41
|
-
configurable: true,
|
|
42
|
-
writable: true,
|
|
43
|
-
value: void 0
|
|
44
|
-
});
|
|
45
|
-
this.limiter = limiter;
|
|
46
|
-
this.bypassSecret = opts.bypassSecret;
|
|
47
|
-
this.bypassIps = opts.bypassIps;
|
|
48
|
-
this.calcKey = opts.calcKey ?? defaultKey;
|
|
49
|
-
this.calcPoints = opts.calcPoints ?? defaultPoints;
|
|
50
|
-
}
|
|
51
|
-
static memory(opts) {
|
|
52
|
-
const limiter = new rate_limiter_flexible_1.RateLimiterMemory({
|
|
53
|
-
keyPrefix: opts.keyPrefix,
|
|
54
|
-
duration: Math.floor(opts.durationMs / 1000),
|
|
55
|
-
points: opts.points,
|
|
56
|
-
});
|
|
57
|
-
return new RateLimiter(limiter, opts);
|
|
58
|
-
}
|
|
59
|
-
static redis(storeClient, opts) {
|
|
60
|
-
const limiter = new rate_limiter_flexible_1.RateLimiterRedis({
|
|
61
|
-
storeClient,
|
|
62
|
-
keyPrefix: opts.keyPrefix,
|
|
63
|
-
duration: Math.floor(opts.durationMs / 1000),
|
|
64
|
-
points: opts.points,
|
|
65
|
-
});
|
|
66
|
-
return new RateLimiter(limiter, opts);
|
|
67
|
-
}
|
|
68
|
-
async consume(ctx, opts) {
|
|
69
|
-
if (this.bypassSecret &&
|
|
70
|
-
ctx.req.header('x-ratelimit-bypass') === this.bypassSecret) {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
if (this.bypassIps && this.bypassIps.includes(ctx.req.ip)) {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
const key = opts?.calcKey ? opts.calcKey(ctx) : this.calcKey(ctx);
|
|
77
|
-
if (key === null) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
const points = opts?.calcPoints
|
|
81
|
-
? opts.calcPoints(ctx)
|
|
82
|
-
: this.calcPoints(ctx);
|
|
83
|
-
if (points < 1) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
try {
|
|
87
|
-
const res = await this.limiter.consume(key, points);
|
|
88
|
-
return (0, exports.formatLimiterStatus)(this.limiter, res);
|
|
89
|
-
}
|
|
90
|
-
catch (err) {
|
|
91
|
-
// yes this library rejects with a res not an error
|
|
92
|
-
if (err instanceof rate_limiter_flexible_1.RateLimiterRes) {
|
|
93
|
-
const status = (0, exports.formatLimiterStatus)(this.limiter, err);
|
|
94
|
-
return new types_1.RateLimitExceededError(status);
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
if (this.failClosed) {
|
|
98
|
-
throw err;
|
|
99
|
-
}
|
|
100
|
-
logger_1.logger.error({
|
|
101
|
-
err,
|
|
102
|
-
keyPrefix: this.limiter.keyPrefix,
|
|
103
|
-
points: this.limiter.points,
|
|
104
|
-
duration: this.limiter.duration,
|
|
105
|
-
}, 'rate limiter failed to consume points');
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
exports.RateLimiter = RateLimiter;
|
|
112
|
-
const formatLimiterStatus = (limiter, res) => {
|
|
113
|
-
return {
|
|
114
|
-
limit: limiter.points,
|
|
115
|
-
duration: limiter.duration,
|
|
116
|
-
remainingPoints: res.remainingPoints,
|
|
117
|
-
msBeforeNext: res.msBeforeNext,
|
|
118
|
-
consumedPoints: res.consumedPoints,
|
|
119
|
-
isFirstInDuration: res.isFirstInDuration,
|
|
120
|
-
};
|
|
121
|
-
};
|
|
122
|
-
exports.formatLimiterStatus = formatLimiterStatus;
|
|
123
|
-
const consumeMany = async (ctx, fns) => {
|
|
124
|
-
if (fns.length === 0)
|
|
125
|
-
return null;
|
|
126
|
-
const results = await Promise.all(fns.map((fn) => fn(ctx)));
|
|
127
|
-
const tightestLimit = (0, exports.getTightestLimit)(results);
|
|
128
|
-
if (tightestLimit === null) {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
else if (tightestLimit instanceof types_1.RateLimitExceededError) {
|
|
132
|
-
(0, exports.setResHeaders)(ctx, tightestLimit.status);
|
|
133
|
-
return tightestLimit;
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
(0, exports.setResHeaders)(ctx, tightestLimit);
|
|
137
|
-
return tightestLimit;
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
exports.consumeMany = consumeMany;
|
|
141
|
-
const setResHeaders = (ctx, status) => {
|
|
142
|
-
ctx.res.setHeader('RateLimit-Limit', status.limit);
|
|
143
|
-
ctx.res.setHeader('RateLimit-Remaining', status.remainingPoints);
|
|
144
|
-
ctx.res.setHeader('RateLimit-Reset', Math.floor((Date.now() + status.msBeforeNext) / 1000));
|
|
145
|
-
ctx.res.setHeader('RateLimit-Policy', `${status.limit};w=${status.duration}`);
|
|
146
|
-
};
|
|
147
|
-
exports.setResHeaders = setResHeaders;
|
|
148
|
-
const getTightestLimit = (resps) => {
|
|
149
|
-
let lowest = null;
|
|
150
|
-
for (const resp of resps) {
|
|
151
|
-
if (resp === null)
|
|
152
|
-
continue;
|
|
153
|
-
if (resp instanceof types_1.RateLimitExceededError)
|
|
154
|
-
return resp;
|
|
155
|
-
if (lowest === null || resp.remainingPoints < lowest.remainingPoints) {
|
|
156
|
-
lowest = resp;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return lowest;
|
|
160
|
-
};
|
|
161
|
-
exports.getTightestLimit = getTightestLimit;
|
|
162
|
-
// when using a proxy, ensure headers are getting forwarded correctly: `app.set('trust proxy', true)`
|
|
163
|
-
// https://expressjs.com/en/guide/behind-proxies.html
|
|
164
|
-
const defaultKey = (ctx) => ctx.req.ip;
|
|
165
|
-
const defaultPoints = () => 1;
|
|
166
|
-
//# sourceMappingURL=rate-limiter.js.map
|
package/dist/rate-limiter.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAgB,EAEd,OAAO,EACP,MAAM,EACN,OAAO,EACP,QAAQ,EAER,YAAY,EACZ,cAAc,EACf,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,UAAU,EACV,QAAQ,EAER,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACpB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAmC,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC5E,OAAO,EACL,WAAW,EAMX,iBAAiB,EAKjB,OAAO,EACP,uBAAuB,EACvB,iBAAiB,EAIjB,YAAY,EACZ,kBAAkB,EAInB,MAAM,SAAS,CAAA;AAUhB,wBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,EAAE,OAAO,CAAC,EAAE,OAAO,UAEtE;AAED,qBAAa,MAAM;IACjB,MAAM,EAAE,OAAO,CAAY;IAC3B,MAAM,EAAE,MAAM,CAAmB;IACjC,aAAa,gCAAsC;IACnD,GAAG,WAAiB;IACpB,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,CAAA;IACnD,kBAAkB,EAAE,YAAY,EAAE,CAAA;IAClC,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IAChD,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAA;gBAE7C,QAAQ,CAAC,EAAE,UAAU,EAAE,EAAE,IAAI,CAAC,EAAE,OAAO;IAyCnD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,GAAG,WAAW;IAIhE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,GAAG,WAAW;IAWnE,YAAY,CACV,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,uBAAuB,GAAG,iBAAiB;IAKzD,eAAe,CACb,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,uBAAuB,GAAG,iBAAiB;IAezD,UAAU,CAAC,GAAG,EAAE,UAAU;IAI1B,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE;cASd,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,YAAY,GAAG,gBAAgB,EACpC,MAAM,EAAE,iBAAiB;IAoBrB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY;IAsB/D,aAAa,CACX,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,YAAY,GAAG,gBAAgB,EACpC,QAAQ,EAAE,iBAAiB,GAC1B,cAAc;cAsHD,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,mBAAmB,EACxB,MAAM,EAAE,uBAAuB;IA4DjC,OAAO,CAAC,uBAAuB;IAmB/B,OAAO,CAAC,oBAAoB;CAiD7B"}
|
package/dist/server.js
DELETED
|
@@ -1,472 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Server = exports.createServer = void 0;
|
|
7
|
-
const stream_1 = require("stream");
|
|
8
|
-
const express_1 = __importDefault(require("express"));
|
|
9
|
-
const lexicon_1 = require("@atproto/lexicon");
|
|
10
|
-
const common_1 = require("@atproto/common");
|
|
11
|
-
const stream_2 = require("./stream");
|
|
12
|
-
const types_1 = require("./types");
|
|
13
|
-
const util_1 = require("./util");
|
|
14
|
-
const logger_1 = __importDefault(require("./logger"));
|
|
15
|
-
const rate_limiter_1 = require("./rate-limiter");
|
|
16
|
-
function createServer(lexicons, options) {
|
|
17
|
-
return new Server(lexicons, options);
|
|
18
|
-
}
|
|
19
|
-
exports.createServer = createServer;
|
|
20
|
-
class Server {
|
|
21
|
-
constructor(lexicons, opts) {
|
|
22
|
-
Object.defineProperty(this, "router", {
|
|
23
|
-
enumerable: true,
|
|
24
|
-
configurable: true,
|
|
25
|
-
writable: true,
|
|
26
|
-
value: (0, express_1.default)()
|
|
27
|
-
});
|
|
28
|
-
Object.defineProperty(this, "routes", {
|
|
29
|
-
enumerable: true,
|
|
30
|
-
configurable: true,
|
|
31
|
-
writable: true,
|
|
32
|
-
value: express_1.default.Router()
|
|
33
|
-
});
|
|
34
|
-
Object.defineProperty(this, "subscriptions", {
|
|
35
|
-
enumerable: true,
|
|
36
|
-
configurable: true,
|
|
37
|
-
writable: true,
|
|
38
|
-
value: new Map()
|
|
39
|
-
});
|
|
40
|
-
Object.defineProperty(this, "lex", {
|
|
41
|
-
enumerable: true,
|
|
42
|
-
configurable: true,
|
|
43
|
-
writable: true,
|
|
44
|
-
value: new lexicon_1.Lexicons()
|
|
45
|
-
});
|
|
46
|
-
Object.defineProperty(this, "options", {
|
|
47
|
-
enumerable: true,
|
|
48
|
-
configurable: true,
|
|
49
|
-
writable: true,
|
|
50
|
-
value: void 0
|
|
51
|
-
});
|
|
52
|
-
Object.defineProperty(this, "middleware", {
|
|
53
|
-
enumerable: true,
|
|
54
|
-
configurable: true,
|
|
55
|
-
writable: true,
|
|
56
|
-
value: void 0
|
|
57
|
-
});
|
|
58
|
-
Object.defineProperty(this, "globalRateLimiters", {
|
|
59
|
-
enumerable: true,
|
|
60
|
-
configurable: true,
|
|
61
|
-
writable: true,
|
|
62
|
-
value: void 0
|
|
63
|
-
});
|
|
64
|
-
Object.defineProperty(this, "sharedRateLimiters", {
|
|
65
|
-
enumerable: true,
|
|
66
|
-
configurable: true,
|
|
67
|
-
writable: true,
|
|
68
|
-
value: void 0
|
|
69
|
-
});
|
|
70
|
-
Object.defineProperty(this, "routeRateLimiterFns", {
|
|
71
|
-
enumerable: true,
|
|
72
|
-
configurable: true,
|
|
73
|
-
writable: true,
|
|
74
|
-
value: void 0
|
|
75
|
-
});
|
|
76
|
-
if (lexicons) {
|
|
77
|
-
this.addLexicons(lexicons);
|
|
78
|
-
}
|
|
79
|
-
this.router.use(this.routes);
|
|
80
|
-
this.router.use('/xrpc/:methodId', this.catchall.bind(this));
|
|
81
|
-
this.router.use(errorMiddleware);
|
|
82
|
-
this.router.once('mount', (app) => {
|
|
83
|
-
this.enableStreamingOnListen(app);
|
|
84
|
-
});
|
|
85
|
-
this.options = opts ?? {};
|
|
86
|
-
this.middleware = {
|
|
87
|
-
json: express_1.default.json({ limit: opts?.payload?.jsonLimit }),
|
|
88
|
-
text: express_1.default.text({ limit: opts?.payload?.textLimit }),
|
|
89
|
-
};
|
|
90
|
-
this.globalRateLimiters = [];
|
|
91
|
-
this.sharedRateLimiters = {};
|
|
92
|
-
this.routeRateLimiterFns = {};
|
|
93
|
-
if (opts?.rateLimits?.global) {
|
|
94
|
-
for (const limit of opts.rateLimits.global) {
|
|
95
|
-
const rateLimiter = opts.rateLimits.creator({
|
|
96
|
-
...limit,
|
|
97
|
-
keyPrefix: `rl-${limit.name}`,
|
|
98
|
-
});
|
|
99
|
-
this.globalRateLimiters.push(rateLimiter);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
if (opts?.rateLimits?.shared) {
|
|
103
|
-
for (const limit of opts.rateLimits.shared) {
|
|
104
|
-
const rateLimiter = opts.rateLimits.creator({
|
|
105
|
-
...limit,
|
|
106
|
-
keyPrefix: `rl-${limit.name}`,
|
|
107
|
-
});
|
|
108
|
-
this.sharedRateLimiters[limit.name] = rateLimiter;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// handlers
|
|
113
|
-
// =
|
|
114
|
-
method(nsid, configOrFn) {
|
|
115
|
-
this.addMethod(nsid, configOrFn);
|
|
116
|
-
}
|
|
117
|
-
addMethod(nsid, configOrFn) {
|
|
118
|
-
const config = typeof configOrFn === 'function' ? { handler: configOrFn } : configOrFn;
|
|
119
|
-
const def = this.lex.getDef(nsid);
|
|
120
|
-
if (def?.type === 'query' || def?.type === 'procedure') {
|
|
121
|
-
this.addRoute(nsid, def, config);
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
throw new Error(`Lex def for ${nsid} is not a query or a procedure`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
streamMethod(nsid, configOrFn) {
|
|
128
|
-
this.addStreamMethod(nsid, configOrFn);
|
|
129
|
-
}
|
|
130
|
-
addStreamMethod(nsid, configOrFn) {
|
|
131
|
-
const config = typeof configOrFn === 'function' ? { handler: configOrFn } : configOrFn;
|
|
132
|
-
const def = this.lex.getDef(nsid);
|
|
133
|
-
if (def?.type === 'subscription') {
|
|
134
|
-
this.addSubscription(nsid, def, config);
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
throw new Error(`Lex def for ${nsid} is not a subscription`);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
// schemas
|
|
141
|
-
// =
|
|
142
|
-
addLexicon(doc) {
|
|
143
|
-
this.lex.add(doc);
|
|
144
|
-
}
|
|
145
|
-
addLexicons(docs) {
|
|
146
|
-
for (const doc of docs) {
|
|
147
|
-
this.addLexicon(doc);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
// http
|
|
151
|
-
// =
|
|
152
|
-
async addRoute(nsid, def, config) {
|
|
153
|
-
const verb = def.type === 'procedure' ? 'post' : 'get';
|
|
154
|
-
const middleware = [];
|
|
155
|
-
middleware.push(createLocalsMiddleware(nsid));
|
|
156
|
-
if (config.auth) {
|
|
157
|
-
middleware.push(createAuthMiddleware(config.auth));
|
|
158
|
-
}
|
|
159
|
-
if (verb === 'post') {
|
|
160
|
-
middleware.push(this.middleware.json);
|
|
161
|
-
middleware.push(this.middleware.text);
|
|
162
|
-
}
|
|
163
|
-
this.setupRouteRateLimits(nsid, config);
|
|
164
|
-
this.routes[verb](`/xrpc/${nsid}`, ...middleware, this.createHandler(nsid, def, config));
|
|
165
|
-
}
|
|
166
|
-
async catchall(req, _res, next) {
|
|
167
|
-
const def = this.lex.getDef(req.params.methodId);
|
|
168
|
-
if (!def) {
|
|
169
|
-
return next(new types_1.MethodNotImplementedError());
|
|
170
|
-
}
|
|
171
|
-
// validate method
|
|
172
|
-
if (def.type === 'query' && req.method !== 'GET') {
|
|
173
|
-
return next(new types_1.InvalidRequestError(`Incorrect HTTP method (${req.method}) expected GET`));
|
|
174
|
-
}
|
|
175
|
-
else if (def.type === 'procedure' && req.method !== 'POST') {
|
|
176
|
-
return next(new types_1.InvalidRequestError(`Incorrect HTTP method (${req.method}) expected POST`));
|
|
177
|
-
}
|
|
178
|
-
return next();
|
|
179
|
-
}
|
|
180
|
-
createHandler(nsid, def, routeCfg) {
|
|
181
|
-
const routeOpts = {
|
|
182
|
-
blobLimit: routeCfg.opts?.blobLimit ?? this.options.payload?.blobLimit,
|
|
183
|
-
};
|
|
184
|
-
const validateReqInput = (req) => (0, util_1.validateInput)(nsid, def, req, routeOpts, this.lex);
|
|
185
|
-
const validateResOutput = this.options.validateResponse === false
|
|
186
|
-
? (output) => output
|
|
187
|
-
: (output) => (0, util_1.validateOutput)(nsid, def, output, this.lex);
|
|
188
|
-
const assertValidXrpcParams = (params) => this.lex.assertValidXrpcParams(nsid, params);
|
|
189
|
-
const rlFns = this.routeRateLimiterFns[nsid] ?? [];
|
|
190
|
-
const consumeRateLimit = (reqCtx) => (0, rate_limiter_1.consumeMany)(reqCtx, rlFns);
|
|
191
|
-
return async function (req, res, next) {
|
|
192
|
-
try {
|
|
193
|
-
// validate request
|
|
194
|
-
let params = (0, util_1.decodeQueryParams)(def, req.query);
|
|
195
|
-
try {
|
|
196
|
-
params = assertValidXrpcParams(params);
|
|
197
|
-
}
|
|
198
|
-
catch (e) {
|
|
199
|
-
throw new types_1.InvalidRequestError(String(e));
|
|
200
|
-
}
|
|
201
|
-
const input = validateReqInput(req);
|
|
202
|
-
if (input?.body instanceof stream_1.Readable) {
|
|
203
|
-
// If the body stream errors at any time, abort the request
|
|
204
|
-
input.body.once('error', next);
|
|
205
|
-
}
|
|
206
|
-
const locals = req[kRequestLocals];
|
|
207
|
-
const reqCtx = {
|
|
208
|
-
params,
|
|
209
|
-
input,
|
|
210
|
-
auth: locals.auth,
|
|
211
|
-
req,
|
|
212
|
-
res,
|
|
213
|
-
};
|
|
214
|
-
// handle rate limits
|
|
215
|
-
const result = await consumeRateLimit(reqCtx);
|
|
216
|
-
if (result instanceof types_1.RateLimitExceededError) {
|
|
217
|
-
return next(result);
|
|
218
|
-
}
|
|
219
|
-
// run the handler
|
|
220
|
-
const outputUnvalidated = await routeCfg.handler(reqCtx);
|
|
221
|
-
if ((0, types_1.isHandlerError)(outputUnvalidated)) {
|
|
222
|
-
throw types_1.XRPCError.fromError(outputUnvalidated);
|
|
223
|
-
}
|
|
224
|
-
if (outputUnvalidated && isHandlerPipeThrough(outputUnvalidated)) {
|
|
225
|
-
// set headers
|
|
226
|
-
if (outputUnvalidated?.headers) {
|
|
227
|
-
Object.entries(outputUnvalidated.headers).forEach(([name, val]) => {
|
|
228
|
-
res.header(name, val);
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
res
|
|
232
|
-
.header('Content-Type', outputUnvalidated.encoding)
|
|
233
|
-
.status(200)
|
|
234
|
-
.send(Buffer.from(outputUnvalidated.buffer));
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
if (!outputUnvalidated || isHandlerSuccess(outputUnvalidated)) {
|
|
238
|
-
// validate response
|
|
239
|
-
const output = validateResOutput(outputUnvalidated);
|
|
240
|
-
// set headers
|
|
241
|
-
if (output?.headers) {
|
|
242
|
-
Object.entries(output.headers).forEach(([name, val]) => {
|
|
243
|
-
res.header(name, val);
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
// send response
|
|
247
|
-
if (output?.encoding === 'application/json' ||
|
|
248
|
-
output?.encoding === 'json') {
|
|
249
|
-
const json = (0, lexicon_1.lexToJson)(output.body);
|
|
250
|
-
res.status(200).json(json);
|
|
251
|
-
}
|
|
252
|
-
else if (output?.body instanceof stream_1.Readable) {
|
|
253
|
-
res.header('Content-Type', output.encoding);
|
|
254
|
-
res.status(200);
|
|
255
|
-
res.once('error', (err) => res.destroy(err));
|
|
256
|
-
(0, common_1.forwardStreamErrors)(output.body, res);
|
|
257
|
-
output.body.pipe(res);
|
|
258
|
-
}
|
|
259
|
-
else if (output) {
|
|
260
|
-
res
|
|
261
|
-
.header('Content-Type', output.encoding)
|
|
262
|
-
.status(200)
|
|
263
|
-
.send(output.body instanceof Uint8Array
|
|
264
|
-
? Buffer.from(output.body)
|
|
265
|
-
: output.body);
|
|
266
|
-
}
|
|
267
|
-
else {
|
|
268
|
-
res.status(200).end();
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
catch (err) {
|
|
273
|
-
// Express will not call the next middleware (errorMiddleware in this case)
|
|
274
|
-
// if the value passed to next is falsy (e.g. null, undefined, 0).
|
|
275
|
-
// Hence we replace it with an InternalServerError.
|
|
276
|
-
if (!err) {
|
|
277
|
-
next(new types_1.InternalServerError());
|
|
278
|
-
}
|
|
279
|
-
else {
|
|
280
|
-
next(err);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
async addSubscription(nsid, def, config) {
|
|
286
|
-
const assertValidXrpcParams = (params) => this.lex.assertValidXrpcParams(nsid, params);
|
|
287
|
-
this.subscriptions.set(nsid, new stream_2.XrpcStreamServer({
|
|
288
|
-
noServer: true,
|
|
289
|
-
handler: async function* (req, signal) {
|
|
290
|
-
try {
|
|
291
|
-
// authenticate request
|
|
292
|
-
const auth = await config.auth?.({ req });
|
|
293
|
-
if ((0, types_1.isHandlerError)(auth)) {
|
|
294
|
-
throw types_1.XRPCError.fromError(auth);
|
|
295
|
-
}
|
|
296
|
-
// validate request
|
|
297
|
-
let params = (0, util_1.decodeQueryParams)(def, (0, util_1.getQueryParams)(req.url));
|
|
298
|
-
try {
|
|
299
|
-
params = assertValidXrpcParams(params);
|
|
300
|
-
}
|
|
301
|
-
catch (e) {
|
|
302
|
-
throw new types_1.InvalidRequestError(String(e));
|
|
303
|
-
}
|
|
304
|
-
// stream
|
|
305
|
-
const items = config.handler({ req, params, auth, signal });
|
|
306
|
-
for await (const item of items) {
|
|
307
|
-
if (item instanceof stream_2.Frame) {
|
|
308
|
-
yield item;
|
|
309
|
-
continue;
|
|
310
|
-
}
|
|
311
|
-
const type = item?.['$type'];
|
|
312
|
-
if (!common_1.check.is(item, common_1.schema.map) || typeof type !== 'string') {
|
|
313
|
-
yield new stream_2.MessageFrame(item);
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
const split = type.split('#');
|
|
317
|
-
let t;
|
|
318
|
-
if (split.length === 2 &&
|
|
319
|
-
(split[0] === '' || split[0] === nsid)) {
|
|
320
|
-
t = `#${split[1]}`;
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
t = type;
|
|
324
|
-
}
|
|
325
|
-
const clone = { ...item };
|
|
326
|
-
delete clone['$type'];
|
|
327
|
-
yield new stream_2.MessageFrame(clone, { type: t });
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
catch (err) {
|
|
331
|
-
const xrpcErrPayload = types_1.XRPCError.fromError(err).payload;
|
|
332
|
-
yield new stream_2.ErrorFrame({
|
|
333
|
-
error: xrpcErrPayload.error ?? 'Unknown',
|
|
334
|
-
message: xrpcErrPayload.message,
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
},
|
|
338
|
-
}));
|
|
339
|
-
}
|
|
340
|
-
enableStreamingOnListen(app) {
|
|
341
|
-
const _listen = app.listen;
|
|
342
|
-
app.listen = (...args) => {
|
|
343
|
-
// @ts-ignore the args spread
|
|
344
|
-
const httpServer = _listen.call(app, ...args);
|
|
345
|
-
httpServer.on('upgrade', (req, socket, head) => {
|
|
346
|
-
const url = new URL(req.url || '', 'http://x');
|
|
347
|
-
const sub = url.pathname.startsWith('/xrpc/')
|
|
348
|
-
? this.subscriptions.get(url.pathname.replace('/xrpc/', ''))
|
|
349
|
-
: undefined;
|
|
350
|
-
if (!sub)
|
|
351
|
-
return socket.destroy();
|
|
352
|
-
sub.wss.handleUpgrade(req, socket, head, (ws) => sub.wss.emit('connection', ws, req));
|
|
353
|
-
});
|
|
354
|
-
return httpServer;
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
setupRouteRateLimits(nsid, config) {
|
|
358
|
-
this.routeRateLimiterFns[nsid] = [];
|
|
359
|
-
for (const limit of this.globalRateLimiters) {
|
|
360
|
-
const consumeFn = async (ctx) => {
|
|
361
|
-
return limit.consume(ctx);
|
|
362
|
-
};
|
|
363
|
-
this.routeRateLimiterFns[nsid].push(consumeFn);
|
|
364
|
-
}
|
|
365
|
-
if (config.rateLimit) {
|
|
366
|
-
const limits = Array.isArray(config.rateLimit)
|
|
367
|
-
? config.rateLimit
|
|
368
|
-
: [config.rateLimit];
|
|
369
|
-
this.routeRateLimiterFns[nsid] = [];
|
|
370
|
-
for (let i = 0; i < limits.length; i++) {
|
|
371
|
-
const limit = limits[i];
|
|
372
|
-
const { calcKey, calcPoints } = limit;
|
|
373
|
-
if ((0, types_1.isShared)(limit)) {
|
|
374
|
-
const rateLimiter = this.sharedRateLimiters[limit.name];
|
|
375
|
-
if (rateLimiter) {
|
|
376
|
-
const consumeFn = (ctx) => rateLimiter.consume(ctx, {
|
|
377
|
-
calcKey,
|
|
378
|
-
calcPoints,
|
|
379
|
-
});
|
|
380
|
-
this.routeRateLimiterFns[nsid].push(consumeFn);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
else {
|
|
384
|
-
const { durationMs, points } = limit;
|
|
385
|
-
const rateLimiter = this.options.rateLimits?.creator({
|
|
386
|
-
keyPrefix: `nsid-${i}`,
|
|
387
|
-
durationMs,
|
|
388
|
-
points,
|
|
389
|
-
calcKey,
|
|
390
|
-
calcPoints,
|
|
391
|
-
});
|
|
392
|
-
if (rateLimiter) {
|
|
393
|
-
this.sharedRateLimiters[nsid] = rateLimiter;
|
|
394
|
-
const consumeFn = (ctx) => rateLimiter.consume(ctx, {
|
|
395
|
-
calcKey,
|
|
396
|
-
calcPoints,
|
|
397
|
-
});
|
|
398
|
-
this.routeRateLimiterFns[nsid].push(consumeFn);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
exports.Server = Server;
|
|
406
|
-
function isHandlerSuccess(v) {
|
|
407
|
-
return types_1.handlerSuccess.safeParse(v).success;
|
|
408
|
-
}
|
|
409
|
-
function isHandlerPipeThrough(v) {
|
|
410
|
-
if (v === null || typeof v !== 'object') {
|
|
411
|
-
return false;
|
|
412
|
-
}
|
|
413
|
-
if (!isString(v['encoding']) || !(v['buffer'] instanceof ArrayBuffer)) {
|
|
414
|
-
return false;
|
|
415
|
-
}
|
|
416
|
-
if (v['headers'] !== undefined) {
|
|
417
|
-
if (v['headers'] === null || typeof v['headers'] !== 'object') {
|
|
418
|
-
return false;
|
|
419
|
-
}
|
|
420
|
-
if (!Object.values(v['headers']).every(isString)) {
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
return true;
|
|
425
|
-
}
|
|
426
|
-
const isString = (val) => typeof val === 'string';
|
|
427
|
-
const kRequestLocals = Symbol('requestLocals');
|
|
428
|
-
function createLocalsMiddleware(nsid) {
|
|
429
|
-
return function (req, _res, next) {
|
|
430
|
-
const locals = { auth: undefined, nsid };
|
|
431
|
-
req[kRequestLocals] = locals;
|
|
432
|
-
return next();
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
function createAuthMiddleware(verifier) {
|
|
436
|
-
return async function (req, res, next) {
|
|
437
|
-
try {
|
|
438
|
-
const result = await verifier({ req, res });
|
|
439
|
-
if ((0, types_1.isHandlerError)(result)) {
|
|
440
|
-
throw types_1.XRPCError.fromError(result);
|
|
441
|
-
}
|
|
442
|
-
const locals = req[kRequestLocals];
|
|
443
|
-
locals.auth = result;
|
|
444
|
-
next();
|
|
445
|
-
}
|
|
446
|
-
catch (err) {
|
|
447
|
-
next(err);
|
|
448
|
-
}
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
const errorMiddleware = function (err, req, res, next) {
|
|
452
|
-
const locals = req[kRequestLocals];
|
|
453
|
-
const methodSuffix = locals ? ` method ${locals.nsid}` : '';
|
|
454
|
-
const xrpcError = types_1.XRPCError.fromError(err);
|
|
455
|
-
if (xrpcError instanceof types_1.InternalServerError) {
|
|
456
|
-
// log trace for unhandled exceptions
|
|
457
|
-
logger_1.default.error(err, `unhandled exception in xrpc${methodSuffix}`);
|
|
458
|
-
}
|
|
459
|
-
else {
|
|
460
|
-
// do not log trace for known xrpc errors
|
|
461
|
-
logger_1.default.error({
|
|
462
|
-
status: xrpcError.type,
|
|
463
|
-
message: xrpcError.message,
|
|
464
|
-
name: xrpcError.customErrorName,
|
|
465
|
-
}, `error in xrpc${methodSuffix}`);
|
|
466
|
-
}
|
|
467
|
-
if (res.headersSent) {
|
|
468
|
-
return next(err);
|
|
469
|
-
}
|
|
470
|
-
return res.status(xrpcError.type).json(xrpcError.payload);
|
|
471
|
-
};
|
|
472
|
-
//# sourceMappingURL=server.js.map
|