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
JavaScript
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
;