@jaredwray/mockhttp 3.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +45 -0
- package/dist/index.mjs +315 -2
- package/package.json +5 -3
- package/site/dist/api/index.html +188 -2
- package/site/dist/api/swagger.json +226 -1
- package/site/dist/changelog/index.html +20 -17
- package/site/dist/changelog/page/2/index.html +17 -16
- package/site/dist/changelog/{v0-2-1 → v3-0-1}/index.html +83 -9
- package/site/dist/changelog-latest.json +13 -13
- package/site/dist/changelog.json +13 -13
- package/site/dist/docs/bins/index.html +62 -2
- package/site/dist/docs/configuration/index.html +2 -2
- package/site/dist/docs/hosted/index.html +2 -2
- package/site/dist/docs/how-to-deploy/cloudflare/index.html +8 -3
- package/site/dist/docs/how-to-deploy/docker/index.html +2 -2
- package/site/dist/docs/how-to-deploy/wasmer/index.html +2 -2
- package/site/dist/docs/https/index.html +2 -2
- package/site/dist/docs/index.html +2 -2
- package/site/dist/docs/library/index.html +3 -3
- package/site/dist/docs/taps/index.html +2 -2
- package/site/dist/feed.xml +1 -1
- package/site/dist/index.html +2 -2
- package/site/dist/llms-full.txt +371 -15
- package/site/dist/llms.txt +1 -1
- package/site/dist/search-index.json +1 -1
- package/site/dist/sitemap.xml +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -2,6 +2,43 @@ import { RateLimitPluginOptions } from "@fastify/rate-limit";
|
|
|
2
2
|
import { FastifyInstance, FastifyRequest } from "fastify";
|
|
3
3
|
import { Hookified, HookifiedOptions } from "hookified";
|
|
4
4
|
import Keyv from "keyv";
|
|
5
|
+
//#region src/bin-store-diagnostics.d.ts
|
|
6
|
+
type BinStoreErrorInfo = {
|
|
7
|
+
name: string;
|
|
8
|
+
message: string;
|
|
9
|
+
code: string | number | null;
|
|
10
|
+
};
|
|
11
|
+
type BinHealth = {
|
|
12
|
+
status: "ok";
|
|
13
|
+
bins: {
|
|
14
|
+
store: "mongo" | "memory";
|
|
15
|
+
connected: true;
|
|
16
|
+
latencyMs: number;
|
|
17
|
+
uriPresent: boolean;
|
|
18
|
+
uri?: UriDiagnostics;
|
|
19
|
+
};
|
|
20
|
+
} | {
|
|
21
|
+
status: "error";
|
|
22
|
+
bins: {
|
|
23
|
+
store: "mongo" | "memory";
|
|
24
|
+
connected: false;
|
|
25
|
+
uriPresent: boolean;
|
|
26
|
+
uri?: UriDiagnostics;
|
|
27
|
+
error: BinStoreErrorInfo;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
/** Redacted URI facts for `GET /healthz`. No password and no full URI. */
|
|
31
|
+
type UriDiagnostics = {
|
|
32
|
+
length: number;
|
|
33
|
+
leadingWhitespace: boolean;
|
|
34
|
+
trailingWhitespace: boolean;
|
|
35
|
+
newline: boolean;
|
|
36
|
+
wrappedQuotes: boolean;
|
|
37
|
+
atCount: number;
|
|
38
|
+
passwordReserved: string[];
|
|
39
|
+
passwordHasPercent: boolean;
|
|
40
|
+
};
|
|
41
|
+
//#endregion
|
|
5
42
|
//#region src/certificate.d.ts
|
|
6
43
|
type CertificateOptions = {
|
|
7
44
|
/**
|
|
@@ -455,6 +492,7 @@ declare class MockHttp extends Hookified {
|
|
|
455
492
|
private _server;
|
|
456
493
|
private _taps;
|
|
457
494
|
private _bins;
|
|
495
|
+
private _binHealthCheck?;
|
|
458
496
|
constructor(options?: MockHttpOptions);
|
|
459
497
|
/**
|
|
460
498
|
* The port to listen on. If not provided, defaults to 3000 and detects the next available port if in use.
|
|
@@ -624,6 +662,13 @@ declare class MockHttp extends Hookified {
|
|
|
624
662
|
* The MockHttpBins instance for request bins.
|
|
625
663
|
*/
|
|
626
664
|
set bins(bins: MockHttpBins);
|
|
665
|
+
/**
|
|
666
|
+
* Override the bin storage probe used by `GET /healthz`.
|
|
667
|
+
* The default probe reads the in-memory Keyv.
|
|
668
|
+
*/
|
|
669
|
+
set binHealthCheck(check: () => Promise<BinHealth>);
|
|
670
|
+
/** Whether bin storage can serve a read or a MongoDB ping. */
|
|
671
|
+
checkBinStore(): Promise<BinHealth>;
|
|
627
672
|
/**
|
|
628
673
|
* Register plugins and routes without listening. Use `inject()` against
|
|
629
674
|
* `server`, or call `start()` to bind a port.
|
package/dist/index.mjs
CHANGED
|
@@ -293,6 +293,134 @@ function getFastifyConfig(logging = true) {
|
|
|
293
293
|
};
|
|
294
294
|
}
|
|
295
295
|
//#endregion
|
|
296
|
+
//#region src/bin-store-diagnostics.ts
|
|
297
|
+
const ENCODING_HINT = "Percent-encode reserved characters in the username and password (@ : / ? # [ ] $).";
|
|
298
|
+
const loggedPhases = /* @__PURE__ */ new WeakMap();
|
|
299
|
+
/** Error whose message is already safe to return to clients. */
|
|
300
|
+
var BinStoreFailure = class extends Error {
|
|
301
|
+
binStoreFailure = true;
|
|
302
|
+
constructor(message, cause) {
|
|
303
|
+
super(message, cause === void 0 ? void 0 : { cause });
|
|
304
|
+
this.name = "BinStoreFailure";
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
function isBinStoreFailure(error) {
|
|
308
|
+
return error instanceof BinStoreFailure || typeof error === "object" && error !== null && "binStoreFailure" in error && error.binStoreFailure === true;
|
|
309
|
+
}
|
|
310
|
+
function mongoUriFacts(uri) {
|
|
311
|
+
if (!uri) return {
|
|
312
|
+
present: false,
|
|
313
|
+
scheme: null
|
|
314
|
+
};
|
|
315
|
+
if (uri.startsWith("mongodb+srv://")) return {
|
|
316
|
+
present: true,
|
|
317
|
+
scheme: "mongodb+srv"
|
|
318
|
+
};
|
|
319
|
+
if (uri.startsWith("mongodb://")) return {
|
|
320
|
+
present: true,
|
|
321
|
+
scheme: "mongodb"
|
|
322
|
+
};
|
|
323
|
+
return {
|
|
324
|
+
present: true,
|
|
325
|
+
scheme: null
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Shape flags only. A normal URI has one `@` or zero `@`.
|
|
330
|
+
* A second `@` makes the driver throw `Invalid connection string` before the network call.
|
|
331
|
+
*/
|
|
332
|
+
function uriShape(uri) {
|
|
333
|
+
return {
|
|
334
|
+
whitespace: /\s/.test(uri),
|
|
335
|
+
wrappedQuotes: uri.startsWith("\"") || uri.startsWith("'") || uri.endsWith("\"") || uri.endsWith("'"),
|
|
336
|
+
extraAt: uri.split("@").length - 1 > 1
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
function replaceSecret(message, secret) {
|
|
340
|
+
if (secret.length < 3) return message;
|
|
341
|
+
if (/^[a-z]+$/i.test(secret) && secret.length < 8) return message;
|
|
342
|
+
return message.split(secret).join("[redacted]");
|
|
343
|
+
}
|
|
344
|
+
function sensitiveParts(uri) {
|
|
345
|
+
const parts = [];
|
|
346
|
+
const body = uri.replace(/^mongodb(?:\+srv)?:\/\//i, "");
|
|
347
|
+
const at = body.lastIndexOf("@");
|
|
348
|
+
if (at >= 0) {
|
|
349
|
+
const userinfo = body.slice(0, at);
|
|
350
|
+
const colon = userinfo.indexOf(":");
|
|
351
|
+
if (colon >= 0) parts.push(userinfo.slice(0, colon), userinfo.slice(colon + 1));
|
|
352
|
+
else if (userinfo) parts.push(userinfo);
|
|
353
|
+
const hostname = (body.slice(at + 1).split(/[/?]/)[0] ?? "").split(":")[0] ?? "";
|
|
354
|
+
if (hostname) parts.push(hostname);
|
|
355
|
+
} else {
|
|
356
|
+
const hostname = (body.split(/[/?]/)[0] ?? "").split(":")[0] ?? "";
|
|
357
|
+
if (hostname) parts.push(hostname);
|
|
358
|
+
}
|
|
359
|
+
return parts;
|
|
360
|
+
}
|
|
361
|
+
function redactSecrets(message, uri) {
|
|
362
|
+
let out = message;
|
|
363
|
+
if (uri) {
|
|
364
|
+
out = out.split(uri).join("[redacted-uri]");
|
|
365
|
+
for (const part of sensitiveParts(uri)) out = replaceSecret(out, part);
|
|
366
|
+
}
|
|
367
|
+
out = out.replace(/mongodb(?:\+srv)?:\/\/\S+/gi, "[redacted-uri]");
|
|
368
|
+
out = out.replace(/\/\/([^/\s:@]+):([^/\s@]+)@/g, "//[redacted]:[redacted]@");
|
|
369
|
+
return out;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Add the encode hint only when the driver message is already a parse error.
|
|
373
|
+
* A DNS error or a scheme error keeps its own text.
|
|
374
|
+
*/
|
|
375
|
+
function withEncodingHint(message) {
|
|
376
|
+
if (!/invalid connection string|unescaped characters/i.test(message) || message.includes("Percent-encode")) return message;
|
|
377
|
+
return `${message}. ${ENCODING_HINT}`;
|
|
378
|
+
}
|
|
379
|
+
function redactStoreError(error, uri) {
|
|
380
|
+
const name = error instanceof Error && error.name ? error.name : "Error";
|
|
381
|
+
const raw = error instanceof Error ? error.message : "Bin store request failed";
|
|
382
|
+
const codeValue = typeof error === "object" && error !== null && "code" in error && error.code != null ? error.code : null;
|
|
383
|
+
const code = typeof codeValue === "string" || typeof codeValue === "number" ? codeValue : null;
|
|
384
|
+
return {
|
|
385
|
+
name,
|
|
386
|
+
message: withEncodingHint(redactSecrets(raw, uri)),
|
|
387
|
+
code
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function alreadyLogged(error, phase) {
|
|
391
|
+
if (typeof error !== "object" || error === null) return false;
|
|
392
|
+
let phases = loggedPhases.get(error);
|
|
393
|
+
if (!phases) {
|
|
394
|
+
phases = /* @__PURE__ */ new Set();
|
|
395
|
+
loggedPhases.set(error, phases);
|
|
396
|
+
}
|
|
397
|
+
if (phases.has(phase)) return true;
|
|
398
|
+
phases.add(phase);
|
|
399
|
+
return false;
|
|
400
|
+
}
|
|
401
|
+
/** One JSON line. Safe to print in Workers logs. */
|
|
402
|
+
function logBinStore(input) {
|
|
403
|
+
if (input.error !== void 0 && alreadyLogged(input.error, input.phase)) return;
|
|
404
|
+
const facts = mongoUriFacts(input.uri);
|
|
405
|
+
const payload = {
|
|
406
|
+
source: "mockhttp.bin-store",
|
|
407
|
+
phase: input.phase,
|
|
408
|
+
store: input.store,
|
|
409
|
+
uriPresent: facts.present,
|
|
410
|
+
scheme: facts.scheme
|
|
411
|
+
};
|
|
412
|
+
if (input.uri) payload.uriShape = uriShape(input.uri);
|
|
413
|
+
if (input.connected !== void 0) payload.connected = input.connected;
|
|
414
|
+
if (input.latencyMs !== void 0) payload.latencyMs = input.latencyMs;
|
|
415
|
+
if (input.error !== void 0) payload.error = redactStoreError(input.error, input.uri);
|
|
416
|
+
const line = JSON.stringify(payload);
|
|
417
|
+
if (input.level === "info") {
|
|
418
|
+
console.info(line);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
console.error(line);
|
|
422
|
+
}
|
|
423
|
+
//#endregion
|
|
296
424
|
//#region src/mock-http-bins.ts
|
|
297
425
|
const DEFAULT_TTL_MS = 864e5;
|
|
298
426
|
const DEFAULT_MAX_REQUESTS = 100;
|
|
@@ -439,6 +567,7 @@ var MockHttpBins = class {
|
|
|
439
567
|
try {
|
|
440
568
|
saved = await this._keyv.set(this.binKey(doc.bin.id), doc, this.ttlFor(doc.bin));
|
|
441
569
|
} catch (cause) {
|
|
570
|
+
if (isBinStoreFailure(cause)) throw new BinStoreFailure(`${message}. ${cause.message}`, cause);
|
|
442
571
|
throw new Error(message, { cause });
|
|
443
572
|
}
|
|
444
573
|
if (!saved) throw new Error(message);
|
|
@@ -1162,6 +1291,18 @@ const clearRequestsSchema = {
|
|
|
1162
1291
|
}
|
|
1163
1292
|
};
|
|
1164
1293
|
/**
|
|
1294
|
+
* Public capture URL for a new bin.
|
|
1295
|
+
* The last forwarded protocol wins, matching a proxy chain. An unrecognized
|
|
1296
|
+
* value falls back to the socket protocol, then `http`.
|
|
1297
|
+
*/
|
|
1298
|
+
function binCaptureUrl(forwardedProto, socketProtocol, host, id) {
|
|
1299
|
+
const forwarded = (Array.isArray(forwardedProto) ? forwardedProto.join(",") : forwardedProto)?.split(",").at(-1)?.trim().toLowerCase();
|
|
1300
|
+
let protocol = "http";
|
|
1301
|
+
if (forwarded === "https" || forwarded === "http") protocol = forwarded;
|
|
1302
|
+
else if (socketProtocol === "https") protocol = "https";
|
|
1303
|
+
return `${protocol}://${host}/b/${id}`;
|
|
1304
|
+
}
|
|
1305
|
+
/**
|
|
1165
1306
|
* Create a Fastify plugin that registers bin management endpoints, with the
|
|
1166
1307
|
* provided {@link MockHttpBins} injected.
|
|
1167
1308
|
*/
|
|
@@ -1173,7 +1314,7 @@ const binsManagementRoute = (bins) => {
|
|
|
1173
1314
|
const host = request.headers.host ?? request.hostname;
|
|
1174
1315
|
return {
|
|
1175
1316
|
...bin,
|
|
1176
|
-
url:
|
|
1317
|
+
url: binCaptureUrl(request.headers["x-mockhttp-forwarded-proto"] ?? request.headers["x-forwarded-proto"], request.protocol, host, bin.id)
|
|
1177
1318
|
};
|
|
1178
1319
|
});
|
|
1179
1320
|
fastify.get("/bins", { schema: listBinsSchema }, async (_request, _reply) => ({ bins: await bins.listBins() }));
|
|
@@ -1844,6 +1985,164 @@ const uuidRoute = (fastify) => {
|
|
|
1844
1985
|
fastify.get("/uuid", { schema: uuidSchema }, async () => ({ uuid: randomUUID() }));
|
|
1845
1986
|
};
|
|
1846
1987
|
//#endregion
|
|
1988
|
+
//#region src/routes/health.ts
|
|
1989
|
+
/** Cheap read against the in-memory Keyv used when MongoDB is not configured. */
|
|
1990
|
+
async function checkMemoryBinStore(keyv) {
|
|
1991
|
+
const started = Date.now();
|
|
1992
|
+
try {
|
|
1993
|
+
await keyv.get("__mockhttp_healthz__");
|
|
1994
|
+
return {
|
|
1995
|
+
status: "ok",
|
|
1996
|
+
bins: {
|
|
1997
|
+
store: "memory",
|
|
1998
|
+
connected: true,
|
|
1999
|
+
latencyMs: Math.max(0, Date.now() - started),
|
|
2000
|
+
uriPresent: false
|
|
2001
|
+
}
|
|
2002
|
+
};
|
|
2003
|
+
} catch (error) {
|
|
2004
|
+
logBinStore({
|
|
2005
|
+
phase: "healthz",
|
|
2006
|
+
store: "memory",
|
|
2007
|
+
error
|
|
2008
|
+
});
|
|
2009
|
+
return {
|
|
2010
|
+
status: "error",
|
|
2011
|
+
bins: {
|
|
2012
|
+
store: "memory",
|
|
2013
|
+
connected: false,
|
|
2014
|
+
uriPresent: false,
|
|
2015
|
+
error: redactStoreError(error)
|
|
2016
|
+
}
|
|
2017
|
+
};
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
const binHealthFields = {
|
|
2021
|
+
store: {
|
|
2022
|
+
type: "string",
|
|
2023
|
+
enum: ["mongo", "memory"]
|
|
2024
|
+
},
|
|
2025
|
+
connected: { type: "boolean" },
|
|
2026
|
+
latencyMs: { type: "integer" },
|
|
2027
|
+
uriPresent: { type: "boolean" },
|
|
2028
|
+
uri: {
|
|
2029
|
+
type: "object",
|
|
2030
|
+
properties: {
|
|
2031
|
+
length: { type: "integer" },
|
|
2032
|
+
leadingWhitespace: { type: "boolean" },
|
|
2033
|
+
trailingWhitespace: { type: "boolean" },
|
|
2034
|
+
newline: { type: "boolean" },
|
|
2035
|
+
wrappedQuotes: { type: "boolean" },
|
|
2036
|
+
atCount: { type: "integer" },
|
|
2037
|
+
passwordReserved: {
|
|
2038
|
+
type: "array",
|
|
2039
|
+
items: { type: "string" }
|
|
2040
|
+
},
|
|
2041
|
+
passwordHasPercent: { type: "boolean" }
|
|
2042
|
+
},
|
|
2043
|
+
required: [
|
|
2044
|
+
"length",
|
|
2045
|
+
"leadingWhitespace",
|
|
2046
|
+
"trailingWhitespace",
|
|
2047
|
+
"newline",
|
|
2048
|
+
"wrappedQuotes",
|
|
2049
|
+
"atCount",
|
|
2050
|
+
"passwordReserved",
|
|
2051
|
+
"passwordHasPercent"
|
|
2052
|
+
]
|
|
2053
|
+
}
|
|
2054
|
+
};
|
|
2055
|
+
const healthSchema = {
|
|
2056
|
+
description: "Report whether bin storage is reachable. MongoDB failures include the driver error. The scheme, the host, the username, the password, the password length, and the full URI are never returned.",
|
|
2057
|
+
tags: ["Health"],
|
|
2058
|
+
response: {
|
|
2059
|
+
200: {
|
|
2060
|
+
type: "object",
|
|
2061
|
+
properties: {
|
|
2062
|
+
status: {
|
|
2063
|
+
type: "string",
|
|
2064
|
+
enum: ["ok"]
|
|
2065
|
+
},
|
|
2066
|
+
bins: {
|
|
2067
|
+
type: "object",
|
|
2068
|
+
properties: binHealthFields,
|
|
2069
|
+
required: [
|
|
2070
|
+
"store",
|
|
2071
|
+
"connected",
|
|
2072
|
+
"latencyMs",
|
|
2073
|
+
"uriPresent"
|
|
2074
|
+
]
|
|
2075
|
+
}
|
|
2076
|
+
},
|
|
2077
|
+
required: ["status", "bins"]
|
|
2078
|
+
},
|
|
2079
|
+
503: {
|
|
2080
|
+
type: "object",
|
|
2081
|
+
properties: {
|
|
2082
|
+
status: {
|
|
2083
|
+
type: "string",
|
|
2084
|
+
enum: ["error"]
|
|
2085
|
+
},
|
|
2086
|
+
bins: {
|
|
2087
|
+
type: "object",
|
|
2088
|
+
properties: {
|
|
2089
|
+
...binHealthFields,
|
|
2090
|
+
error: {
|
|
2091
|
+
type: "object",
|
|
2092
|
+
properties: {
|
|
2093
|
+
name: { type: "string" },
|
|
2094
|
+
message: { type: "string" },
|
|
2095
|
+
code: { type: [
|
|
2096
|
+
"string",
|
|
2097
|
+
"number",
|
|
2098
|
+
"null"
|
|
2099
|
+
] }
|
|
2100
|
+
},
|
|
2101
|
+
required: [
|
|
2102
|
+
"name",
|
|
2103
|
+
"message",
|
|
2104
|
+
"code"
|
|
2105
|
+
]
|
|
2106
|
+
}
|
|
2107
|
+
},
|
|
2108
|
+
required: [
|
|
2109
|
+
"store",
|
|
2110
|
+
"connected",
|
|
2111
|
+
"uriPresent",
|
|
2112
|
+
"error"
|
|
2113
|
+
]
|
|
2114
|
+
}
|
|
2115
|
+
},
|
|
2116
|
+
required: ["status", "bins"]
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
};
|
|
2120
|
+
const healthRoute = (check) => (fastify) => {
|
|
2121
|
+
fastify.get("/healthz", { schema: healthSchema }, async (_request, reply) => {
|
|
2122
|
+
try {
|
|
2123
|
+
const report = await check();
|
|
2124
|
+
if (report.status === "error") return reply.status(503).send(report);
|
|
2125
|
+
return report;
|
|
2126
|
+
} catch (error) {
|
|
2127
|
+
logBinStore({
|
|
2128
|
+
phase: "healthz",
|
|
2129
|
+
store: "unknown",
|
|
2130
|
+
error
|
|
2131
|
+
});
|
|
2132
|
+
const info = redactStoreError(error);
|
|
2133
|
+
return reply.status(503).send({
|
|
2134
|
+
status: "error",
|
|
2135
|
+
bins: {
|
|
2136
|
+
store: "mongo",
|
|
2137
|
+
connected: false,
|
|
2138
|
+
uriPresent: false,
|
|
2139
|
+
error: info
|
|
2140
|
+
}
|
|
2141
|
+
});
|
|
2142
|
+
}
|
|
2143
|
+
});
|
|
2144
|
+
};
|
|
2145
|
+
//#endregion
|
|
1847
2146
|
//#region src/routes/http-methods/delete.ts
|
|
1848
2147
|
const deleteSchema = {
|
|
1849
2148
|
description: "Handles a DELETE request and returns request information",
|
|
@@ -3355,7 +3654,7 @@ A simple HTTP server that can be used to mock HTTP responses for testing purpose
|
|
|
3355
3654
|
|
|
3356
3655
|
[mockhttp.org](https://mockhttp.org) is a free hosted instance of this codebase for testing. It runs on a Cloudflare Worker (no containers): documentation is served from Workers Assets, and mock APIs such as \`/get\` and \`/post\` run in the Worker. The service is globally available and rate-limited (1000 requests per minute per IP) to prevent abuse.
|
|
3357
3656
|
`,
|
|
3358
|
-
version: "3.0.
|
|
3657
|
+
version: "3.0.1"
|
|
3359
3658
|
} } };
|
|
3360
3659
|
const withLocalServer = (spec) => {
|
|
3361
3660
|
spec.servers = [{
|
|
@@ -3516,6 +3815,7 @@ var MockHttp = class extends Hookified {
|
|
|
3516
3815
|
_server;
|
|
3517
3816
|
_taps = new TapManager();
|
|
3518
3817
|
_bins = new MockHttpBins();
|
|
3818
|
+
_binHealthCheck;
|
|
3519
3819
|
constructor(options) {
|
|
3520
3820
|
super(options?.hookOptions);
|
|
3521
3821
|
if (options?.port) this._port = options.port;
|
|
@@ -3782,6 +4082,18 @@ var MockHttp = class extends Hookified {
|
|
|
3782
4082
|
this._bins = bins;
|
|
3783
4083
|
}
|
|
3784
4084
|
/**
|
|
4085
|
+
* Override the bin storage probe used by `GET /healthz`.
|
|
4086
|
+
* The default probe reads the in-memory Keyv.
|
|
4087
|
+
*/
|
|
4088
|
+
set binHealthCheck(check) {
|
|
4089
|
+
this._binHealthCheck = check;
|
|
4090
|
+
}
|
|
4091
|
+
/** Whether bin storage can serve a read or a MongoDB ping. */
|
|
4092
|
+
checkBinStore() {
|
|
4093
|
+
if (this._binHealthCheck) return this._binHealthCheck();
|
|
4094
|
+
return checkMemoryBinStore(this._bins.keyv);
|
|
4095
|
+
}
|
|
4096
|
+
/**
|
|
3785
4097
|
* Register plugins and routes without listening. Use `inject()` against
|
|
3786
4098
|
* `server`, or call `start()` to bind a port.
|
|
3787
4099
|
*/
|
|
@@ -3834,6 +4146,7 @@ var MockHttp = class extends Hookified {
|
|
|
3834
4146
|
} } });
|
|
3835
4147
|
if (this._rateLimit) await this._server.register(fastifyRateLimit, this._rateLimit);
|
|
3836
4148
|
if (this._apiDocs) await this.registerSwagger();
|
|
4149
|
+
await this.server.register(healthRoute(() => this.checkBinStore()));
|
|
3837
4150
|
const { httpMethods, redirects, requestInspection, responseInspection, responseFormats, statusCodes, cookies, anything, auth, images, dynamicData, bins } = this._httpBin;
|
|
3838
4151
|
if (httpMethods) await this.registerHttpMethods();
|
|
3839
4152
|
if (statusCodes) await this.registerStatusCodeRoutes();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jaredwray/mockhttp",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Mock Http - Easy way to mock http with httpbin replacement",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
"tsx": "^4.23.15",
|
|
50
50
|
"typescript": "7.0.2",
|
|
51
51
|
"vite": "^8.3.4",
|
|
52
|
-
"vitest": "^5.0.3"
|
|
52
|
+
"vitest": "^5.0.3",
|
|
53
|
+
"wrangler": "4.127.0"
|
|
53
54
|
},
|
|
54
55
|
"dependencies": {
|
|
55
56
|
"@fastify/cookie": "^11.1.3",
|
|
@@ -63,6 +64,7 @@
|
|
|
63
64
|
"hookified": "^3.0.4",
|
|
64
65
|
"html-escaper": "^3.0.3",
|
|
65
66
|
"keyv": "^6.1.0",
|
|
67
|
+
"mongodb": "7.7.0",
|
|
66
68
|
"pino": "^10.4.0",
|
|
67
69
|
"pino-pretty": "^13.2.0"
|
|
68
70
|
},
|
|
@@ -70,7 +72,7 @@
|
|
|
70
72
|
"dist",
|
|
71
73
|
"public",
|
|
72
74
|
"site/dist",
|
|
73
|
-
"
|
|
75
|
+
"LICENSE"
|
|
74
76
|
],
|
|
75
77
|
"scripts": {
|
|
76
78
|
"lint": "biome check --write --error-on-warnings",
|