@atproto/xrpc-server 0.11.3 → 0.11.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 +8 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +13 -6
- package/dist/server.js.map +1 -1
- package/package.json +7 -7
- package/src/server.ts +21 -7
- package/tests/bodies.test.ts +13 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @atproto/xrpc-server
|
|
2
2
|
|
|
3
|
+
## 0.11.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#5156](https://github.com/bluesky-social/atproto/pull/5156) [`f2a0efe`](https://github.com/bluesky-social/atproto/commit/f2a0efe11140c8bebe488ac1f737e242d7f23f0b) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add more details to the xrpc-server log errors
|
|
8
|
+
|
|
9
|
+
- [#5156](https://github.com/bluesky-social/atproto/pull/5156) [`f2a0efe`](https://github.com/bluesky-social/atproto/commit/f2a0efe11140c8bebe488ac1f737e242d7f23f0b) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add explicit error message when using invalid HTTP verb with xrpc methods defined using `.add()`
|
|
10
|
+
|
|
3
11
|
## 0.11.3
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -108,9 +108,15 @@ export class Server {
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
addProcedureSchema(schema, config) {
|
|
111
|
+
this.routes.get(`/xrpc/${schema.nsid}`, (req, res, next) => {
|
|
112
|
+
next(new InvalidRequestError(`Incorrect HTTP method (${req.method}) expected POST`));
|
|
113
|
+
});
|
|
111
114
|
this.routes.post(`/xrpc/${schema.nsid}`, this.createHandlerInternal(this.createAuthVerifier(config), this.createSchemaParamsVerifier(schema, config.opts), this.createSchemaInputVerifier(schema, config.opts), this.createRouteRateLimiter(schema.nsid, config), config.handler, this.createSchemaOutputVerifier(schema)));
|
|
112
115
|
}
|
|
113
116
|
addQuerySchema(schema, config) {
|
|
117
|
+
this.routes.post(`/xrpc/${schema.nsid}`, (req, res, next) => {
|
|
118
|
+
next(new InvalidRequestError(`Incorrect HTTP method (${req.method}) expected GET`));
|
|
119
|
+
});
|
|
114
120
|
this.routes.get(`/xrpc/${schema.nsid}`, this.createHandlerInternal(this.createAuthVerifier(config), this.createSchemaParamsVerifier(schema, config.opts), this.createSchemaInputVerifier(schema, config.opts), this.createRouteRateLimiter(schema.nsid, config), config.handler, this.createSchemaOutputVerifier(schema)));
|
|
115
121
|
}
|
|
116
122
|
addSubscriptionSchema(schema, config) {
|
|
@@ -406,14 +412,15 @@ function createErrorMiddleware({ errorParser = (err) => XRPCError.fromError(err)
|
|
|
406
412
|
// Use the request's logger (if available) to benefit from request context
|
|
407
413
|
// (id, timing) and logging configuration (serialization, etc.).
|
|
408
414
|
const logger = isPinoHttpRequest(req) ? req.log : log;
|
|
409
|
-
const
|
|
410
|
-
const
|
|
411
|
-
const
|
|
412
|
-
const msg = `${
|
|
415
|
+
const msgError = xrpcError.error || 'Unknown';
|
|
416
|
+
const msgLoc = nsid ? `xrpc method ${nsid}` : `${req.method} ${req.url}`;
|
|
417
|
+
const msgDetail = xrpcError.message ? ` (${xrpcError.message})` : '';
|
|
418
|
+
const msg = `${msgError} error in ${msgLoc}${msgDetail}`;
|
|
413
419
|
logger.error({
|
|
414
420
|
// @NOTE Computation of error stack is an expensive operation, so
|
|
415
|
-
// we strip it for expected errors.
|
|
416
|
-
err:
|
|
421
|
+
// we strip it for expected (non-server) errors.
|
|
422
|
+
err: xrpcError instanceof InternalServerError ||
|
|
423
|
+
process.env.NODE_ENV === 'development'
|
|
417
424
|
? err
|
|
418
425
|
: toSimplifiedErrorLike(err),
|
|
419
426
|
// XRPC specific properties, for easier browsing of logs
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { IncomingMessage } from 'node:http'\nimport { Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport express, {\n Application,\n ErrorRequestHandler,\n Express,\n RequestHandler,\n Router,\n} from 'express'\nimport { LexValue } from '@atproto/lex-data'\nimport { l } from '@atproto/lex-schema'\nimport {\n LexXrpcProcedure,\n LexXrpcQuery,\n LexXrpcSubscription,\n LexiconDoc,\n Lexicons,\n lexToJson,\n} from '@atproto/lexicon'\nimport {\n InternalServerError,\n InvalidRequestError,\n MethodNotImplementedError,\n XRPCError,\n excludeErrorResult,\n} from './errors.js'\nimport log, { LOGGER_NAME } from './logger.js'\nimport { HttpRateLimiter } from './rate-limiter-http.js'\nimport {\n CalcKeyFn,\n CalcPointsFn,\n RateLimiterErrorHandlerDetails,\n RateLimiterI,\n RateLimiterOptions,\n WrappedRateLimiter,\n} from './rate-limiter.js'\nimport {\n ErrorFrame,\n Frame,\n MessageFrame,\n XrpcStreamServer,\n} from './stream/index.js'\nimport {\n Auth,\n AuthResult,\n AuthVerifier,\n CatchallHandler,\n HandlerContext,\n Input,\n LexMethodConfig,\n LexMethodHandler,\n LexMethodInput,\n LexMethodOutput,\n LexMethodParams,\n LexSubscriptionConfig,\n LexSubscriptionHandler,\n MethodAuthContext,\n MethodConfig,\n MethodConfigOrHandler,\n MethodHandler,\n Options,\n Output,\n Params,\n RouteOptions,\n ServerRateLimitDescription,\n StreamAuthContext,\n StreamConfig,\n StreamConfigOrHandler,\n StreamContext,\n isHandlerPipeThroughBuffer,\n isHandlerPipeThroughStream,\n isHandlerSuccess,\n isSharedRateLimitOpts,\n} from './types.js'\nimport {\n AuthVerifierInternal,\n InputVerifierInternal,\n OutputVerifierInternal,\n ParamsVerifierInternal,\n asArray,\n createLexiconInputVerifier,\n createLexiconOutputVerifier,\n createLexiconParamsVerifier,\n createSchemaInputVerifier,\n createSchemaOutputVerifier,\n createSchemaParamsVerifier,\n extractUrlNsid,\n setHeaders,\n} from './util.js'\n\nexport function createServer(lexicons?: LexiconDoc[], options?: Options) {\n return new Server(lexicons, options)\n}\n\nexport class Server {\n router: Express = express()\n routes: Router = Router()\n subscriptions = new Map<string, XrpcStreamServer>()\n lex = new Lexicons()\n options: Options\n globalRateLimiter?: HttpRateLimiter<HandlerContext>\n sharedRateLimiters?: Map<string, RateLimiterI<HandlerContext>>\n\n constructor(lexicons?: LexiconDoc[], opts: Options = {}) {\n if (lexicons) {\n this.addLexicons(lexicons)\n }\n this.router.use(this.routes)\n this.router.use(this.catchall)\n this.router.use(createErrorMiddleware(opts))\n this.router.once('mount', (app: Application) => {\n this.enableStreamingOnListen(app)\n })\n this.options = opts\n\n if (opts.rateLimits) {\n const { global, shared, creator, bypass } = opts.rateLimits\n\n if (global) {\n this.globalRateLimiter = HttpRateLimiter.from(\n global.map((options) => creator(buildRateLimiterOptions(options))),\n { bypass },\n )\n }\n\n if (shared) {\n this.sharedRateLimiters = new Map(\n shared.map((options) => [\n options.name,\n creator(buildRateLimiterOptions(options)),\n ]),\n )\n }\n }\n }\n\n listen(port: number, callback?: () => void) {\n return this.router.listen(port, callback)\n }\n\n // handlers\n // =\n\n // Routes with auth\n add<M extends l.Procedure | l.Query | l.Subscription, A extends AuthResult>(\n ns: l.Main<M>,\n config: M extends l.Procedure | l.Query\n ? LexMethodConfig<M, A> & { auth: Exclude<unknown, void> }\n : M extends l.Subscription\n ? LexSubscriptionConfig<M, A> & { auth: Exclude<unknown, void> }\n : never,\n ): void\n // Routes without auth\n add<M extends l.Procedure | l.Query | l.Subscription>(\n ns: l.Main<M>,\n config: M extends l.Procedure | l.Query\n ? LexMethodConfig<M, void> | LexMethodHandler<M, void>\n : M extends l.Subscription\n ? LexSubscriptionConfig<M, void> | LexSubscriptionHandler<M, void>\n : never,\n ): void\n add<M extends l.Procedure | l.Query | l.Subscription, A extends Auth>(\n ns: l.Main<M>,\n configOfHandler: M extends l.Procedure | l.Query\n ? LexMethodConfig<M, A> | LexMethodHandler<M, A>\n : M extends l.Subscription\n ? LexSubscriptionConfig<M, A> | LexSubscriptionHandler<M, A>\n : never,\n ): void {\n const schema = l.getMain(ns)\n const config =\n typeof configOfHandler === 'function'\n ? { handler: configOfHandler }\n : configOfHandler\n switch (schema.type) {\n case 'procedure':\n return this.addProcedureSchema(\n schema,\n config as LexMethodConfig<l.Procedure, A>,\n )\n case 'query':\n return this.addQuerySchema(\n schema,\n config as LexMethodConfig<l.Query, A>,\n )\n case 'subscription':\n return this.addSubscriptionSchema(\n schema,\n config as LexSubscriptionConfig<l.Subscription, A>,\n )\n default:\n throw new TypeError(\n // @ts-expect-error should never happen\n `Unsupported schema ${schema.nsid} of type ${schema.type}`,\n )\n }\n }\n\n protected addProcedureSchema<M extends l.Procedure, A extends Auth>(\n schema: M,\n config: LexMethodConfig<M, A>,\n ): void {\n this.routes.post(\n `/xrpc/${schema.nsid}`,\n this.createHandlerInternal<\n A,\n LexMethodParams<M>,\n LexMethodInput<M>,\n LexMethodOutput<M>\n >(\n this.createAuthVerifier(config),\n this.createSchemaParamsVerifier(schema, config.opts),\n this.createSchemaInputVerifier(schema, config.opts),\n this.createRouteRateLimiter(schema.nsid, config),\n config.handler,\n this.createSchemaOutputVerifier(schema),\n ),\n )\n }\n\n protected addQuerySchema<M extends l.Query, A extends Auth>(\n schema: M,\n config: LexMethodConfig<M, A>,\n ): void {\n this.routes.get(\n `/xrpc/${schema.nsid}`,\n this.createHandlerInternal<\n A,\n LexMethodParams<M>,\n LexMethodInput<M>,\n LexMethodOutput<M>\n >(\n this.createAuthVerifier(config),\n this.createSchemaParamsVerifier(schema, config.opts),\n this.createSchemaInputVerifier(schema, config.opts),\n this.createRouteRateLimiter(schema.nsid, config),\n config.handler,\n this.createSchemaOutputVerifier(schema),\n ),\n )\n }\n\n protected addSubscriptionSchema<\n M extends l.Subscription,\n A extends Auth = void,\n >(schema: M, config: LexSubscriptionConfig<M, A>): void {\n const { handler } = config\n const messageSchema =\n this.options.validateResponse === false ? undefined : schema.message\n\n return this.addSubscriptionInternal(\n schema.nsid,\n this.createSchemaParamsVerifier(schema),\n this.createAuthVerifier(config),\n // Wrap the handler to validate outgoing messages if a message schema\n // is available\n messageSchema\n ? async function* (ctx) {\n for await (const item of handler(ctx)) {\n if (item instanceof Frame) {\n messageSchema.validate(item.body)\n yield item\n } else {\n yield messageSchema.validate(item)\n }\n }\n }\n : handler,\n )\n }\n\n method<A extends Auth = Auth>(\n nsid: string,\n configOrFn: MethodConfigOrHandler<A>,\n ): void {\n this.addMethod(nsid, configOrFn)\n }\n\n addMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: MethodConfigOrHandler<A>,\n ) {\n const config =\n typeof configOrFn === 'function' ? { handler: configOrFn } : configOrFn\n if (config.opts && 'paramsParseLoose' in config.opts) {\n throw new Error(\n `paramsParseLoose is not supported with method(), use add() instead`,\n )\n }\n const def = this.lex.getDef(nsid)\n if (def?.type === 'query' || def?.type === 'procedure') {\n this.addRoute(nsid, def, config)\n } else {\n throw new Error(`Lex def for ${nsid} is not a query or a procedure`)\n }\n }\n\n streamMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: StreamConfigOrHandler<A, Params>,\n ) {\n this.addStreamMethod(nsid, configOrFn)\n }\n\n addStreamMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: StreamConfigOrHandler<A, Params>,\n ) {\n const config =\n typeof configOrFn === 'function' ? { handler: configOrFn } : configOrFn\n const def = this.lex.getDef(nsid)\n if (def?.type === 'subscription') {\n this.addSubscription(nsid, def, config)\n } else {\n throw new Error(`Lex def for ${nsid} is not a subscription`)\n }\n }\n\n // schemas\n // =\n\n addLexicon(doc: LexiconDoc) {\n this.lex.add(doc)\n }\n\n addLexicons(docs: LexiconDoc[]) {\n for (const doc of docs) {\n this.addLexicon(doc)\n }\n }\n\n // http\n // =\n\n protected async addRoute<A extends Auth = Auth>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n config: MethodConfig<A>,\n ) {\n const path = `/xrpc/${nsid}`\n const handler = this.createHandler(nsid, def, config)\n\n if (def.type === 'procedure') {\n this.routes.post(path, handler)\n } else {\n this.routes.get(path, handler)\n }\n }\n\n catchall: CatchallHandler = async (req, res, next) => {\n // catchall handler only applies to XRPC routes\n if (!req.url.startsWith('/xrpc/')) return next()\n\n // Validate the NSID\n const nsid = extractUrlNsid(req.url)\n if (!nsid) {\n return next(new InvalidRequestError('invalid xrpc path'))\n }\n\n if (this.globalRateLimiter) {\n try {\n await this.globalRateLimiter.handle({\n req,\n res,\n auth: undefined,\n params: {},\n input: undefined,\n async resetRouteRateLimits() {},\n })\n } catch (err) {\n return next(err)\n }\n }\n\n // Ensure that known XRPC methods are only called with the correct HTTP\n // method.\n const def = this.lex.getDef(nsid)\n if (def) {\n const expectedMethod =\n def.type === 'procedure' ? 'POST' : def.type === 'query' ? 'GET' : null\n if (expectedMethod != null && expectedMethod !== req.method) {\n return next(\n new InvalidRequestError(\n `Incorrect HTTP method (${req.method}) expected ${expectedMethod}`,\n ),\n )\n }\n }\n\n if (this.options.catchall) {\n this.options.catchall.call(null, req, res, next)\n } else if (!def) {\n next(new MethodNotImplementedError())\n } else {\n next()\n }\n }\n\n createHandler<\n A extends Auth = Auth,\n P extends Params = Params,\n I extends Input = Input,\n O extends Output = Output,\n >(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n cfg: MethodConfig<A, P, I, O>,\n ): RequestHandler {\n return this.createHandlerInternal<A, P, I, O>(\n this.createAuthVerifier(cfg),\n this.createLexiconParamsVerifier<P>(nsid, def),\n this.createLexiconInputVerifier<I>(nsid, def, cfg.opts),\n this.createRouteRateLimiter(nsid, cfg),\n cfg.handler,\n this.createLexiconOutputVerifier<O>(nsid, def),\n )\n }\n\n protected createHandlerInternal<\n A extends Auth,\n P extends Params,\n I extends Input,\n O extends Output,\n >(\n authVerifier: AuthVerifierInternal<MethodAuthContext<P>, A> | null,\n paramsVerifier: ParamsVerifierInternal<P>,\n inputVerifier: InputVerifierInternal<I>,\n routeLimiter: HttpRateLimiter<HandlerContext<A, P, I>> | undefined,\n handler: MethodHandler<A, P, I, O>,\n validateResOutput: null | OutputVerifierInternal<O>,\n ): RequestHandler {\n return async function (req, res, next) {\n try {\n // parse & validate params\n const params = paramsVerifier(req)\n\n // authenticate request\n const auth: A = authVerifier\n ? await authVerifier({ req, res, params })\n : (undefined as A)\n\n // parse & validate input\n const input: I = await inputVerifier(req, res)\n\n const ctx: HandlerContext<A, P, I> = {\n params,\n input,\n auth,\n req,\n res,\n resetRouteRateLimits: async () => routeLimiter?.reset(ctx),\n }\n\n // handle rate limits\n if (routeLimiter) await routeLimiter.handle(ctx)\n\n // run the handler\n const output = (await handler(ctx)) as O\n\n if (!output) {\n validateResOutput?.(output)\n res.status(200)\n res.end()\n } else if (isHandlerPipeThroughStream(output)) {\n setHeaders(res, output.headers)\n res.status(200)\n res.header('Content-Type', output.encoding)\n await pipeline(output.stream, res)\n } else if (isHandlerPipeThroughBuffer(output)) {\n setHeaders(res, output.headers)\n res.status(200)\n res.header('Content-Type', output.encoding)\n res.end(output.buffer)\n } else if (isHandlerSuccess(output)) {\n validateResOutput?.(output)\n\n res.status(200)\n setHeaders(res, output.headers)\n\n const encoding =\n output.encoding === 'json' ? 'application/json' : output.encoding\n\n res.header('Content-Type', encoding)\n\n if (output.body instanceof Readable) {\n // The \"Readable\" check comes first to avoid calling \"lexToJson\" on\n // a stream, which would be a bug.\n await pipeline(output.body, res)\n } else if (encoding === 'application/json') {\n const json = lexToJson(output.body)\n res.json(json)\n } else {\n res.send(\n Buffer.isBuffer(output.body)\n ? output.body\n : output.body instanceof Uint8Array\n ? Buffer.from(output.body)\n : output.body,\n )\n }\n } else {\n next(XRPCError.fromError(output))\n }\n } catch (err: unknown) {\n // Express will not call the next middleware (errorMiddleware in this case)\n // if the value passed to next is false-y (e.g. null, undefined, 0).\n // Hence we replace it with an InternalServerError.\n if (!err) {\n next(new InternalServerError())\n } else {\n next(err)\n }\n }\n }\n }\n\n protected async addSubscription<A extends Auth = Auth>(\n nsid: string,\n def: LexXrpcSubscription,\n cfg: StreamConfig<A, Params>,\n ) {\n this.addSubscriptionInternal(\n nsid,\n this.createLexiconParamsVerifier(nsid, def),\n this.createAuthVerifier(cfg),\n // @NOTE outgoing messages are not validated against the lexicon schema\n // (unlike the handlers for @atproto/lex based subscriptions)\n cfg.handler,\n )\n }\n\n protected addSubscriptionInternal<A extends Auth, P extends Params>(\n nsid: string,\n paramsVerifier: ParamsVerifierInternal<P>,\n authVerifier: AuthVerifierInternal<StreamAuthContext<P>, A> | null,\n handler: (ctx: StreamContext<A, P>) => AsyncIterable<unknown>,\n ) {\n this.subscriptions.set(\n nsid,\n new XrpcStreamServer({\n noServer: true,\n handler: async function* (req, signal) {\n try {\n // validate request\n const params = paramsVerifier(req)\n\n // authenticate request\n const auth = authVerifier\n ? await authVerifier({ req, params })\n : (undefined as A)\n\n // stream\n for await (const item of handler({ req, params, auth, signal })) {\n yield item instanceof Frame\n ? item\n : MessageFrame.fromLexValue(item as LexValue, nsid)\n }\n } catch (err) {\n yield ErrorFrame.fromError(err)\n }\n },\n }),\n )\n }\n\n private createAuthVerifier<C, A extends AuthResult>(cfg: {\n auth?: AuthVerifier<C, A>\n }): null | AuthVerifierInternal<C, A> {\n const { auth } = cfg\n if (!auth) return null\n\n return async (ctx) => {\n const result = await auth(ctx)\n return excludeErrorResult(result)\n }\n }\n\n private createLexiconParamsVerifier<P extends Params = Params>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure | LexXrpcSubscription,\n ) {\n return createLexiconParamsVerifier<P>(nsid, def, this.lex)\n }\n\n private createLexiconInputVerifier<I extends Input = Input>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n opts?: RouteOptions,\n ): InputVerifierInternal<I> {\n return createLexiconInputVerifier(\n nsid,\n def,\n {\n blobLimit: opts?.blobLimit ?? this.options.payload?.blobLimit,\n jsonLimit: opts?.jsonLimit ?? this.options.payload?.jsonLimit,\n textLimit: opts?.textLimit ?? this.options.payload?.textLimit,\n },\n this.lex,\n )\n }\n\n private createLexiconOutputVerifier<O extends Output = Output>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n ): null | OutputVerifierInternal<O> {\n if (this.options.validateResponse === false) {\n return null\n }\n return createLexiconOutputVerifier(nsid, def, this.lex)\n }\n\n private createSchemaParamsVerifier<\n M extends l.Procedure | l.Query | l.Subscription,\n >(\n ns: l.Main<M>,\n opts?: RouteOptions,\n ): ParamsVerifierInternal<LexMethodParams<M>> {\n return createSchemaParamsVerifier<M>(ns, opts)\n }\n\n private createSchemaInputVerifier<M extends l.Procedure | l.Query>(\n ns: l.Main<M>,\n opts?: RouteOptions,\n ): InputVerifierInternal<LexMethodInput<M>> {\n return createSchemaInputVerifier<M>(ns, {\n blobLimit: opts?.blobLimit ?? this.options.payload?.blobLimit,\n jsonLimit: opts?.jsonLimit ?? this.options.payload?.jsonLimit,\n textLimit: opts?.textLimit ?? this.options.payload?.textLimit,\n })\n }\n\n private createSchemaOutputVerifier<M extends l.Procedure | l.Query>(\n ns: l.Main<M>,\n ): null | OutputVerifierInternal<LexMethodOutput<M>> {\n if (this.options.validateResponse === false) {\n return null\n }\n return createSchemaOutputVerifier<M>(ns)\n }\n\n private enableStreamingOnListen(app: Application) {\n const _listen = app.listen\n app.listen = (...args) => {\n // @ts-ignore the args spread\n const httpServer = _listen.call(app, ...args)\n httpServer.on('upgrade', (req, socket, head) => {\n const nsid = req.url ? extractUrlNsid(req.url) : undefined\n const sub = nsid ? this.subscriptions.get(nsid) : undefined\n if (!sub) return socket.destroy()\n sub.wss.handleUpgrade(req, socket, head, (ws) =>\n sub.wss.emit('connection', ws, req),\n )\n })\n return httpServer\n }\n }\n\n private createRouteRateLimiter<\n A extends Auth,\n P extends Params,\n I extends Input,\n O extends Output,\n >(\n nsid: string,\n config: MethodConfig<A, P, I, O>,\n ): HttpRateLimiter<HandlerContext<A, P, I>> | undefined {\n // @NOTE global & shared rate limiters are instantiated with a context of\n // HandlerContext which is compatible (more generic) with the context of\n // this route specific rate limiters (C). For this reason, it's safe to cast\n // the context of the global rate limiter to the context of the route\n // specific rate limiter (HandlerContext<A, P, I>).\n\n const globalRateLimiter = this.globalRateLimiter as\n | HttpRateLimiter<HandlerContext<A, P, I>>\n | undefined\n\n // No route specific rate limiting configured, use the global rate limiter.\n if (!config.rateLimit) return globalRateLimiter\n\n const { rateLimits } = this.options\n\n // @NOTE Silently ignore creation of route specific rate limiter if the\n // `rateLimits` options was not provided to the constructor.\n if (!rateLimits) return globalRateLimiter\n\n const { creator, bypass } = rateLimits\n\n const rateLimiters = asArray(config.rateLimit).map((options, i) => {\n if (isSharedRateLimitOpts(options)) {\n const rateLimiter = this.sharedRateLimiters?.get(options.name) as\n | RateLimiterI<HandlerContext<A, P, I>>\n | undefined\n\n // The route config references a shared rate limiter that does not\n // exist. This is a configuration error.\n assert(rateLimiter, `Shared rate limiter \"${options.name}\" not defined`)\n\n return WrappedRateLimiter.from<HandlerContext<A, P, I>>(\n rateLimiter,\n options,\n )\n } else {\n return creator({\n ...options,\n calcKey: options.calcKey ?? defaultKey,\n calcPoints: options.calcPoints ?? defaultPoints,\n keyPrefix: `${nsid}-${i}`,\n })\n }\n })\n\n // If the route config contains an empty array, use global rate limiter.\n if (!rateLimiters.length) return globalRateLimiter\n\n // The global rate limiter (if present) should be applied in addition to\n // the route specific rate limiters.\n if (globalRateLimiter) rateLimiters.push(globalRateLimiter)\n\n return HttpRateLimiter.from<HandlerContext<A, P, I>>(rateLimiters, {\n bypass,\n })\n }\n}\n\nfunction createErrorMiddleware({\n errorParser = (err) => XRPCError.fromError(err),\n}: Options): ErrorRequestHandler {\n return (err, req, res, next) => {\n const nsid = extractUrlNsid(req.originalUrl)\n const xrpcError = errorParser(err)\n\n // Use the request's logger (if available) to benefit from request context\n // (id, timing) and logging configuration (serialization, etc.).\n const logger = isPinoHttpRequest(req) ? req.log : log\n\n const isInternalError = xrpcError instanceof InternalServerError\n\n const msgPrefix = isInternalError ? 'unhandled exception' : 'error'\n const msgSuffix = nsid ? `xrpc method ${nsid}` : `${req.method} ${req.url}`\n const msg = `${msgPrefix} in ${msgSuffix}`\n\n logger.error(\n {\n // @NOTE Computation of error stack is an expensive operation, so\n // we strip it for expected errors.\n err:\n isInternalError || process.env.NODE_ENV === 'development'\n ? err\n : toSimplifiedErrorLike(err),\n\n // XRPC specific properties, for easier browsing of logs\n nsid,\n type: xrpcError.type,\n status: xrpcError.statusCode,\n payload: xrpcError.payload,\n\n // Ensure that the logged item's name is set to LOGGER_NAME, instead of\n // the name of the pino-http logger, to ensure consistency across logs.\n name: LOGGER_NAME,\n },\n msg,\n )\n\n if (res.headersSent) {\n return next(err)\n }\n\n return res.status(xrpcError.statusCode).json(xrpcError.payload)\n }\n}\n\nfunction isPinoHttpRequest(req: IncomingMessage): req is IncomingMessage & {\n log: { error: (obj: unknown, msg: string) => void }\n} {\n return typeof (req as { log?: any }).log?.error === 'function'\n}\n\nfunction toSimplifiedErrorLike(err: unknown): unknown {\n if (err instanceof Error) {\n // Transform into an \"ErrorLike\" for pino's std \"err\" serializer\n return {\n ...err,\n // Carry over non-enumerable properties\n message: err.message,\n name:\n !Object.hasOwn(err, 'name') &&\n Object.prototype.toString.call(err.constructor) === '[object Function]'\n ? err.constructor.name // extract the class name for sub-classes of Error\n : err.name,\n // @NOTE Error.stack, Error.cause and AggregateError.error are non\n // enumerable properties so they won't be spread to the ErrorLike\n }\n }\n\n return err\n}\n\nfunction buildRateLimiterOptions<C extends HandlerContext = HandlerContext>({\n name,\n calcKey = defaultKey,\n calcPoints = defaultPoints,\n failClosed = false,\n durationMs,\n points,\n}: ServerRateLimitDescription<C>): RateLimiterOptions<C> {\n return {\n durationMs,\n points,\n calcKey,\n calcPoints,\n keyPrefix: `rl-${name}`,\n onError: failClosed\n ? undefined // Let the error propagate\n : rateLimiterLoggerErrorHandler,\n }\n}\n\nconst defaultPoints: CalcPointsFn = () => 1\n\n/**\n * @note when using a proxy, ensure headers are getting forwarded correctly:\n * `app.set('trust proxy', true)`\n *\n * @see {@link https://expressjs.com/en/guide/behind-proxies.html}\n */\nconst defaultKey: CalcKeyFn<HandlerContext> = ({ req }) => req.ip\n\nasync function rateLimiterLoggerErrorHandler(\n err: unknown,\n ctx: HandlerContext,\n { limiter: { keyPrefix, points, duration } }: RateLimiterErrorHandlerDetails,\n): Promise<null> {\n const { req } = ctx\n const logger = isPinoHttpRequest(req) ? req.log : log\n\n logger.error(\n { err, keyPrefix, points, duration },\n 'rate limiter failed to consume points',\n )\n\n return null\n}\n"]}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { IncomingMessage } from 'node:http'\nimport { Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport express, {\n Application,\n ErrorRequestHandler,\n Express,\n RequestHandler,\n Router,\n} from 'express'\nimport { LexValue } from '@atproto/lex-data'\nimport { l } from '@atproto/lex-schema'\nimport {\n LexXrpcProcedure,\n LexXrpcQuery,\n LexXrpcSubscription,\n LexiconDoc,\n Lexicons,\n lexToJson,\n} from '@atproto/lexicon'\nimport {\n InternalServerError,\n InvalidRequestError,\n MethodNotImplementedError,\n XRPCError,\n excludeErrorResult,\n} from './errors.js'\nimport log, { LOGGER_NAME } from './logger.js'\nimport { HttpRateLimiter } from './rate-limiter-http.js'\nimport {\n CalcKeyFn,\n CalcPointsFn,\n RateLimiterErrorHandlerDetails,\n RateLimiterI,\n RateLimiterOptions,\n WrappedRateLimiter,\n} from './rate-limiter.js'\nimport {\n ErrorFrame,\n Frame,\n MessageFrame,\n XrpcStreamServer,\n} from './stream/index.js'\nimport {\n Auth,\n AuthResult,\n AuthVerifier,\n CatchallHandler,\n HandlerContext,\n Input,\n LexMethodConfig,\n LexMethodHandler,\n LexMethodInput,\n LexMethodOutput,\n LexMethodParams,\n LexSubscriptionConfig,\n LexSubscriptionHandler,\n MethodAuthContext,\n MethodConfig,\n MethodConfigOrHandler,\n MethodHandler,\n Options,\n Output,\n Params,\n RouteOptions,\n ServerRateLimitDescription,\n StreamAuthContext,\n StreamConfig,\n StreamConfigOrHandler,\n StreamContext,\n isHandlerPipeThroughBuffer,\n isHandlerPipeThroughStream,\n isHandlerSuccess,\n isSharedRateLimitOpts,\n} from './types.js'\nimport {\n AuthVerifierInternal,\n InputVerifierInternal,\n OutputVerifierInternal,\n ParamsVerifierInternal,\n asArray,\n createLexiconInputVerifier,\n createLexiconOutputVerifier,\n createLexiconParamsVerifier,\n createSchemaInputVerifier,\n createSchemaOutputVerifier,\n createSchemaParamsVerifier,\n extractUrlNsid,\n setHeaders,\n} from './util.js'\n\nexport function createServer(lexicons?: LexiconDoc[], options?: Options) {\n return new Server(lexicons, options)\n}\n\nexport class Server {\n router: Express = express()\n routes: Router = Router()\n subscriptions = new Map<string, XrpcStreamServer>()\n lex = new Lexicons()\n options: Options\n globalRateLimiter?: HttpRateLimiter<HandlerContext>\n sharedRateLimiters?: Map<string, RateLimiterI<HandlerContext>>\n\n constructor(lexicons?: LexiconDoc[], opts: Options = {}) {\n if (lexicons) {\n this.addLexicons(lexicons)\n }\n this.router.use(this.routes)\n this.router.use(this.catchall)\n this.router.use(createErrorMiddleware(opts))\n this.router.once('mount', (app: Application) => {\n this.enableStreamingOnListen(app)\n })\n this.options = opts\n\n if (opts.rateLimits) {\n const { global, shared, creator, bypass } = opts.rateLimits\n\n if (global) {\n this.globalRateLimiter = HttpRateLimiter.from(\n global.map((options) => creator(buildRateLimiterOptions(options))),\n { bypass },\n )\n }\n\n if (shared) {\n this.sharedRateLimiters = new Map(\n shared.map((options) => [\n options.name,\n creator(buildRateLimiterOptions(options)),\n ]),\n )\n }\n }\n }\n\n listen(port: number, callback?: () => void) {\n return this.router.listen(port, callback)\n }\n\n // handlers\n // =\n\n // Routes with auth\n add<M extends l.Procedure | l.Query | l.Subscription, A extends AuthResult>(\n ns: l.Main<M>,\n config: M extends l.Procedure | l.Query\n ? LexMethodConfig<M, A> & { auth: Exclude<unknown, void> }\n : M extends l.Subscription\n ? LexSubscriptionConfig<M, A> & { auth: Exclude<unknown, void> }\n : never,\n ): void\n // Routes without auth\n add<M extends l.Procedure | l.Query | l.Subscription>(\n ns: l.Main<M>,\n config: M extends l.Procedure | l.Query\n ? LexMethodConfig<M, void> | LexMethodHandler<M, void>\n : M extends l.Subscription\n ? LexSubscriptionConfig<M, void> | LexSubscriptionHandler<M, void>\n : never,\n ): void\n add<M extends l.Procedure | l.Query | l.Subscription, A extends Auth>(\n ns: l.Main<M>,\n configOfHandler: M extends l.Procedure | l.Query\n ? LexMethodConfig<M, A> | LexMethodHandler<M, A>\n : M extends l.Subscription\n ? LexSubscriptionConfig<M, A> | LexSubscriptionHandler<M, A>\n : never,\n ): void {\n const schema = l.getMain(ns)\n const config =\n typeof configOfHandler === 'function'\n ? { handler: configOfHandler }\n : configOfHandler\n switch (schema.type) {\n case 'procedure':\n return this.addProcedureSchema(\n schema,\n config as LexMethodConfig<l.Procedure, A>,\n )\n case 'query':\n return this.addQuerySchema(\n schema,\n config as LexMethodConfig<l.Query, A>,\n )\n case 'subscription':\n return this.addSubscriptionSchema(\n schema,\n config as LexSubscriptionConfig<l.Subscription, A>,\n )\n default:\n throw new TypeError(\n // @ts-expect-error should never happen\n `Unsupported schema ${schema.nsid} of type ${schema.type}`,\n )\n }\n }\n\n protected addProcedureSchema<M extends l.Procedure, A extends Auth>(\n schema: M,\n config: LexMethodConfig<M, A>,\n ): void {\n this.routes.get(`/xrpc/${schema.nsid}`, (req, res, next) => {\n next(\n new InvalidRequestError(\n `Incorrect HTTP method (${req.method}) expected POST`,\n ),\n )\n })\n this.routes.post(\n `/xrpc/${schema.nsid}`,\n this.createHandlerInternal<\n A,\n LexMethodParams<M>,\n LexMethodInput<M>,\n LexMethodOutput<M>\n >(\n this.createAuthVerifier(config),\n this.createSchemaParamsVerifier(schema, config.opts),\n this.createSchemaInputVerifier(schema, config.opts),\n this.createRouteRateLimiter(schema.nsid, config),\n config.handler,\n this.createSchemaOutputVerifier(schema),\n ),\n )\n }\n\n protected addQuerySchema<M extends l.Query, A extends Auth>(\n schema: M,\n config: LexMethodConfig<M, A>,\n ): void {\n this.routes.post(`/xrpc/${schema.nsid}`, (req, res, next) => {\n next(\n new InvalidRequestError(\n `Incorrect HTTP method (${req.method}) expected GET`,\n ),\n )\n })\n this.routes.get(\n `/xrpc/${schema.nsid}`,\n this.createHandlerInternal<\n A,\n LexMethodParams<M>,\n LexMethodInput<M>,\n LexMethodOutput<M>\n >(\n this.createAuthVerifier(config),\n this.createSchemaParamsVerifier(schema, config.opts),\n this.createSchemaInputVerifier(schema, config.opts),\n this.createRouteRateLimiter(schema.nsid, config),\n config.handler,\n this.createSchemaOutputVerifier(schema),\n ),\n )\n }\n\n protected addSubscriptionSchema<\n M extends l.Subscription,\n A extends Auth = void,\n >(schema: M, config: LexSubscriptionConfig<M, A>): void {\n const { handler } = config\n const messageSchema =\n this.options.validateResponse === false ? undefined : schema.message\n\n return this.addSubscriptionInternal(\n schema.nsid,\n this.createSchemaParamsVerifier(schema),\n this.createAuthVerifier(config),\n // Wrap the handler to validate outgoing messages if a message schema\n // is available\n messageSchema\n ? async function* (ctx) {\n for await (const item of handler(ctx)) {\n if (item instanceof Frame) {\n messageSchema.validate(item.body)\n yield item\n } else {\n yield messageSchema.validate(item)\n }\n }\n }\n : handler,\n )\n }\n\n method<A extends Auth = Auth>(\n nsid: string,\n configOrFn: MethodConfigOrHandler<A>,\n ): void {\n this.addMethod(nsid, configOrFn)\n }\n\n addMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: MethodConfigOrHandler<A>,\n ) {\n const config =\n typeof configOrFn === 'function' ? { handler: configOrFn } : configOrFn\n if (config.opts && 'paramsParseLoose' in config.opts) {\n throw new Error(\n `paramsParseLoose is not supported with method(), use add() instead`,\n )\n }\n const def = this.lex.getDef(nsid)\n if (def?.type === 'query' || def?.type === 'procedure') {\n this.addRoute(nsid, def, config)\n } else {\n throw new Error(`Lex def for ${nsid} is not a query or a procedure`)\n }\n }\n\n streamMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: StreamConfigOrHandler<A, Params>,\n ) {\n this.addStreamMethod(nsid, configOrFn)\n }\n\n addStreamMethod<A extends Auth = Auth>(\n nsid: string,\n configOrFn: StreamConfigOrHandler<A, Params>,\n ) {\n const config =\n typeof configOrFn === 'function' ? { handler: configOrFn } : configOrFn\n const def = this.lex.getDef(nsid)\n if (def?.type === 'subscription') {\n this.addSubscription(nsid, def, config)\n } else {\n throw new Error(`Lex def for ${nsid} is not a subscription`)\n }\n }\n\n // schemas\n // =\n\n addLexicon(doc: LexiconDoc) {\n this.lex.add(doc)\n }\n\n addLexicons(docs: LexiconDoc[]) {\n for (const doc of docs) {\n this.addLexicon(doc)\n }\n }\n\n // http\n // =\n\n protected async addRoute<A extends Auth = Auth>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n config: MethodConfig<A>,\n ) {\n const path = `/xrpc/${nsid}`\n const handler = this.createHandler(nsid, def, config)\n\n if (def.type === 'procedure') {\n this.routes.post(path, handler)\n } else {\n this.routes.get(path, handler)\n }\n }\n\n catchall: CatchallHandler = async (req, res, next) => {\n // catchall handler only applies to XRPC routes\n if (!req.url.startsWith('/xrpc/')) return next()\n\n // Validate the NSID\n const nsid = extractUrlNsid(req.url)\n if (!nsid) {\n return next(new InvalidRequestError('invalid xrpc path'))\n }\n\n if (this.globalRateLimiter) {\n try {\n await this.globalRateLimiter.handle({\n req,\n res,\n auth: undefined,\n params: {},\n input: undefined,\n async resetRouteRateLimits() {},\n })\n } catch (err) {\n return next(err)\n }\n }\n\n // Ensure that known XRPC methods are only called with the correct HTTP\n // method.\n const def = this.lex.getDef(nsid)\n if (def) {\n const expectedMethod =\n def.type === 'procedure' ? 'POST' : def.type === 'query' ? 'GET' : null\n if (expectedMethod != null && expectedMethod !== req.method) {\n return next(\n new InvalidRequestError(\n `Incorrect HTTP method (${req.method}) expected ${expectedMethod}`,\n ),\n )\n }\n }\n\n if (this.options.catchall) {\n this.options.catchall.call(null, req, res, next)\n } else if (!def) {\n next(new MethodNotImplementedError())\n } else {\n next()\n }\n }\n\n createHandler<\n A extends Auth = Auth,\n P extends Params = Params,\n I extends Input = Input,\n O extends Output = Output,\n >(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n cfg: MethodConfig<A, P, I, O>,\n ): RequestHandler {\n return this.createHandlerInternal<A, P, I, O>(\n this.createAuthVerifier(cfg),\n this.createLexiconParamsVerifier<P>(nsid, def),\n this.createLexiconInputVerifier<I>(nsid, def, cfg.opts),\n this.createRouteRateLimiter(nsid, cfg),\n cfg.handler,\n this.createLexiconOutputVerifier<O>(nsid, def),\n )\n }\n\n protected createHandlerInternal<\n A extends Auth,\n P extends Params,\n I extends Input,\n O extends Output,\n >(\n authVerifier: AuthVerifierInternal<MethodAuthContext<P>, A> | null,\n paramsVerifier: ParamsVerifierInternal<P>,\n inputVerifier: InputVerifierInternal<I>,\n routeLimiter: HttpRateLimiter<HandlerContext<A, P, I>> | undefined,\n handler: MethodHandler<A, P, I, O>,\n validateResOutput: null | OutputVerifierInternal<O>,\n ): RequestHandler {\n return async function (req, res, next) {\n try {\n // parse & validate params\n const params = paramsVerifier(req)\n\n // authenticate request\n const auth: A = authVerifier\n ? await authVerifier({ req, res, params })\n : (undefined as A)\n\n // parse & validate input\n const input: I = await inputVerifier(req, res)\n\n const ctx: HandlerContext<A, P, I> = {\n params,\n input,\n auth,\n req,\n res,\n resetRouteRateLimits: async () => routeLimiter?.reset(ctx),\n }\n\n // handle rate limits\n if (routeLimiter) await routeLimiter.handle(ctx)\n\n // run the handler\n const output = (await handler(ctx)) as O\n\n if (!output) {\n validateResOutput?.(output)\n res.status(200)\n res.end()\n } else if (isHandlerPipeThroughStream(output)) {\n setHeaders(res, output.headers)\n res.status(200)\n res.header('Content-Type', output.encoding)\n await pipeline(output.stream, res)\n } else if (isHandlerPipeThroughBuffer(output)) {\n setHeaders(res, output.headers)\n res.status(200)\n res.header('Content-Type', output.encoding)\n res.end(output.buffer)\n } else if (isHandlerSuccess(output)) {\n validateResOutput?.(output)\n\n res.status(200)\n setHeaders(res, output.headers)\n\n const encoding =\n output.encoding === 'json' ? 'application/json' : output.encoding\n\n res.header('Content-Type', encoding)\n\n if (output.body instanceof Readable) {\n // The \"Readable\" check comes first to avoid calling \"lexToJson\" on\n // a stream, which would be a bug.\n await pipeline(output.body, res)\n } else if (encoding === 'application/json') {\n const json = lexToJson(output.body)\n res.json(json)\n } else {\n res.send(\n Buffer.isBuffer(output.body)\n ? output.body\n : output.body instanceof Uint8Array\n ? Buffer.from(output.body)\n : output.body,\n )\n }\n } else {\n next(XRPCError.fromError(output))\n }\n } catch (err: unknown) {\n // Express will not call the next middleware (errorMiddleware in this case)\n // if the value passed to next is false-y (e.g. null, undefined, 0).\n // Hence we replace it with an InternalServerError.\n if (!err) {\n next(new InternalServerError())\n } else {\n next(err)\n }\n }\n }\n }\n\n protected async addSubscription<A extends Auth = Auth>(\n nsid: string,\n def: LexXrpcSubscription,\n cfg: StreamConfig<A, Params>,\n ) {\n this.addSubscriptionInternal(\n nsid,\n this.createLexiconParamsVerifier(nsid, def),\n this.createAuthVerifier(cfg),\n // @NOTE outgoing messages are not validated against the lexicon schema\n // (unlike the handlers for @atproto/lex based subscriptions)\n cfg.handler,\n )\n }\n\n protected addSubscriptionInternal<A extends Auth, P extends Params>(\n nsid: string,\n paramsVerifier: ParamsVerifierInternal<P>,\n authVerifier: AuthVerifierInternal<StreamAuthContext<P>, A> | null,\n handler: (ctx: StreamContext<A, P>) => AsyncIterable<unknown>,\n ) {\n this.subscriptions.set(\n nsid,\n new XrpcStreamServer({\n noServer: true,\n handler: async function* (req, signal) {\n try {\n // validate request\n const params = paramsVerifier(req)\n\n // authenticate request\n const auth = authVerifier\n ? await authVerifier({ req, params })\n : (undefined as A)\n\n // stream\n for await (const item of handler({ req, params, auth, signal })) {\n yield item instanceof Frame\n ? item\n : MessageFrame.fromLexValue(item as LexValue, nsid)\n }\n } catch (err) {\n yield ErrorFrame.fromError(err)\n }\n },\n }),\n )\n }\n\n private createAuthVerifier<C, A extends AuthResult>(cfg: {\n auth?: AuthVerifier<C, A>\n }): null | AuthVerifierInternal<C, A> {\n const { auth } = cfg\n if (!auth) return null\n\n return async (ctx) => {\n const result = await auth(ctx)\n return excludeErrorResult(result)\n }\n }\n\n private createLexiconParamsVerifier<P extends Params = Params>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure | LexXrpcSubscription,\n ) {\n return createLexiconParamsVerifier<P>(nsid, def, this.lex)\n }\n\n private createLexiconInputVerifier<I extends Input = Input>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n opts?: RouteOptions,\n ): InputVerifierInternal<I> {\n return createLexiconInputVerifier(\n nsid,\n def,\n {\n blobLimit: opts?.blobLimit ?? this.options.payload?.blobLimit,\n jsonLimit: opts?.jsonLimit ?? this.options.payload?.jsonLimit,\n textLimit: opts?.textLimit ?? this.options.payload?.textLimit,\n },\n this.lex,\n )\n }\n\n private createLexiconOutputVerifier<O extends Output = Output>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure,\n ): null | OutputVerifierInternal<O> {\n if (this.options.validateResponse === false) {\n return null\n }\n return createLexiconOutputVerifier(nsid, def, this.lex)\n }\n\n private createSchemaParamsVerifier<\n M extends l.Procedure | l.Query | l.Subscription,\n >(\n ns: l.Main<M>,\n opts?: RouteOptions,\n ): ParamsVerifierInternal<LexMethodParams<M>> {\n return createSchemaParamsVerifier<M>(ns, opts)\n }\n\n private createSchemaInputVerifier<M extends l.Procedure | l.Query>(\n ns: l.Main<M>,\n opts?: RouteOptions,\n ): InputVerifierInternal<LexMethodInput<M>> {\n return createSchemaInputVerifier<M>(ns, {\n blobLimit: opts?.blobLimit ?? this.options.payload?.blobLimit,\n jsonLimit: opts?.jsonLimit ?? this.options.payload?.jsonLimit,\n textLimit: opts?.textLimit ?? this.options.payload?.textLimit,\n })\n }\n\n private createSchemaOutputVerifier<M extends l.Procedure | l.Query>(\n ns: l.Main<M>,\n ): null | OutputVerifierInternal<LexMethodOutput<M>> {\n if (this.options.validateResponse === false) {\n return null\n }\n return createSchemaOutputVerifier<M>(ns)\n }\n\n private enableStreamingOnListen(app: Application) {\n const _listen = app.listen\n app.listen = (...args) => {\n // @ts-ignore the args spread\n const httpServer = _listen.call(app, ...args)\n httpServer.on('upgrade', (req, socket, head) => {\n const nsid = req.url ? extractUrlNsid(req.url) : undefined\n const sub = nsid ? this.subscriptions.get(nsid) : undefined\n if (!sub) return socket.destroy()\n sub.wss.handleUpgrade(req, socket, head, (ws) =>\n sub.wss.emit('connection', ws, req),\n )\n })\n return httpServer\n }\n }\n\n private createRouteRateLimiter<\n A extends Auth,\n P extends Params,\n I extends Input,\n O extends Output,\n >(\n nsid: string,\n config: MethodConfig<A, P, I, O>,\n ): HttpRateLimiter<HandlerContext<A, P, I>> | undefined {\n // @NOTE global & shared rate limiters are instantiated with a context of\n // HandlerContext which is compatible (more generic) with the context of\n // this route specific rate limiters (C). For this reason, it's safe to cast\n // the context of the global rate limiter to the context of the route\n // specific rate limiter (HandlerContext<A, P, I>).\n\n const globalRateLimiter = this.globalRateLimiter as\n | HttpRateLimiter<HandlerContext<A, P, I>>\n | undefined\n\n // No route specific rate limiting configured, use the global rate limiter.\n if (!config.rateLimit) return globalRateLimiter\n\n const { rateLimits } = this.options\n\n // @NOTE Silently ignore creation of route specific rate limiter if the\n // `rateLimits` options was not provided to the constructor.\n if (!rateLimits) return globalRateLimiter\n\n const { creator, bypass } = rateLimits\n\n const rateLimiters = asArray(config.rateLimit).map((options, i) => {\n if (isSharedRateLimitOpts(options)) {\n const rateLimiter = this.sharedRateLimiters?.get(options.name) as\n | RateLimiterI<HandlerContext<A, P, I>>\n | undefined\n\n // The route config references a shared rate limiter that does not\n // exist. This is a configuration error.\n assert(rateLimiter, `Shared rate limiter \"${options.name}\" not defined`)\n\n return WrappedRateLimiter.from<HandlerContext<A, P, I>>(\n rateLimiter,\n options,\n )\n } else {\n return creator({\n ...options,\n calcKey: options.calcKey ?? defaultKey,\n calcPoints: options.calcPoints ?? defaultPoints,\n keyPrefix: `${nsid}-${i}`,\n })\n }\n })\n\n // If the route config contains an empty array, use global rate limiter.\n if (!rateLimiters.length) return globalRateLimiter\n\n // The global rate limiter (if present) should be applied in addition to\n // the route specific rate limiters.\n if (globalRateLimiter) rateLimiters.push(globalRateLimiter)\n\n return HttpRateLimiter.from<HandlerContext<A, P, I>>(rateLimiters, {\n bypass,\n })\n }\n}\n\nfunction createErrorMiddleware({\n errorParser = (err) => XRPCError.fromError(err),\n}: Options): ErrorRequestHandler {\n return (err, req, res, next) => {\n const nsid = extractUrlNsid(req.originalUrl)\n const xrpcError = errorParser(err)\n\n // Use the request's logger (if available) to benefit from request context\n // (id, timing) and logging configuration (serialization, etc.).\n const logger = isPinoHttpRequest(req) ? req.log : log\n\n const msgError = xrpcError.error || 'Unknown'\n const msgLoc = nsid ? `xrpc method ${nsid}` : `${req.method} ${req.url}`\n const msgDetail = xrpcError.message ? ` (${xrpcError.message})` : ''\n const msg = `${msgError} error in ${msgLoc}${msgDetail}`\n\n logger.error(\n {\n // @NOTE Computation of error stack is an expensive operation, so\n // we strip it for expected (non-server) errors.\n err:\n xrpcError instanceof InternalServerError ||\n process.env.NODE_ENV === 'development'\n ? err\n : toSimplifiedErrorLike(err),\n\n // XRPC specific properties, for easier browsing of logs\n nsid,\n type: xrpcError.type,\n status: xrpcError.statusCode,\n payload: xrpcError.payload,\n\n // Ensure that the logged item's name is set to LOGGER_NAME, instead of\n // the name of the pino-http logger, to ensure consistency across logs.\n name: LOGGER_NAME,\n },\n msg,\n )\n\n if (res.headersSent) {\n return next(err)\n }\n\n return res.status(xrpcError.statusCode).json(xrpcError.payload)\n }\n}\n\nfunction isPinoHttpRequest(req: IncomingMessage): req is IncomingMessage & {\n log: { error: (obj: unknown, msg: string) => void }\n} {\n return typeof (req as { log?: any }).log?.error === 'function'\n}\n\nfunction toSimplifiedErrorLike(err: unknown): unknown {\n if (err instanceof Error) {\n // Transform into an \"ErrorLike\" for pino's std \"err\" serializer\n return {\n ...err,\n // Carry over non-enumerable properties\n message: err.message,\n name:\n !Object.hasOwn(err, 'name') &&\n Object.prototype.toString.call(err.constructor) === '[object Function]'\n ? err.constructor.name // extract the class name for sub-classes of Error\n : err.name,\n // @NOTE Error.stack, Error.cause and AggregateError.error are non\n // enumerable properties so they won't be spread to the ErrorLike\n }\n }\n\n return err\n}\n\nfunction buildRateLimiterOptions<C extends HandlerContext = HandlerContext>({\n name,\n calcKey = defaultKey,\n calcPoints = defaultPoints,\n failClosed = false,\n durationMs,\n points,\n}: ServerRateLimitDescription<C>): RateLimiterOptions<C> {\n return {\n durationMs,\n points,\n calcKey,\n calcPoints,\n keyPrefix: `rl-${name}`,\n onError: failClosed\n ? undefined // Let the error propagate\n : rateLimiterLoggerErrorHandler,\n }\n}\n\nconst defaultPoints: CalcPointsFn = () => 1\n\n/**\n * @note when using a proxy, ensure headers are getting forwarded correctly:\n * `app.set('trust proxy', true)`\n *\n * @see {@link https://expressjs.com/en/guide/behind-proxies.html}\n */\nconst defaultKey: CalcKeyFn<HandlerContext> = ({ req }) => req.ip\n\nasync function rateLimiterLoggerErrorHandler(\n err: unknown,\n ctx: HandlerContext,\n { limiter: { keyPrefix, points, duration } }: RateLimiterErrorHandlerDetails,\n): Promise<null> {\n const { req } = ctx\n const logger = isPinoHttpRequest(req) ? req.log : log\n\n logger.error(\n { err, keyPrefix, points, duration },\n 'rate limiter failed to consume points',\n )\n\n return null\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/xrpc-server",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "atproto HTTP API (XRPC) server library",
|
|
6
6
|
"keywords": [
|
|
@@ -22,16 +22,16 @@
|
|
|
22
22
|
"mime-types": "^2.1.35",
|
|
23
23
|
"rate-limiter-flexible": "^2.4.1",
|
|
24
24
|
"ws": "^8.12.0",
|
|
25
|
-
"@atproto/
|
|
25
|
+
"@atproto/lex-data": "^0.1.3",
|
|
26
26
|
"@atproto/crypto": "^0.5.2",
|
|
27
27
|
"@atproto/lex-cbor": "^0.1.2",
|
|
28
|
-
"@atproto/lex-
|
|
28
|
+
"@atproto/lex-json": "^0.1.2",
|
|
29
29
|
"@atproto/lex-client": "^0.1.5",
|
|
30
|
+
"@atproto/common": "^0.6.4",
|
|
30
31
|
"@atproto/lex-schema": "^0.1.5",
|
|
31
32
|
"@atproto/lexicon": "^0.7.3",
|
|
32
|
-
"@atproto/xrpc": "^0.8.2",
|
|
33
33
|
"@atproto/ws-client": "^0.1.3",
|
|
34
|
-
"@atproto/
|
|
34
|
+
"@atproto/xrpc": "^0.8.2"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@jest/globals": "^30.0.0",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"jose": "^5.0.1",
|
|
46
46
|
"key-encoder": "^2.0.3",
|
|
47
47
|
"multiformats": "^13.0.0",
|
|
48
|
+
"@atproto/lex-document": "^0.1.2",
|
|
48
49
|
"@atproto/crypto": "^0.5.2",
|
|
49
|
-
"@atproto/lex": "^0.1.5"
|
|
50
|
-
"@atproto/lex-document": "^0.1.2"
|
|
50
|
+
"@atproto/lex": "^0.1.5"
|
|
51
51
|
},
|
|
52
52
|
"type": "module",
|
|
53
53
|
"exports": {
|
package/src/server.ts
CHANGED
|
@@ -202,6 +202,13 @@ export class Server {
|
|
|
202
202
|
schema: M,
|
|
203
203
|
config: LexMethodConfig<M, A>,
|
|
204
204
|
): void {
|
|
205
|
+
this.routes.get(`/xrpc/${schema.nsid}`, (req, res, next) => {
|
|
206
|
+
next(
|
|
207
|
+
new InvalidRequestError(
|
|
208
|
+
`Incorrect HTTP method (${req.method}) expected POST`,
|
|
209
|
+
),
|
|
210
|
+
)
|
|
211
|
+
})
|
|
205
212
|
this.routes.post(
|
|
206
213
|
`/xrpc/${schema.nsid}`,
|
|
207
214
|
this.createHandlerInternal<
|
|
@@ -224,6 +231,13 @@ export class Server {
|
|
|
224
231
|
schema: M,
|
|
225
232
|
config: LexMethodConfig<M, A>,
|
|
226
233
|
): void {
|
|
234
|
+
this.routes.post(`/xrpc/${schema.nsid}`, (req, res, next) => {
|
|
235
|
+
next(
|
|
236
|
+
new InvalidRequestError(
|
|
237
|
+
`Incorrect HTTP method (${req.method}) expected GET`,
|
|
238
|
+
),
|
|
239
|
+
)
|
|
240
|
+
})
|
|
227
241
|
this.routes.get(
|
|
228
242
|
`/xrpc/${schema.nsid}`,
|
|
229
243
|
this.createHandlerInternal<
|
|
@@ -735,18 +749,18 @@ function createErrorMiddleware({
|
|
|
735
749
|
// (id, timing) and logging configuration (serialization, etc.).
|
|
736
750
|
const logger = isPinoHttpRequest(req) ? req.log : log
|
|
737
751
|
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
const
|
|
741
|
-
const
|
|
742
|
-
const msg = `${msgPrefix} in ${msgSuffix}`
|
|
752
|
+
const msgError = xrpcError.error || 'Unknown'
|
|
753
|
+
const msgLoc = nsid ? `xrpc method ${nsid}` : `${req.method} ${req.url}`
|
|
754
|
+
const msgDetail = xrpcError.message ? ` (${xrpcError.message})` : ''
|
|
755
|
+
const msg = `${msgError} error in ${msgLoc}${msgDetail}`
|
|
743
756
|
|
|
744
757
|
logger.error(
|
|
745
758
|
{
|
|
746
759
|
// @NOTE Computation of error stack is an expensive operation, so
|
|
747
|
-
// we strip it for expected errors.
|
|
760
|
+
// we strip it for expected (non-server) errors.
|
|
748
761
|
err:
|
|
749
|
-
|
|
762
|
+
xrpcError instanceof InternalServerError ||
|
|
763
|
+
process.env.NODE_ENV === 'development'
|
|
750
764
|
? err
|
|
751
765
|
: toSimplifiedErrorLike(err),
|
|
752
766
|
|
package/tests/bodies.test.ts
CHANGED
|
@@ -262,23 +262,20 @@ for (const buildServer of [buildMethodLexicons, buildAddLexicons]) {
|
|
|
262
262
|
|
|
263
263
|
test('validation errors on procedures include details in logs', async () => {
|
|
264
264
|
// 500 responses don't include details, so we nab details from the logger.
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}),
|
|
265
|
+
using spy = jest.spyOn(logger, 'error')
|
|
266
|
+
|
|
267
|
+
await expect(client.call('io.example.validationTestTwo')).rejects.toThrow(
|
|
268
|
+
'Internal Server Error',
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
expect(spy).toHaveBeenCalledWith(
|
|
272
|
+
expect.objectContaining({
|
|
273
|
+
err: expect.objectContaining({
|
|
274
|
+
message: expect.stringContaining('foo'),
|
|
276
275
|
}),
|
|
277
|
-
|
|
278
|
-
)
|
|
279
|
-
|
|
280
|
-
spy.mockRestore()
|
|
281
|
-
}
|
|
276
|
+
}),
|
|
277
|
+
expect.stringContaining('InternalServerError error'),
|
|
278
|
+
)
|
|
282
279
|
})
|
|
283
280
|
|
|
284
281
|
it('supports ArrayBuffers', async () => {
|