UNPKG

apitally

Version:

Simple API monitoring & analytics for REST APIs built with Express, Fastify, NestJS, AdonisJS, Hono, H3, Elysia, Hapi, and Koa.

1 lines 4.19 kB
{"version":3,"sources":["../../src/common/response.ts"],"sourcesContent":["type CaptureResponseOptions = {\n captureBody: boolean;\n maxBodySize: number;\n readTimeout: number;\n};\n\nexport type CapturedResponse = {\n body?: Buffer;\n size: number;\n completed: boolean;\n error?: Error;\n};\n\nexport function captureResponse(\n response: Response,\n {\n captureBody = false,\n maxBodySize = 0,\n readTimeout = 5000,\n }: Partial<CaptureResponseOptions> = {},\n): [Response, Promise<CapturedResponse>] {\n if (!response.body) {\n return [\n response,\n Promise.resolve({\n size: 0,\n completed: true,\n }),\n ];\n }\n\n let size = 0;\n let bodySizeLimitExceeded = false;\n let readStarted = false;\n const chunks: Uint8Array[] = [];\n\n const { readable, writable } = new TransformStream({\n transform: (chunk, controller) => {\n readStarted = true;\n size += chunk.byteLength;\n if (captureBody && !bodySizeLimitExceeded) {\n if (size > maxBodySize) {\n bodySizeLimitExceeded = true;\n chunks.length = 0;\n } else {\n chunks.push(chunk);\n }\n }\n controller.enqueue(chunk);\n },\n });\n\n const pipePromise = response.body\n .pipeTo(writable)\n .then(() => ({\n body: chunks.length > 0 ? Buffer.concat(chunks) : undefined,\n size,\n completed: true,\n }))\n .catch((error) => ({\n size,\n completed: false,\n error,\n }));\n const timeoutPromise = new Promise<CapturedResponse>((resolve) =>\n setTimeout(() => {\n if (!readStarted) {\n resolve({\n size: 0,\n completed: false,\n });\n }\n }, readTimeout),\n );\n const racePromise = Promise.race([pipePromise, timeoutPromise]);\n\n const newResponse = new Response(readable, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n\n // Force Bun to initialize the headers (workaround for lazy evaluation in Bun's Response implementation)\n void newResponse.headers;\n\n return [newResponse, racePromise];\n}\n\nexport function getResponseJson(body: Buffer) {\n if (body.length === 0) {\n return null;\n }\n try {\n return JSON.parse(body.toString());\n } catch (error) {\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAaA;;;;;;AAAO,SAASA,gBACdC,UACA,EACEC,cAAc,OACdC,cAAc,GACdC,cAAc,IAAI,IACiB,CAAC,GAAC;AAEvC,MAAI,CAACH,SAASI,MAAM;AAClB,WAAO;MACLJ;MACAK,QAAQC,QAAQ;QACdC,MAAM;QACNC,WAAW;MACb,CAAA;;EAEJ;AAEA,MAAID,OAAO;AACX,MAAIE,wBAAwB;AAC5B,MAAIC,cAAc;AAClB,QAAMC,SAAuB,CAAA;AAE7B,QAAM,EAAEC,UAAUC,SAAQ,IAAK,IAAIC,gBAAgB;IACjDC,WAAW,wBAACC,OAAOC,eAAAA;AACjBP,oBAAc;AACdH,cAAQS,MAAME;AACd,UAAIjB,eAAe,CAACQ,uBAAuB;AACzC,YAAIF,OAAOL,aAAa;AACtBO,kCAAwB;AACxBE,iBAAOQ,SAAS;QAClB,OAAO;AACLR,iBAAOS,KAAKJ,KAAAA;QACd;MACF;AACAC,iBAAWI,QAAQL,KAAAA;IACrB,GAZW;EAab,CAAA;AAEA,QAAMM,cAActB,SAASI,KAC1BmB,OAAOV,QAAAA,EACPW,KAAK,OAAO;IACXpB,MAAMO,OAAOQ,SAAS,IAAIM,OAAOC,OAAOf,MAAAA,IAAUgB;IAClDpB;IACAC,WAAW;EACb,EAAA,EACCoB,MAAM,CAACC,WAAW;IACjBtB;IACAC,WAAW;IACXqB;EACF,EAAA;AACF,QAAMC,iBAAiB,IAAIzB,QAA0B,CAACC,YACpDyB,WAAW,MAAA;AACT,QAAI,CAACrB,aAAa;AAChBJ,cAAQ;QACNC,MAAM;QACNC,WAAW;MACb,CAAA;IACF;EACF,GAAGL,WAAAA,CAAAA;AAEL,QAAM6B,cAAc3B,QAAQ4B,KAAK;IAACX;IAAaQ;GAAe;AAE9D,QAAMI,cAAc,IAAIC,SAASvB,UAAU;IACzCwB,QAAQpC,SAASoC;IACjBC,YAAYrC,SAASqC;IACrBC,SAAStC,SAASsC;EACpB,CAAA;AAGA,OAAKJ,YAAYI;AAEjB,SAAO;IAACJ;IAAaF;;AACvB;AAzEgBjC;AA2ET,SAASwC,gBAAgBnC,MAAY;AAC1C,MAAIA,KAAKe,WAAW,GAAG;AACrB,WAAO;EACT;AACA,MAAI;AACF,WAAOqB,KAAKC,MAAMrC,KAAKsC,SAAQ,CAAA;EACjC,SAASb,OAAO;AACd,WAAO;EACT;AACF;AATgBU;","names":["captureResponse","response","captureBody","maxBodySize","readTimeout","body","Promise","resolve","size","completed","bodySizeLimitExceeded","readStarted","chunks","readable","writable","TransformStream","transform","chunk","controller","byteLength","length","push","enqueue","pipePromise","pipeTo","then","Buffer","concat","undefined","catch","error","timeoutPromise","setTimeout","racePromise","race","newResponse","Response","status","statusText","headers","getResponseJson","JSON","parse","toString"]}