UNPKG

apitally

Version:

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

237 lines (228 loc) 9.32 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/adonisjs/middleware.ts var middleware_exports = {}; __export(middleware_exports, { default: () => ApitallyMiddleware }); module.exports = __toCommonJS(middleware_exports); var import_node_perf_hooks = require("perf_hooks"); // src/common/consumerRegistry.ts var consumerFromStringOrObject = /* @__PURE__ */ __name((consumer) => { var _a, _b; if (typeof consumer === "string") { consumer = String(consumer).trim().substring(0, 128); return consumer ? { identifier: consumer } : null; } else { consumer.identifier = String(consumer.identifier).trim().substring(0, 128); consumer.name = (_a = consumer.name) == null ? void 0 : _a.trim().substring(0, 64); consumer.group = (_b = consumer.group) == null ? void 0 : _b.trim().substring(0, 64); return consumer.identifier ? consumer : null; } }, "consumerFromStringOrObject"); // src/common/headers.ts function parseContentLength(contentLength) { if (contentLength === void 0 || contentLength === null) { return void 0; } if (typeof contentLength === "number") { return contentLength; } if (typeof contentLength === "string") { const parsed = parseInt(contentLength); return isNaN(parsed) ? void 0 : parsed; } if (Array.isArray(contentLength)) { return parseContentLength(contentLength[0]); } return void 0; } __name(parseContentLength, "parseContentLength"); // src/common/requestLogger.ts var import_async_lock = __toESM(require("async-lock"), 1); var import_node_buffer2 = require("buffer"); var import_node_crypto3 = require("crypto"); var import_node_fs2 = require("fs"); var import_node_os2 = require("os"); var import_node_path2 = require("path"); // src/common/sentry.ts var sentry; (async () => { try { sentry = await import("@sentry/node"); } catch (e) { } })(); // src/common/serverErrorCounter.ts var import_node_crypto = require("crypto"); // src/common/tempGzipFile.ts var import_node_buffer = require("buffer"); var import_node_crypto2 = require("crypto"); var import_node_fs = require("fs"); var import_promises = require("fs/promises"); var import_node_os = require("os"); var import_node_path = require("path"); var import_node_zlib = require("zlib"); // src/common/requestLogger.ts var BODY_TOO_LARGE = import_node_buffer2.Buffer.from("<body too large>"); var BODY_MASKED = import_node_buffer2.Buffer.from("<masked>"); function convertHeaders(headers) { if (!headers) { return []; } if (headers instanceof Headers) { return Array.from(headers.entries()); } return Object.entries(headers).flatMap(([key, value]) => { if (value === void 0) { return []; } if (Array.isArray(value)) { return value.map((v) => [ key, v ]); } return [ [ key, value.toString() ] ]; }); } __name(convertHeaders, "convertHeaders"); // src/adonisjs/middleware.ts var _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 = import_node_perf_hooks.performance.now(); await next(); const responseTime = import_node_perf_hooks.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"); var ApitallyMiddleware = _ApitallyMiddleware; //# sourceMappingURL=middleware.cjs.map