From c9b2775361ed457f6e2c8fd97cbb979664f8d7a3 Mon Sep 17 00:00:00 2001 From: Jared Wray Date: Fri, 12 Dec 2025 09:26:44 -0800 Subject: [PATCH 1/2] feat: ability to disable logging --- README.md | 22 ++++++++++++++++++++++ src/fastify-config.ts | 30 +++++++++++++++++------------- src/index.ts | 5 +++++ src/mock-http.ts | 29 +++++++++++++++++++++++++++-- test/mock-http.test.ts | 38 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a3cc0d8..d3bcd95 100644 --- a/README.md +++ b/README.md @@ -405,6 +405,26 @@ await mock.start(); // Restarts with new settings For the complete list of options, see the [@fastify/rate-limit documentation](https://github.com/fastify/fastify-rate-limit#options). +# Logging + +MockHttp uses [Pino](https://github.com/pinojs/pino) for logging via Fastify's built-in logger. Logging is **enabled by default** but can be disabled when needed. + +## Disabling Logging + +```javascript +import { MockHttp } from '@jaredwray/mockhttp'; + +const mock = new MockHttp({ logging: false }); +await mock.start(); +// Server runs silently without any log output +``` + +You can also disable logging via the `LOGGING` environment variable: + +```bash +LOGGING=false node your-app.js +``` + # API Reference ## MockHttp Class @@ -423,6 +443,7 @@ new MockHttp(options?) - `helmet?`: boolean - Use Helmet for security headers (default: true) - `apiDocs?`: boolean - Enable Swagger API documentation (default: true) - `rateLimit?`: RateLimitPluginOptions - Configure rate limiting (default: 1000 req/min, localhost excluded) + - `logging?`: boolean - Enable logging (default: true) - `httpBin?`: HttpBinOptions - Configure which httpbin routes to enable - `httpMethods?`: boolean - Enable HTTP method routes (default: true) - `redirects?`: boolean - Enable redirect routes (default: true) @@ -443,6 +464,7 @@ new MockHttp(options?) - `autoDetectPort`: boolean - Get/set auto-detect port behavior - `helmet`: boolean - Get/set Helmet security headers - `apiDocs`: boolean - Get/set API documentation +- `logging`: boolean - Get/set logging enabled state - `rateLimit`: RateLimitPluginOptions | undefined - Get/set rate limiting options - `httpBin`: HttpBinOptions - Get/set httpbin route options - `server`: FastifyInstance - Get/set the Fastify server instance diff --git a/src/fastify-config.ts b/src/fastify-config.ts index abf1cc7..09f3749 100644 --- a/src/fastify-config.ts +++ b/src/fastify-config.ts @@ -1,13 +1,17 @@ -export const fastifyConfig = { - logger: { - transport: { - target: "pino-pretty", - options: { - colorize: true, - translateTime: true, - ignore: "pid,hostname", - singleLine: true, - }, - }, - }, -}; +export function getFastifyConfig(logging = true) { + return { + logger: logging + ? { + transport: { + target: "pino-pretty", + options: { + colorize: true, + translateTime: true, + ignore: "pid,hostname", + singleLine: true, + }, + }, + } + : false, + }; +} diff --git a/src/index.ts b/src/index.ts index a55abb6..0e0064f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,11 @@ export const start = async () => { mockHttp.host = process.env.HOST; } + /* v8 ignore next -- @preserve */ + if (process.env.LOGGING === "false") { + mockHttp.logging = false; + } + await mockHttp.start(); return mockHttp; diff --git a/src/mock-http.ts b/src/mock-http.ts index 05f7ebf..5107a84 100644 --- a/src/mock-http.ts +++ b/src/mock-http.ts @@ -9,7 +9,7 @@ import { fastifySwagger } from "@fastify/swagger"; import { detect } from "detect-port"; import Fastify, { type FastifyInstance } from "fastify"; import { Hookified, type HookifiedOptions } from "hookified"; -import { fastifyConfig } from "./fastify-config.js"; +import { getFastifyConfig } from "./fastify-config.js"; import { anythingRoute } from "./routes/anything/index.js"; import { basicAuthRoute, @@ -100,6 +100,10 @@ export type MockHttpOptions = { * Hookified options. */ hookOptions?: HookifiedOptions; + /** + * Whether to enable logging. Defaults to true. + */ + logging?: boolean; }; export class MockHttp extends Hookified { @@ -108,6 +112,7 @@ export class MockHttp extends Hookified { private _autoDetectPort = true; private _helmet = true; private _apiDocs = true; + private _logging = true; private _httpBin: HttpBinOptions = { httpMethods: true, redirects: true, @@ -160,6 +165,10 @@ export class MockHttp extends Hookified { this._rateLimit = options.rateLimit as RateLimitPluginOptions; } } + + if (options?.logging !== undefined) { + this._logging = options.logging; + } } /** @@ -244,6 +253,22 @@ export class MockHttp extends Hookified { this._apiDocs = apiDocs; } + /** + * Whether to enable logging. Defaults to true. + * @default true + */ + public get logging(): boolean { + return this._logging; + } + + /** + * Whether to enable logging. Defaults to true. + * @default true + */ + public set logging(logging: boolean) { + this._logging = logging; + } + /** * HTTP Bin options. Defaults to all enabled. */ @@ -316,7 +341,7 @@ export class MockHttp extends Hookified { await this._server.close(); } - this._server = Fastify(fastifyConfig); + this._server = Fastify(getFastifyConfig(this._logging)); // Register injection hook to intercept requests this._server.addHook("onRequest", async (request, reply) => { diff --git a/test/mock-http.test.ts b/test/mock-http.test.ts index 394f282..ac2991d 100644 --- a/test/mock-http.test.ts +++ b/test/mock-http.test.ts @@ -434,6 +434,44 @@ describe("MockHttp", () => { }); }); + describe("logging", () => { + test("should be enabled by default", () => { + const mock = new MockHttp(); + expect(mock.logging).toBe(true); + }); + + test("should be able to disable logging via options", () => { + const mock = new MockHttp({ logging: false }); + expect(mock.logging).toBe(false); + }); + + test("should be able to enable logging via options", () => { + const mock = new MockHttp({ logging: true }); + expect(mock.logging).toBe(true); + }); + + test("should be able to set logging via setter", () => { + const mock = new MockHttp(); + expect(mock.logging).toBe(true); + + mock.logging = false; + expect(mock.logging).toBe(false); + + mock.logging = true; + expect(mock.logging).toBe(true); + }); + + test("should start server with logging disabled", async () => { + const mock = new MockHttp({ logging: false }); + await mock.start(); + + // Server should start successfully with logging disabled + expect(mock.server).toBeDefined(); + + await mock.close(); + }); + }); + describe("rate limiting", () => { test("should be enabled by default with 1000 requests per minute and localhost excluded", () => { const mock = new MockHttp(); From 89e5473534de99e2781afaff6469c92f6bb16683 Mon Sep 17 00:00:00 2001 From: Jared Wray Date: Fri, 12 Dec 2025 09:29:00 -0800 Subject: [PATCH 2/2] Update README.md --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index d3bcd95..04bb9a5 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,18 @@ A simple HTTP server that can be used to mock HTTP responses for testing purpose * Auto detect the port that is not in use * Maintained and updated regularly! +# Table of Contents +- [Deploy via Docker](#deploy-via-docker) +- [Deploy via Docker Compose](#deploy-via-docker-compose) +- [Deploy via NodeJS](#deploy-via-nodejs) +- [Response Injection (Tap Feature)](#response-injection-tap-feature) +- [Rate Limiting](#rate-limiting) +- [Logging](#logging) +- [API Reference](#api-reference) +- [About mockhttp.org](#about-mockhttporg) +- [Contributing](#contributing) +- [License](#license) + # Deploy via Docker ```bash docker run -d -p 3000:3000 jaredwray/mockhttp