@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/dist/util.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { IncomingMessage, OutgoingMessage } from 'node:http'\nimport { Duplex, Readable, pipeline } from 'node:stream'\nimport {\n Request as ExpressRequest,\n Response as ExpressResponse,\n json,\n text,\n} from 'express'\n// eslint-disable-next-line import/default, import/no-named-as-default-member\nimport mimeTypes from 'mime-types'\n// eslint-disable-next-line import/no-named-as-default-member\nconst { contentType } = mimeTypes\nimport { MaxSizeChecker, createDecoders } from '@atproto/common'\nimport { jsonToLex } from '@atproto/lex-json'\nimport { l } from '@atproto/lex-schema'\nimport {\n type LexXrpcBody,\n type LexXrpcProcedure,\n type LexXrpcQuery,\n type LexXrpcSubscription,\n Lexicons,\n jsonToLex as jsonToLexWithBlobRef,\n} from '@atproto/lexicon'\nimport { ResponseType } from '@atproto/xrpc'\nimport {\n ErrorResult,\n InternalServerError,\n InvalidRequestError,\n XRPCError,\n} from './errors.js'\nimport {\n Auth,\n Input,\n LexMethodInput,\n LexMethodOutput,\n LexMethodParams,\n Output,\n Params,\n RouteOptions,\n UndecodedParams,\n handlerSuccess,\n} from './types.js'\n\nexport type ParamsVerifierInternal<P extends Params = Params> = (\n req: IncomingMessage | ExpressRequest,\n) => P\n\nexport type AuthVerifierInternal<C, A extends Auth = Auth> = (\n ctx: C,\n) => Promise<Exclude<A, ErrorResult>>\n\nexport type InputVerifierInternal<I extends Input = Input> = (\n req: ExpressRequest,\n res: ExpressResponse,\n) => Promise<I>\n\nexport type OutputVerifierInternal<O extends Output = Output> = (\n handleOutput: O,\n) => void\n\nexport const asArray = <T>(arr: T | T[]): T[] =>\n Array.isArray(arr) ? arr : [arr]\n\nexport function setHeaders(\n res: OutgoingMessage,\n headers?: Record<string, string | number>,\n) {\n if (headers) {\n for (const [name, val] of Object.entries(headers)) {\n if (val != null) res.setHeader(name, val)\n }\n }\n}\n\nfunction decodeQueryParams(\n def: LexXrpcProcedure | LexXrpcQuery | LexXrpcSubscription,\n params: UndecodedParams,\n): Params {\n const decoded: Params = {}\n for (const k in params) {\n const val = params[k]\n const property = def.parameters?.properties?.[k]\n if (property) {\n if (property.type === 'array') {\n const vals: (typeof val)[] = []\n decoded[k] = val\n ? vals\n .concat(val) // Cast to array\n .flatMap((v) => decodeQueryParam(property.items.type, v) ?? [])\n : undefined\n } else {\n decoded[k] = decodeQueryParam(property.type, val)\n }\n }\n }\n return decoded\n}\n\nexport function decodeQueryParam(\n type: string,\n value: unknown,\n): string | number | boolean | undefined {\n if (!value) {\n return undefined\n }\n if (type === 'string' || type === 'datetime') {\n return String(value)\n }\n if (type === 'float') {\n return Number(String(value))\n } else if (type === 'integer') {\n return parseInt(String(value), 10) || 0\n } else if (type === 'boolean') {\n return value === 'true'\n }\n}\n\nfunction getSearchParams(\n url?: string,\n opts?: { parseLoose?: boolean },\n): URLSearchParams | undefined {\n if (!url) return undefined\n\n const queryStringIdx = url.indexOf('?')\n if (queryStringIdx === -1) return undefined\n\n const queryString = url.slice(queryStringIdx + 1)\n if (queryString.length === 0) return undefined\n\n const urlSearchParams = new URLSearchParams(queryString)\n\n if (opts?.parseLoose) {\n // @NOTE this is non-standard and should only be used for limited backwards-compatibility purposes.\n // Converts \"foo[]=bar&foo[0]=baz\" syntax into \"foo=bar&foo=baz\"\n\n // We cannot \"delete()\" while iterating. SO we'll first collect all keys\n // that need to be changed, then apply the changes after\n const toAppend = new URLSearchParams()\n const toDelete = new Set<string>()\n\n for (const [key, value] of urlSearchParams) {\n const match = key.endsWith(']') ? key.match(/^([^[]*)\\[\\d*\\]$/) : null\n if (match) {\n toAppend.append(match[1], value)\n toDelete.add(key)\n }\n }\n\n for (const key of toDelete) {\n urlSearchParams.delete(key)\n }\n\n for (const [key, value] of toAppend) {\n urlSearchParams.append(key, value)\n }\n }\n\n return urlSearchParams\n}\n\nexport function getQueryParams(\n req: IncomingMessage | ExpressRequest,\n opts?: { parseLoose?: boolean },\n): UndecodedParams {\n if ('query' in req) return req.query\n\n const result: UndecodedParams = Object.create(null)\n\n const searchParams = getSearchParams(req.url, opts)\n if (!searchParams) return result\n\n if (searchParams.has('__proto__')) {\n // Prevent prototype pollution\n throw new InvalidRequestError(\n `Invalid query parameter: __proto__`,\n 'InvalidQueryParameter',\n )\n }\n\n for (const key of searchParams.keys()) {\n const values = searchParams.getAll(key)\n result[key] = values.length === 1 ? values[0] : values\n }\n\n return result\n}\n\nexport function createLexiconParamsVerifier<P extends Params = Params>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure | LexXrpcSubscription,\n lexicons: Lexicons,\n): ParamsVerifierInternal<P> {\n return (req) => {\n const queryParams = getQueryParams(req)\n const params = decodeQueryParams(def, queryParams)\n try {\n return lexicons.assertValidXrpcParams(nsid, params) as P\n } catch (cause) {\n // @NOTE WE historically did not check for specific error types here,\n throw new InvalidRequestError(String(cause), undefined, { cause })\n }\n }\n}\n\nexport function createSchemaParamsVerifier<\n M extends l.Procedure | l.Query | l.Subscription,\n>(\n ns: l.Main<M>,\n options?: RouteOptions,\n): ParamsVerifierInternal<LexMethodParams<M>> {\n const schema = l.getMain(ns)\n const queryOpts = { parseLoose: options?.paramsParseLoose }\n return (req) => {\n const urlSearchParams =\n getSearchParams(req.url, queryOpts) ?? new URLSearchParams()\n try {\n const params = schema.parameters.fromURLSearchParams(urlSearchParams)\n return params as LexMethodParams<M>\n } catch (cause) {\n if (cause instanceof l.LexValidationError) {\n const message = `Invalid ${schema.nsid} params: ${cause.issues\n .map((issue) => issue.message)\n .join(', ')}`\n throw new InvalidRequestError(message, undefined, { cause })\n }\n throw cause\n }\n }\n}\n\nexport function createLexiconInputVerifier<I extends Input = Input>(\n nsid: string,\n def: LexXrpcProcedure | LexXrpcQuery,\n options: RouteOptions,\n lexicons: Lexicons,\n): InputVerifierInternal<I> {\n if (def.type === 'query' || !def.input) {\n return async (req) => {\n // @NOTE We allow (and ignore) \"empty\" bodies\n if (getBodyPresence(req) === 'present') {\n throw new InvalidRequestError(\n `A request body was provided when none was expected`,\n )\n }\n\n return undefined as I\n }\n }\n\n // Lexicon definition expects a request body\n\n const { input } = def\n const { blobLimit } = options\n\n const allowedEncodings = parseDefEncoding(input)\n const checkEncoding = allowedEncodings.includes(ENCODING_ANY)\n ? undefined // No need to check\n : (encoding: string) => allowedEncodings.includes(encoding)\n\n const bodyParser = createBodyParser(input.encoding, options)\n\n return async (req, res) => {\n if (getBodyPresence(req) === 'missing') {\n throw new InvalidRequestError(\n `A request body is expected but none was provided`,\n )\n }\n\n const reqEncoding = parseReqEncoding(req)\n if (checkEncoding && !checkEncoding(reqEncoding)) {\n throw new InvalidRequestError(\n `Wrong request encoding (Content-Type): ${reqEncoding}`,\n )\n }\n\n if (bodyParser) {\n await bodyParser(req, res)\n }\n\n if (input.schema) {\n try {\n const lexBody = req.body ? jsonToLexWithBlobRef(req.body) : req.body\n req.body = lexicons.assertValidXrpcInput(nsid, lexBody)\n } catch (cause) {\n throw new InvalidRequestError(\n cause instanceof Error ? cause.message : String(cause),\n undefined,\n { cause },\n )\n }\n }\n\n // if middleware already got the body, we pass that along as input\n // otherwise, we pass along a decoded readable stream\n const body = req.readableEnded ? req.body : decodeBodyStream(req, blobLimit)\n\n return { encoding: reqEncoding, body } as I\n }\n}\n\nexport function createSchemaInputVerifier<M extends l.Procedure | l.Query>(\n ns: l.Main<M>,\n options: RouteOptions,\n): InputVerifierInternal<LexMethodInput<M>> {\n const schema = l.getMain(ns)\n const { blobLimit } = options\n\n const input: l.Payload | undefined =\n 'input' in schema ? schema.input : undefined\n\n if (!input?.encoding) {\n //\n return async (req) => {\n if (getBodyPresence(req) === 'present') {\n // @NOTE we *could* also discard the body here instead of throwing an error\n throw new InvalidRequestError(\n `A request body was provided when none was expected`,\n )\n }\n\n return undefined as LexMethodInput<M>\n }\n }\n\n const bodyParser = createBodyParser(input.encoding, options)\n\n return async (req, res) => {\n if (getBodyPresence(req) === 'missing') {\n throw new InvalidRequestError(\n `A request body is expected but none was provided`,\n )\n }\n\n const reqEncoding = parseReqEncoding(req)\n if (!input.matchesEncoding(reqEncoding)) {\n throw new InvalidRequestError(\n `Wrong request encoding (Content-Type): ${reqEncoding}`,\n )\n }\n\n if (bodyParser) {\n await bodyParser(req, res)\n }\n\n if (input.schema) {\n try {\n const lexBody = req.body ? jsonToLex(req.body) : req.body\n req.body = input.schema.parse(lexBody)\n } catch (cause) {\n throw new InvalidRequestError(\n cause instanceof Error ? cause.message : String(cause),\n undefined,\n { cause },\n )\n }\n }\n\n // if middleware already got the body, we pass that along as input\n // otherwise, we pass along a decoded readable stream\n const body = req.readableEnded ? req.body : decodeBodyStream(req, blobLimit)\n\n return { encoding: reqEncoding, body } as LexMethodInput<M>\n }\n}\n\nexport function createLexiconOutputVerifier<O extends Output = Output>(\n nsid: string,\n def: LexXrpcProcedure | LexXrpcQuery,\n lexicons: Lexicons,\n): OutputVerifierInternal<O> {\n const outputDef = def.output\n\n // Expects no output\n if (!outputDef) {\n return (handlerOutput) => {\n if (handlerOutput !== undefined) {\n throw new InternalServerError(\n `A response body was provided when none was expected`,\n )\n }\n }\n }\n\n // An output is expected\n return (handlerOutput) => {\n if (handlerOutput === undefined) {\n throw new InternalServerError(\n `A response body is expected but none was provided`,\n )\n }\n\n if (!('encoding' in handlerOutput)) {\n // Ensure handlerOutput is valid ErrorResult\n if ('status' in handlerOutput && handlerOutput.status >= 400) {\n return\n }\n\n throw new InternalServerError(`Invalid handler output: missing encoding`)\n }\n\n if (!('body' in handlerOutput)) {\n // Ensure handlerOutput is valid HandlerPipeThrough\n if ('stream' in handlerOutput || 'buffer' in handlerOutput) {\n return // Validation is ignored for pipe-through outputs\n }\n\n throw new InternalServerError(`Invalid handler output: missing body`)\n }\n\n // Fool-proofing (should not be necessary due to type system)\n const result = handlerSuccess.safeParse(handlerOutput)\n if (!result.success) {\n throw new InternalServerError(`Invalid handler output`, undefined, {\n cause: result.reason,\n })\n }\n\n // output mime\n const { encoding } = handlerOutput\n if (!isValidEncoding(outputDef, encoding)) {\n throw new InternalServerError(`Invalid response encoding: ${encoding}`)\n }\n\n // output schema\n try {\n lexicons.assertValidXrpcOutput(nsid, handlerOutput.body)\n // @TODO Since the output verifier is typically enabled in dev/tests and\n // disabled in production, we don't want to assign the (altered) output\n // back to the handlerOutput object, as this would cause different\n // behaviors between environments. Instead, we should compare the value\n // returned by assertValidXrpcOutput with the original output and throw if\n // they differ (indicating that the output was mutated during validation,\n // e.g. due to default values being applied).\n } catch (cause) {\n const message =\n cause instanceof Error ? cause.message : 'Output body validation failed'\n throw new InternalServerError(message, undefined, { cause })\n }\n }\n}\n\nexport function createSchemaOutputVerifier<M extends l.Procedure | l.Query>(\n ns: l.Main<M>,\n): OutputVerifierInternal<LexMethodOutput<M>> {\n const outputSchema = l.getMain(ns).output\n return (handlerOutput) => {\n // @NOTE If the user of the lib wants to return an output that doesn't\n // conform to the schema, they can use HandlerPipeThrough return types\n if (!outputSchema.matchesEncoding(handlerOutput?.encoding)) {\n throw new InternalServerError('Output encoding mismatch')\n }\n if (outputSchema.schema) {\n const result = outputSchema.schema.safeValidate(handlerOutput?.body)\n if (!result.success) {\n throw new InternalServerError(result.reason.message, undefined, {\n cause: result.reason,\n })\n }\n } else if (!outputSchema.encoding && handlerOutput?.body !== undefined) {\n throw new InternalServerError('Output body not expected')\n }\n }\n}\n\nexport function parseReqEncoding(req: IncomingMessage): string {\n const encoding = normalizeMime(req.headers['content-type'])\n if (encoding) return encoding\n throw new InvalidRequestError(\n `Request encoding (Content-Type) required but not provided`,\n )\n}\n\nfunction normalizeMime(v?: string): string | null {\n if (!v) return null\n const fullType = contentType(v)\n if (!fullType) return null\n const shortType = fullType.split(';')[0]\n if (!shortType) return null\n return shortType\n}\n\nconst ENCODING_ANY = '*/*'\n\nfunction parseDefEncoding({ encoding }: LexXrpcBody) {\n return encoding.split(',').map(trimString)\n}\n\nfunction trimString(str: string): string {\n return str.trim()\n}\n\nfunction isValidEncoding(output: LexXrpcBody, encoding?: string) {\n if (!encoding) return false\n\n const normalized = normalizeMime(encoding)\n if (!normalized) return false\n\n const allowed = parseDefEncoding(output)\n if (!allowed.length) return false\n\n if (allowed.includes(ENCODING_ANY)) return true\n if (allowed.includes(normalized)) return true\n\n // Check for wildcard matches (e.g. normalized=application/json, allowed=application/*)\n for (const allowedEnc of allowed) {\n if (\n allowedEnc.endsWith('/*') &&\n normalized.startsWith(allowedEnc.slice(0, -1))\n ) {\n return true\n }\n }\n\n return false\n}\n\ntype BodyPresence = 'missing' | 'empty' | 'present'\n\nfunction getBodyPresence(req: IncomingMessage): BodyPresence {\n if (req.headers['transfer-encoding'] != null) return 'present'\n if (req.headers['content-length'] === '0') return 'empty'\n if (req.headers['content-length'] != null) return 'present'\n return 'missing'\n}\n\nfunction createBodyParser(inputEncoding: string, options: RouteOptions) {\n if (inputEncoding === ENCODING_ANY) {\n // When the lexicon's input encoding is */*, the handler will determine how to process it\n return\n }\n const { jsonLimit, textLimit } = options\n const jsonParser = json({ limit: jsonLimit })\n const textParser = text({ limit: textLimit })\n // Transform json and text parser middlewares into a single function\n return (req: ExpressRequest, res: ExpressResponse) => {\n return new Promise<void>((resolve, reject) => {\n jsonParser(req, res, (err) => {\n if (err) return reject(XRPCError.fromError(err))\n textParser(req, res, (err) => {\n if (err) return reject(XRPCError.fromError(err))\n resolve()\n })\n })\n })\n }\n}\n\nfunction decodeBodyStream(\n req: IncomingMessage,\n maxSize: number | undefined,\n): Readable {\n const contentEncoding = req.headers['content-encoding']\n const contentLength = req.headers['content-length']\n\n const contentLengthParsed = contentLength\n ? parseInt(contentLength, 10)\n : undefined\n\n if (Number.isNaN(contentLengthParsed)) {\n throw new XRPCError(ResponseType.InvalidRequest, 'invalid content-length')\n }\n\n if (\n maxSize !== undefined &&\n contentLengthParsed !== undefined &&\n contentLengthParsed > maxSize\n ) {\n throw new XRPCError(\n ResponseType.PayloadTooLarge,\n 'request entity too large',\n )\n }\n\n let transforms: Duplex[]\n try {\n transforms = createDecoders(contentEncoding)\n } catch (cause) {\n throw new XRPCError(\n ResponseType.UnsupportedMediaType,\n 'unsupported content-encoding',\n undefined,\n { cause },\n )\n }\n\n if (maxSize !== undefined) {\n const maxSizeChecker = new MaxSizeChecker(\n maxSize,\n () =>\n new XRPCError(ResponseType.PayloadTooLarge, 'request entity too large'),\n )\n transforms.push(maxSizeChecker)\n }\n\n return transforms.length > 0\n ? (pipeline([req, ...transforms], () => {}) as Duplex)\n : req\n}\n\nexport function serverTimingHeader(timings: ServerTiming[]) {\n return timings\n .map((timing) => {\n let header = timing.name\n if (timing.duration) header += `;dur=${timing.duration}`\n if (timing.description) header += `;desc=\"${timing.description}\"`\n return header\n })\n .join(', ')\n}\n\nexport class ServerTimer implements ServerTiming {\n public duration?: number\n private startMs?: number\n constructor(\n public name: string,\n public description?: string,\n ) {}\n start() {\n this.startMs = Date.now()\n return this\n }\n stop() {\n assert(this.startMs, \"timer hasn't been started\")\n this.duration = Date.now() - this.startMs\n return this\n }\n}\n\nexport interface ServerTiming {\n name: string\n duration?: number\n description?: string\n}\n\nexport const parseReqNsid = (req: ExpressRequest | IncomingMessage) =>\n parseUrlNsid('originalUrl' in req ? req.originalUrl : req.url || '/')\n\n/**\n * Validates and extracts the nsid from an xrpc path\n */\nexport const parseUrlNsid = (url: string): string => {\n const nsid = extractUrlNsid(url)\n if (nsid) return nsid\n throw new InvalidRequestError('invalid xrpc path')\n}\n\nexport const extractUrlNsid = (url: string): string | undefined => {\n // /!\\ Hot path\n\n if (\n // Ordered by likelihood of failure\n url.length <= 6 ||\n url[5] !== '/' ||\n url[4] !== 'c' ||\n url[3] !== 'p' ||\n url[2] !== 'r' ||\n url[1] !== 'x' ||\n url[0] !== '/'\n ) {\n return undefined\n }\n\n const startOfNsid = 6\n\n let curr = startOfNsid\n let char: number\n let alphaNumRequired = true\n for (; curr < url.length; curr++) {\n char = url.charCodeAt(curr)\n if (\n (char >= 48 && char <= 57) || // 0-9\n (char >= 65 && char <= 90) || // A-Z\n (char >= 97 && char <= 122) // a-z\n ) {\n alphaNumRequired = false\n } else if (char === 45 /* \"-\" */ || char === 46 /* \".\" */) {\n if (alphaNumRequired) {\n return undefined\n }\n alphaNumRequired = true\n } else if (char === 47 /* \"/\" */) {\n // Allow trailing slash (next char is either EOS or \"?\")\n if (curr === url.length - 1 || url.charCodeAt(curr + 1) === 63) {\n break\n }\n return undefined\n } else if (char === 63 /* \"?\"\" */) {\n break\n } else {\n return undefined\n }\n }\n\n // last char was one of: '-', '.', '/'\n if (alphaNumRequired) {\n return undefined\n }\n\n // A domain name consists of minimum two characters\n if (curr - startOfNsid < 2) {\n return undefined\n }\n\n // @TODO check max length of nsid\n\n return url.slice(startOfNsid, curr)\n}\n"]}
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { IncomingMessage, OutgoingMessage } from 'node:http'\nimport { Duplex, Readable, pipeline } from 'node:stream'\nimport {\n Request as ExpressRequest,\n Response as ExpressResponse,\n json,\n text,\n} from 'express'\n// eslint-disable-next-line import/default, import/no-named-as-default-member\nimport mimeTypes from 'mime-types'\n// eslint-disable-next-line import/no-named-as-default-member\nconst { contentType } = mimeTypes\nimport { MaxSizeChecker, createDecoders } from '@atproto/common'\nimport { jsonToLex } from '@atproto/lex-json'\nimport { l } from '@atproto/lex-schema'\nimport {\n type LexXrpcBody,\n type LexXrpcProcedure,\n type LexXrpcQuery,\n type LexXrpcSubscription,\n Lexicons,\n jsonToLex as jsonToLexWithBlobRef,\n} from '@atproto/lexicon'\nimport { ResponseType } from '@atproto/xrpc'\nimport {\n ErrorResult,\n InternalServerError,\n InvalidRequestError,\n XRPCError,\n} from './errors.js'\nimport {\n Auth,\n Input,\n LexMethodInput,\n LexMethodOutput,\n LexMethodParams,\n Output,\n Params,\n RouteOptions,\n UndecodedParams,\n handlerSuccess,\n} from './types.js'\n\nexport type ParamsVerifierInternal<P extends Params = Params> = (\n req: IncomingMessage | ExpressRequest,\n) => P\n\nexport type AuthVerifierInternal<C, A extends Auth = Auth> = (\n ctx: C,\n) => Promise<Exclude<A, ErrorResult>>\n\nexport type InputVerifierInternal<I extends Input = Input> = (\n req: ExpressRequest,\n res: ExpressResponse,\n) => Promise<I>\n\nexport type OutputVerifierInternal<O extends Output = Output> = (\n handleOutput: O,\n) => void\n\nexport const asArray = <T>(arr: T | T[]): T[] =>\n Array.isArray(arr) ? arr : [arr]\n\nexport function setHeaders(\n res: OutgoingMessage,\n headers?: Record<string, string | number>,\n) {\n if (headers) {\n for (const [name, val] of Object.entries(headers)) {\n if (val != null) res.setHeader(name, val)\n }\n }\n}\n\nfunction decodeQueryParams(\n def: LexXrpcProcedure | LexXrpcQuery | LexXrpcSubscription,\n params: UndecodedParams,\n): Params {\n const decoded: Params = {}\n for (const k in params) {\n const val = params[k]\n const property = def.parameters?.properties?.[k]\n if (property) {\n if (property.type === 'array') {\n const vals: (typeof val)[] = []\n decoded[k] = val\n ? vals\n .concat(val) // Cast to array\n .flatMap((v) => decodeQueryParam(property.items.type, v) ?? [])\n : undefined\n } else {\n decoded[k] = decodeQueryParam(property.type, val)\n }\n }\n }\n return decoded\n}\n\nexport function decodeQueryParam(\n type: string,\n value: unknown,\n): string | number | boolean | undefined {\n if (!value) {\n return undefined\n }\n if (type === 'string' || type === 'datetime') {\n return String(value)\n }\n if (type === 'float') {\n return Number(String(value))\n } else if (type === 'integer') {\n return parseInt(String(value), 10) || 0\n } else if (type === 'boolean') {\n return value === 'true'\n }\n}\n\nfunction getSearchParams(\n url?: string,\n opts?: { parseLoose?: boolean },\n): URLSearchParams | undefined {\n if (!url) return undefined\n\n const queryStringIdx = url.indexOf('?')\n if (queryStringIdx === -1) return undefined\n\n const queryString = url.slice(queryStringIdx + 1)\n if (queryString.length === 0) return undefined\n\n const urlSearchParams = new URLSearchParams(queryString)\n\n if (opts?.parseLoose) {\n // @NOTE this is non-standard and should only be used for limited backwards-compatibility purposes.\n // Converts \"foo[]=bar&foo[0]=baz\" syntax into \"foo=bar&foo=baz\"\n\n // We cannot \"delete()\" while iterating. SO we'll first collect all keys\n // that need to be changed, then apply the changes after\n const toAppend = new URLSearchParams()\n const toDelete = new Set<string>()\n\n for (const [key, value] of urlSearchParams) {\n const match = key.endsWith(']') ? key.match(/^([^[]*)\\[\\d*\\]$/) : null\n if (match) {\n toAppend.append(match[1], value)\n toDelete.add(key)\n }\n }\n\n for (const key of toDelete) {\n urlSearchParams.delete(key)\n }\n\n for (const [key, value] of toAppend) {\n urlSearchParams.append(key, value)\n }\n }\n\n return urlSearchParams\n}\n\nexport function getQueryParams(\n req: IncomingMessage | ExpressRequest,\n opts?: { parseLoose?: boolean },\n): UndecodedParams {\n if ('query' in req) return req.query\n\n const result: UndecodedParams = Object.create(null)\n\n const searchParams = getSearchParams(req.url, opts)\n if (!searchParams) return result\n\n if (searchParams.has('__proto__')) {\n // Prevent prototype pollution\n throw new InvalidRequestError(\n `Invalid query parameter: __proto__`,\n 'InvalidQueryParameter',\n )\n }\n\n for (const key of searchParams.keys()) {\n const values = searchParams.getAll(key)\n result[key] = values.length === 1 ? values[0] : values\n }\n\n return result\n}\n\nexport function createLexiconParamsVerifier<P extends Params = Params>(\n nsid: string,\n def: LexXrpcQuery | LexXrpcProcedure | LexXrpcSubscription,\n lexicons: Lexicons,\n): ParamsVerifierInternal<P> {\n return (req) => {\n const queryParams = getQueryParams(req)\n const params = decodeQueryParams(def, queryParams)\n try {\n return lexicons.assertValidXrpcParams(nsid, params) as P\n } catch (cause) {\n // @NOTE WE historically did not check for specific error types here,\n throw new InvalidRequestError(String(cause), undefined, { cause })\n }\n }\n}\n\nexport function createSchemaParamsVerifier<\n M extends l.Procedure | l.Query | l.Subscription,\n>(\n ns: l.Main<M>,\n options?: RouteOptions,\n): ParamsVerifierInternal<LexMethodParams<M>> {\n const schema = l.getMain(ns)\n const queryOpts = { parseLoose: options?.paramsParseLoose }\n return (req) => {\n const urlSearchParams =\n getSearchParams(req.url, queryOpts) ?? new URLSearchParams()\n try {\n const params = schema.parameters.fromURLSearchParams(urlSearchParams)\n return params as LexMethodParams<M>\n } catch (cause) {\n if (cause instanceof l.LexValidationError) {\n const message = `Invalid ${schema.nsid} params: ${cause.issues\n .map((issue) => issue.message)\n .join(', ')}`\n throw new InvalidRequestError(message, undefined, { cause })\n }\n throw cause\n }\n }\n}\n\nexport function createLexiconInputVerifier<I extends Input = Input>(\n nsid: string,\n def: LexXrpcProcedure | LexXrpcQuery,\n options: RouteOptions,\n lexicons: Lexicons,\n): InputVerifierInternal<I> {\n if (def.type === 'query' || !def.input) {\n return async (req) => {\n // @NOTE We allow (and ignore) \"empty\" bodies\n if (getBodyPresence(req) === 'present') {\n throw new InvalidRequestError(\n `A request body was provided when none was expected`,\n )\n }\n\n return undefined as I\n }\n }\n\n // Lexicon definition expects a request body\n\n const { input } = def\n const { blobLimit } = options\n\n const allowedEncodings = parseDefEncoding(input)\n const checkEncoding = allowedEncodings.includes(ENCODING_ANY)\n ? undefined // No need to check\n : (encoding: string) => allowedEncodings.includes(encoding)\n\n const bodyParser = createBodyParser(input.encoding, options)\n\n return async (req, res) => {\n if (getBodyPresence(req) === 'missing') {\n throw new InvalidRequestError(\n `A request body is expected but none was provided`,\n )\n }\n\n const reqEncoding = parseReqEncoding(req)\n if (checkEncoding && !checkEncoding(reqEncoding)) {\n throw new InvalidRequestError(\n `Wrong request encoding (Content-Type): ${reqEncoding}`,\n )\n }\n\n if (bodyParser) {\n await bodyParser(req, res)\n }\n\n if (input.schema) {\n try {\n const lexBody = req.body ? jsonToLexWithBlobRef(req.body) : req.body\n req.body = lexicons.assertValidXrpcInput(nsid, lexBody)\n } catch (cause) {\n throw new InvalidRequestError(\n cause instanceof Error ? cause.message : String(cause),\n undefined,\n { cause },\n )\n }\n }\n\n // if middleware already got the body, we pass that along as input\n // otherwise, we pass along a decoded readable stream\n const body = req.readableEnded ? req.body : decodeBodyStream(req, blobLimit)\n\n return { encoding: reqEncoding, body } as I\n }\n}\n\nexport function createSchemaInputVerifier<M extends l.Procedure | l.Query>(\n ns: l.Main<M>,\n options: RouteOptions,\n): InputVerifierInternal<LexMethodInput<M>> {\n const schema = l.getMain(ns)\n const { blobLimit } = options\n\n const input: l.Payload | undefined =\n 'input' in schema ? schema.input : undefined\n\n if (!input?.encoding) {\n //\n return async (req) => {\n if (getBodyPresence(req) === 'present') {\n // @NOTE we *could* also discard the body here instead of throwing an error\n throw new InvalidRequestError(\n `A request body was provided when none was expected`,\n )\n }\n\n return undefined as LexMethodInput<M>\n }\n }\n\n const bodyParser = createBodyParser(input.encoding, options)\n\n return async (req, res) => {\n if (getBodyPresence(req) === 'missing') {\n throw new InvalidRequestError(\n `A request body is expected but none was provided`,\n )\n }\n\n const reqEncoding = parseReqEncoding(req)\n if (!input.matchesEncoding(reqEncoding)) {\n throw new InvalidRequestError(\n `Wrong request encoding (Content-Type): ${reqEncoding}`,\n )\n }\n\n if (bodyParser) {\n await bodyParser(req, res)\n }\n\n if (input.schema) {\n try {\n const lexBody = req.body ? jsonToLex(req.body) : req.body\n req.body = input.schema.parse(lexBody)\n } catch (cause) {\n throw new InvalidRequestError(\n cause instanceof Error ? cause.message : String(cause),\n undefined,\n { cause },\n )\n }\n }\n\n // if middleware already got the body, we pass that along as input\n // otherwise, we pass along a decoded readable stream\n const body = req.readableEnded ? req.body : decodeBodyStream(req, blobLimit)\n\n return { encoding: reqEncoding, body } as LexMethodInput<M>\n }\n}\n\nexport function createLexiconOutputVerifier<O extends Output = Output>(\n nsid: string,\n def: LexXrpcProcedure | LexXrpcQuery,\n lexicons: Lexicons,\n): OutputVerifierInternal<O> {\n const outputDef = def.output\n\n // Expects no output\n if (!outputDef) {\n return (handlerOutput) => {\n if (handlerOutput !== undefined) {\n throw new InternalServerError(\n `A response body was provided when none was expected`,\n )\n }\n }\n }\n\n // An output is expected\n return (handlerOutput) => {\n if (handlerOutput === undefined) {\n throw new InternalServerError(\n `A response body is expected but none was provided`,\n )\n }\n\n if (!('encoding' in handlerOutput)) {\n // Ensure handlerOutput is valid ErrorResult\n if ('status' in handlerOutput && handlerOutput.status >= 400) {\n return\n }\n\n throw new InternalServerError(`Invalid handler output: missing encoding`)\n }\n\n if (!('body' in handlerOutput)) {\n // Ensure handlerOutput is valid HandlerPipeThrough\n if ('stream' in handlerOutput || 'buffer' in handlerOutput) {\n return // Validation is ignored for pipe-through outputs\n }\n\n throw new InternalServerError(`Invalid handler output: missing body`)\n }\n\n // Fool-proofing (should not be necessary due to type system)\n const result = handlerSuccess.safeParse(handlerOutput)\n if (!result.success) {\n throw new InternalServerError(`Invalid handler output`, undefined, {\n cause: result.reason,\n })\n }\n\n // output mime\n const { encoding } = handlerOutput\n if (!isValidEncoding(outputDef, encoding)) {\n throw new InternalServerError(`Invalid response encoding: ${encoding}`)\n }\n\n // output schema\n try {\n lexicons.assertValidXrpcOutput(nsid, handlerOutput.body)\n // @TODO Since the output verifier is typically enabled in dev/tests and\n // disabled in production, we don't want to assign the (altered) output\n // back to the handlerOutput object, as this would cause different\n // behaviors between environments. Instead, we should compare the value\n // returned by assertValidXrpcOutput with the original output and throw if\n // they differ (indicating that the output was mutated during validation,\n // e.g. due to default values being applied).\n } catch (cause) {\n const message =\n cause instanceof Error ? cause.message : 'Output body validation failed'\n throw new InternalServerError(message, undefined, { cause })\n }\n }\n}\n\nexport function createSchemaOutputVerifier<M extends l.Procedure | l.Query>(\n ns: l.Main<M>,\n): OutputVerifierInternal<LexMethodOutput<M>> {\n const outputSchema = l.getMain(ns).output\n return (handlerOutput) => {\n // @NOTE If the user of the lib wants to return an output that doesn't\n // conform to the schema, they can use HandlerPipeThrough return types\n if (!outputSchema.matchesEncoding(handlerOutput?.encoding)) {\n throw new InternalServerError('Output encoding mismatch')\n }\n if (outputSchema.schema) {\n const result = outputSchema.schema.safeValidate(handlerOutput?.body)\n if (!result.success) {\n throw new InternalServerError(result.reason.message, undefined, {\n cause: result.reason,\n })\n }\n } else if (!outputSchema.encoding && handlerOutput?.body !== undefined) {\n throw new InternalServerError('Output body not expected')\n }\n }\n}\n\nexport function parseReqEncoding(req: IncomingMessage): string {\n const encoding = normalizeMime(req.headers['content-type'])\n if (encoding) return encoding\n throw new InvalidRequestError(\n `Request encoding (Content-Type) required but not provided`,\n )\n}\n\nfunction normalizeMime(v?: string): string | null {\n if (!v) return null\n const fullType = contentType(v)\n if (!fullType) return null\n const shortType = fullType.split(';')[0]\n if (!shortType) return null\n return shortType\n}\n\nconst ENCODING_ANY = '*/*'\n\nfunction parseDefEncoding({ encoding }: LexXrpcBody) {\n return encoding.split(',').map(trimString)\n}\n\nfunction trimString(str: string): string {\n return str.trim()\n}\n\nfunction isValidEncoding(output: LexXrpcBody, encoding?: string) {\n if (!encoding) return false\n\n const normalized = normalizeMime(encoding)\n if (!normalized) return false\n\n const allowed = parseDefEncoding(output)\n if (!allowed.length) return false\n\n if (allowed.includes(ENCODING_ANY)) return true\n if (allowed.includes(normalized)) return true\n\n // Check for wildcard matches (e.g. normalized=application/json, allowed=application/*)\n for (const allowedEnc of allowed) {\n if (\n allowedEnc.endsWith('/*') &&\n normalized.startsWith(allowedEnc.slice(0, -1))\n ) {\n return true\n }\n }\n\n return false\n}\n\ntype BodyPresence = 'missing' | 'empty' | 'present'\n\nfunction getBodyPresence(req: IncomingMessage): BodyPresence {\n if (req.headers['transfer-encoding'] != null) return 'present'\n if (req.headers['content-length'] === '0') return 'empty'\n if (req.headers['content-length'] != null) return 'present'\n return 'missing'\n}\n\nfunction createBodyParser(inputEncoding: string, options: RouteOptions) {\n if (inputEncoding === ENCODING_ANY) {\n // When the lexicon's input encoding is */*, the handler will determine how to process it\n return\n }\n const { jsonLimit, textLimit } = options\n const jsonParser = json({ limit: jsonLimit })\n const textParser = text({ limit: textLimit })\n // Transform json and text parser middlewares into a single function\n return (req: ExpressRequest, res: ExpressResponse) => {\n return new Promise<void>((resolve, reject) => {\n jsonParser(req, res, (err) => {\n if (err) return reject(XRPCError.fromError(err))\n textParser(req, res, (err) => {\n if (err) return reject(XRPCError.fromError(err))\n resolve()\n })\n })\n })\n }\n}\n\nfunction decodeBodyStream(\n req: IncomingMessage,\n maxSize: number | undefined,\n): Readable {\n const contentEncoding = req.headers['content-encoding']\n const contentLength = req.headers['content-length']\n\n const contentLengthParsed = contentLength\n ? parseInt(contentLength, 10)\n : undefined\n\n if (Number.isNaN(contentLengthParsed)) {\n throw new XRPCError(ResponseType.InvalidRequest, 'invalid content-length')\n }\n\n if (\n maxSize !== undefined &&\n contentLengthParsed !== undefined &&\n contentLengthParsed > maxSize\n ) {\n throw new XRPCError(\n ResponseType.PayloadTooLarge,\n 'request entity too large',\n )\n }\n\n let transforms: Duplex[]\n try {\n transforms = createDecoders(contentEncoding)\n } catch (cause) {\n throw new XRPCError(\n ResponseType.UnsupportedMediaType,\n 'unsupported content-encoding',\n undefined,\n { cause },\n )\n }\n\n if (maxSize !== undefined) {\n const maxSizeChecker = new MaxSizeChecker(\n maxSize,\n () =>\n new XRPCError(ResponseType.PayloadTooLarge, 'request entity too large'),\n )\n transforms.push(maxSizeChecker)\n }\n\n return transforms.length > 0\n ? (pipeline([req, ...transforms], () => {}) as Duplex)\n : req\n}\n\nexport function serverTimingHeader(timings: ServerTiming[]) {\n return timings\n .map((timing) => {\n let header = timing.name\n if (timing.duration) header += `;dur=${timing.duration}`\n if (timing.description) header += `;desc=\"${timing.description}\"`\n return header\n })\n .join(', ')\n}\n\nexport class ServerTimer implements ServerTiming {\n public duration?: number\n private startMs?: number\n constructor(\n public name: string,\n public description?: string,\n ) {}\n start() {\n this.startMs = Date.now()\n return this\n }\n stop() {\n assert(this.startMs, \"timer hasn't been started\")\n this.duration = Date.now() - this.startMs\n return this\n }\n}\n\nexport interface ServerTiming {\n name: string\n duration?: number\n description?: string\n}\n\nexport const parseReqNsid = (req: ExpressRequest | IncomingMessage) =>\n parseUrlNsid('originalUrl' in req ? req.originalUrl : req.url || '/')\n\n/**\n * Validates and extracts the nsid from an xrpc path\n */\nexport const parseUrlNsid = (url: string): string => {\n const nsid = extractUrlNsid(url)\n if (nsid) return nsid\n throw new InvalidRequestError('invalid xrpc path')\n}\n\nexport const extractUrlNsid = (url: string): string | undefined => {\n // /!\\ Hot path\n\n if (\n // Ordered by likelihood of failure\n url.length <= 6 ||\n url[5] !== '/' ||\n url[4] !== 'c' ||\n url[3] !== 'p' ||\n url[2] !== 'r' ||\n url[1] !== 'x' ||\n url[0] !== '/'\n ) {\n return undefined\n }\n\n const startOfNsid = 6\n\n let curr = startOfNsid\n let char: number\n let alphaNumRequired = true\n for (; curr < url.length; curr++) {\n char = url.charCodeAt(curr)\n if (\n (char >= 48 && char <= 57) || // 0-9\n (char >= 65 && char <= 90) || // A-Z\n (char >= 97 && char <= 122) // a-z\n ) {\n alphaNumRequired = false\n } else if (char === 45 /* \"-\" */ || char === 46 /* \".\" */) {\n if (alphaNumRequired) {\n return undefined\n }\n alphaNumRequired = true\n } else if (char === 47 /* \"/\" */) {\n // Allow trailing slash (next char is either EOS or \"?\")\n if (curr === url.length - 1 || url.charCodeAt(curr + 1) === 63) {\n break\n }\n return undefined\n } else if (char === 63 /* \"?\"\" */) {\n break\n } else {\n return undefined\n }\n }\n\n // last char was one of: '-', '.', '/'\n if (alphaNumRequired) {\n return undefined\n }\n\n // A domain name consists of minimum two characters\n if (curr - startOfNsid < 2) {\n return undefined\n }\n\n // @TODO check max length of nsid\n\n return url.slice(startOfNsid, curr)\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/xrpc-server",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
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/common": "^0.6.0",
26
- "@atproto/crypto": "^0.5.0",
27
- "@atproto/lex-data": "^0.1.0",
28
- "@atproto/lex-cbor": "^0.1.0",
29
- "@atproto/lex-client": "^0.1.0",
30
- "@atproto/lex-json": "^0.1.0",
31
- "@atproto/lex-schema": "^0.1.0",
32
- "@atproto/lexicon": "^0.7.0",
33
- "@atproto/ws-client": "^0.1.0",
34
- "@atproto/xrpc": "^0.8.0"
25
+ "@atproto/crypto": "^0.5.1",
26
+ "@atproto/lex-data": "^0.1.2",
27
+ "@atproto/common": "^0.6.3",
28
+ "@atproto/lex-cbor": "^0.1.1",
29
+ "@atproto/lex-json": "^0.1.1",
30
+ "@atproto/lex-client": "^0.1.4",
31
+ "@atproto/lexicon": "^0.7.2",
32
+ "@atproto/xrpc": "^0.8.1",
33
+ "@atproto/lex-schema": "^0.1.4",
34
+ "@atproto/ws-client": "^0.1.1"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@jest/globals": "^30.0.0",
@@ -45,10 +45,9 @@
45
45
  "jose": "^5.0.1",
46
46
  "key-encoder": "^2.0.3",
47
47
  "multiformats": "^13.0.0",
48
- "typescript": "^6.0.3",
49
- "@atproto/crypto": "^0.5.0",
50
- "@atproto/lex": "^0.1.0",
51
- "@atproto/lex-document": "^0.1.0"
48
+ "@atproto/crypto": "^0.5.1",
49
+ "@atproto/lex": "^0.1.4",
50
+ "@atproto/lex-document": "^0.1.1"
52
51
  },
53
52
  "type": "module",
54
53
  "exports": {
@@ -59,6 +58,6 @@
59
58
  },
60
59
  "scripts": {
61
60
  "test": "NODE_OPTIONS=--experimental-vm-modules jest",
62
- "build": "tsc --build tsconfig.build.json"
61
+ "build": "tsgo --build tsconfig.build.json"
63
62
  }
64
63
  }
@@ -0,0 +1,82 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http'
2
+ import {
3
+ CombinedRateLimiter,
4
+ RateLimitExceededError,
5
+ RateLimiterConsume,
6
+ RateLimiterI,
7
+ RateLimiterReset,
8
+ RateLimiterStatus,
9
+ } from './rate-limiter.js'
10
+
11
+ export interface HttpRateLimiterContext {
12
+ req: IncomingMessage
13
+ res?: ServerResponse
14
+ }
15
+
16
+ export type HttpRateLimiterOptions<
17
+ C extends HttpRateLimiterContext = HttpRateLimiterContext,
18
+ > = {
19
+ bypass?: (ctx: C) => boolean
20
+ }
21
+
22
+ /**
23
+ * Wraps a {@link RateLimiterI} class with an {@link RateLimiterI}
24
+ * implementation that will apply the appropriate headers to the response if a
25
+ * limit is exceeded.
26
+ */
27
+ export class HttpRateLimiter<
28
+ C extends HttpRateLimiterContext = HttpRateLimiterContext,
29
+ > implements RateLimiterI<C>
30
+ {
31
+ constructor(
32
+ private readonly rateLimiter: RateLimiterI<C>,
33
+ private readonly options: Readonly<HttpRateLimiterOptions<C>> = {},
34
+ ) {}
35
+
36
+ async handle(ctx: C): Promise<void> {
37
+ const { bypass } = this.options
38
+ if (bypass && bypass(ctx)) return
39
+
40
+ try {
41
+ const result = await this.consume(ctx)
42
+ if (result != null) {
43
+ setStatusHeaders(ctx, result)
44
+ }
45
+ } catch (err) {
46
+ if (err instanceof RateLimitExceededError) {
47
+ setStatusHeaders(ctx, err.status)
48
+ }
49
+
50
+ throw err
51
+ }
52
+ }
53
+
54
+ async consume(...args: Parameters<RateLimiterConsume<C>>) {
55
+ return this.rateLimiter.consume(...args)
56
+ }
57
+
58
+ async reset(...args: Parameters<RateLimiterReset<C>>) {
59
+ return this.rateLimiter.reset(...args)
60
+ }
61
+
62
+ static from<C extends HttpRateLimiterContext = HttpRateLimiterContext>(
63
+ rateLimiters: readonly RateLimiterI<C>[],
64
+ { bypass }: HttpRateLimiterOptions<C> = {},
65
+ ): HttpRateLimiter<C> | undefined {
66
+ const rateLimiter = CombinedRateLimiter.from(rateLimiters)
67
+ if (!rateLimiter) return undefined
68
+
69
+ return new HttpRateLimiter<C>(rateLimiter, { bypass })
70
+ }
71
+ }
72
+
73
+ function setStatusHeaders<
74
+ C extends HttpRateLimiterContext = HttpRateLimiterContext,
75
+ >(ctx: C, status: RateLimiterStatus) {
76
+ const resetAt = Math.floor((Date.now() + status.msBeforeNext) / 1e3)
77
+
78
+ ctx.res?.setHeader('RateLimit-Limit', status.limit)
79
+ ctx.res?.setHeader('RateLimit-Reset', resetAt)
80
+ ctx.res?.setHeader('RateLimit-Remaining', status.remainingPoints)
81
+ ctx.res?.setHeader('RateLimit-Policy', `${status.limit};w=${status.duration}`)
82
+ }