UNPKG

apitally

Version:

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

113 lines 5.3 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); import { performance } from "node:perf_hooks"; import { consumerFromStringOrObject } from "../common/consumerRegistry.js"; import { parseContentLength } from "../common/headers.js"; import { convertHeaders } from "../common/requestLogger.js"; const _ApitallyMiddleware = class _ApitallyMiddleware { async handle(ctx, next) { const client = await ctx.containerResolver.make("apitallyClient"); const logsContext = await ctx.containerResolver.make("apitallyLogsContext"); if (!client.isEnabled() || ctx.request.method().toUpperCase() === "OPTIONS") { await next(); return; } return logsContext.run([], async () => { var _a, _b; const path = (_a = ctx.route) == null ? void 0 : _a.pattern; const timestamp = Date.now() / 1e3; const startTime = performance.now(); await next(); const responseTime = performance.now() - startTime; const requestSize = parseContentLength(ctx.request.header("content-length")); const requestContentType = (_b = ctx.request.header("content-type")) == null ? void 0 : _b.toString(); let responseStatus = ctx.response.getStatus(); let responseHeaders = ctx.response.getHeaders(); let responseSize; let responseContentType; const consumer = ctx.apitallyConsumer ? consumerFromStringOrObject(ctx.apitallyConsumer) : null; client.consumerRegistry.addOrUpdateConsumer(consumer); const onWriteHead = /* @__PURE__ */ __name((statusCode, headers) => { var _a2; responseStatus = statusCode; responseHeaders = headers; responseSize = parseContentLength(headers["content-length"]); responseContentType = (_a2 = headers["content-type"]) == null ? void 0 : _a2.toString(); if (path) { client.requestCounter.addRequest({ consumer: consumer == null ? void 0 : consumer.identifier, method: ctx.request.method(), path, statusCode: responseStatus, responseTime, requestSize, responseSize }); if (responseStatus === 422 && ctx.apitallyError && "code" in ctx.apitallyError && "messages" in ctx.apitallyError && ctx.apitallyError.code === "E_VALIDATION_ERROR" && Array.isArray(ctx.apitallyError.messages)) { ctx.apitallyError.messages.forEach((message) => { client.validationErrorCounter.addValidationError({ consumer: consumer == null ? void 0 : consumer.identifier, method: ctx.request.method(), path, loc: message.field, msg: message.message, type: message.rule }); }); } if (responseStatus === 500 && ctx.apitallyError) { client.serverErrorCounter.addServerError({ consumer: consumer == null ? void 0 : consumer.identifier, method: ctx.request.method(), path, type: ctx.apitallyError.name, msg: ctx.apitallyError.message, traceback: ctx.apitallyError.stack || "" }); } } }, "onWriteHead"); const originalWriteHead = ctx.response.response.writeHead; ctx.response.response.writeHead = (...args) => { originalWriteHead.apply(ctx.response.response, args); onWriteHead(args[0], typeof args[1] === "string" ? args[2] : args[1]); return ctx.response.response; }; if (client.requestLogger.enabled) { const logs = logsContext.getStore(); const onEnd = /* @__PURE__ */ __name((chunk) => { const requestBody = client.requestLogger.config.logRequestBody && client.requestLogger.isSupportedContentType(requestContentType) ? ctx.request.raw() : void 0; const responseBody = client.requestLogger.config.logResponseBody && client.requestLogger.isSupportedContentType(responseContentType) ? chunk : void 0; client.requestLogger.logRequest({ timestamp, method: ctx.request.method(), path, url: ctx.request.completeUrl(true), headers: convertHeaders(ctx.request.headers()), size: requestSize, consumer: consumer == null ? void 0 : consumer.identifier, body: requestBody ? Buffer.from(requestBody) : void 0 }, { statusCode: responseStatus, responseTime: responseTime / 1e3, headers: convertHeaders(responseHeaders), size: responseSize, body: responseBody ? Buffer.from(responseBody) : void 0 }, ctx.apitallyError, logs); }, "onEnd"); const originalEnd = ctx.response.response.end; ctx.response.response.end = (...args) => { originalEnd.apply(ctx.response.response, args); onEnd(typeof args[0] !== "function" ? args[0] : void 0); return ctx.response.response; }; } }); } }; __name(_ApitallyMiddleware, "ApitallyMiddleware"); let ApitallyMiddleware = _ApitallyMiddleware; export { ApitallyMiddleware as default }; //# sourceMappingURL=middleware.js.map