@jaredwray/mockhttp 1.8.1 → 2.0.0
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/README.md +29 -7
- package/dist/index.d.mts +135 -33
- package/dist/index.mjs +360 -342
- package/package.json +22 -18
- package/site/dist/api/index.html +17983 -0
- package/site/dist/api/swagger.json +5487 -0
- package/site/dist/changelog/index.html +767 -0
- package/site/dist/changelog/page/2/index.html +578 -0
- package/site/dist/changelog/v0-1-0/index.html +453 -0
- package/site/dist/changelog/v0-2-0/index.html +437 -0
- package/site/dist/changelog/v0-2-1/index.html +438 -0
- package/site/dist/changelog/v0-2-2/index.html +436 -0
- package/site/dist/changelog/v0-2-3/index.html +440 -0
- package/site/dist/changelog/v0-3-0/index.html +443 -0
- package/site/dist/changelog/v0-4-0/index.html +437 -0
- package/site/dist/changelog/v0-4-1/index.html +441 -0
- package/site/dist/changelog/v0-4-2/index.html +446 -0
- package/site/dist/changelog/v0-4-3/index.html +437 -0
- package/site/dist/changelog/v0-5-0/index.html +443 -0
- package/site/dist/changelog/v0-6-0/index.html +444 -0
- package/site/dist/changelog/v0-6-1/index.html +441 -0
- package/site/dist/changelog/v0-7-0/index.html +445 -0
- package/site/dist/changelog/v0-8-0/index.html +440 -0
- package/site/dist/changelog/v0-9-0/index.html +437 -0
- package/site/dist/changelog/v1-0-0/index.html +446 -0
- package/site/dist/changelog/v1-0-1/index.html +437 -0
- package/site/dist/changelog/v1-1-0/index.html +445 -0
- package/site/dist/changelog/v1-2-0/index.html +443 -0
- package/site/dist/changelog/v1-3-0/index.html +448 -0
- package/site/dist/changelog/v1-4-0/index.html +445 -0
- package/site/dist/changelog/v1-5-0/index.html +439 -0
- package/site/dist/changelog/v1-5-1/index.html +443 -0
- package/site/dist/changelog/v1-6-0/index.html +467 -0
- package/site/dist/changelog/v1-7-0/index.html +462 -0
- package/site/dist/changelog/v1-8-0/index.html +481 -0
- package/site/dist/changelog/v1-8-1/index.html +457 -0
- package/site/dist/changelog/v1-9-0/index.html +495 -0
- package/site/dist/changelog/v2-0-0/index.html +500 -0
- package/site/dist/changelog-latest.json +269 -0
- package/site/dist/changelog.json +399 -0
- package/site/dist/css/api.css +1113 -0
- package/site/dist/css/highlight/highlight.min.js +1433 -0
- package/site/dist/css/highlight/styles/base16/docula.css +123 -0
- package/site/dist/css/home.css +133 -0
- package/site/dist/css/styles.css +1227 -0
- package/site/dist/css/variables.css +32 -0
- package/site/dist/docs/bins/index.html +942 -0
- package/site/dist/docs/configuration/index.html +771 -0
- package/site/dist/docs/hosted/index.html +544 -0
- package/site/dist/docs/https/index.html +758 -0
- package/site/dist/docs/index.html +601 -0
- package/site/dist/docs/library/index.html +780 -0
- package/site/dist/docs/taps/index.html +708 -0
- package/site/dist/favicon.svg +14 -0
- package/site/dist/feed.xml +1 -0
- package/site/dist/index.html +601 -0
- package/site/dist/js/api.js +363 -0
- package/site/dist/js/search.js +436 -0
- package/site/dist/llms-full.txt +7415 -0
- package/site/dist/llms.txt +40 -0
- package/site/dist/logo.svg +21 -0
- package/site/dist/robots.txt +2 -0
- package/site/dist/search-index.json +1 -0
- package/site/dist/sitemap.xml +1 -0
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import process$1 from "node:process";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
3
|
import * as fsPromises from "node:fs/promises";
|
|
3
4
|
import path, { join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
4
6
|
import fastifyCookie from "@fastify/cookie";
|
|
5
7
|
import fastifyHelmet from "@fastify/helmet";
|
|
6
8
|
import fastifyRateLimit from "@fastify/rate-limit";
|
|
@@ -12,10 +14,8 @@ import { Hookified } from "hookified";
|
|
|
12
14
|
import * as crypto$1 from "node:crypto";
|
|
13
15
|
import crypto, { randomBytes, randomInt, randomUUID, timingSafeEqual } from "node:crypto";
|
|
14
16
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
15
|
-
import { readFileSync } from "node:fs";
|
|
16
17
|
import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
|
|
17
18
|
import { escape } from "html-escaper";
|
|
18
|
-
import { fastifySwaggerUi } from "@fastify/swagger-ui";
|
|
19
19
|
//#region src/bin-store.ts
|
|
20
20
|
/**
|
|
21
21
|
* In-memory implementation of {@link BinStore} backed by two Maps. State is
|
|
@@ -70,9 +70,9 @@ var InMemoryBinStore = class {
|
|
|
70
70
|
};
|
|
71
71
|
//#endregion
|
|
72
72
|
//#region src/bin-manager.ts
|
|
73
|
-
const DEFAULT_TTL_MS =
|
|
73
|
+
const DEFAULT_TTL_MS = 864e5;
|
|
74
74
|
const DEFAULT_MAX_REQUESTS = 100;
|
|
75
|
-
const DEFAULT_MAX_BODY_SIZE =
|
|
75
|
+
const DEFAULT_MAX_BODY_SIZE = 1048576;
|
|
76
76
|
const DEFAULT_ID_LENGTH = 12;
|
|
77
77
|
const DEFAULT_CLEANUP_INTERVAL_MS = 6e4;
|
|
78
78
|
/**
|
|
@@ -188,7 +188,7 @@ var BinManager = class {
|
|
|
188
188
|
this._cleanupTimer = setInterval(() => {
|
|
189
189
|
this._store.cleanupExpired(Date.now());
|
|
190
190
|
}, this._cleanupIntervalMs);
|
|
191
|
-
this._cleanupTimer.unref();
|
|
191
|
+
this._cleanupTimer.unref?.();
|
|
192
192
|
}
|
|
193
193
|
/** Stop the periodic cleanup. Idempotent. */
|
|
194
194
|
stop() {
|
|
@@ -228,18 +228,19 @@ function encodeSet(...elements) {
|
|
|
228
228
|
}
|
|
229
229
|
function encodeInteger(value) {
|
|
230
230
|
let buf;
|
|
231
|
-
if (typeof value === "number")
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
231
|
+
if (typeof value === "number") {
|
|
232
|
+
if (value === 0) buf = Buffer.from([0]);
|
|
233
|
+
else {
|
|
234
|
+
const bytes = [];
|
|
235
|
+
let temp = value;
|
|
236
|
+
while (temp > 0) {
|
|
237
|
+
bytes.unshift(temp & 255);
|
|
238
|
+
temp >>= 8;
|
|
239
|
+
}
|
|
240
|
+
if (bytes[0] & 128) bytes.unshift(0);
|
|
241
|
+
buf = Buffer.from(bytes);
|
|
242
|
+
}
|
|
243
|
+
} else if (value.length > 0 && value[0] & 128) buf = Buffer.concat([Buffer.from([0]), value]);
|
|
243
244
|
else buf = value;
|
|
244
245
|
return encodeTlv(2, buf);
|
|
245
246
|
}
|
|
@@ -690,7 +691,7 @@ const bearerAuthRoute = (fastify) => {
|
|
|
690
691
|
//#endregion
|
|
691
692
|
//#region src/routes/auth/digest.ts
|
|
692
693
|
const makeNonce = () => crypto.randomBytes(16).toString("hex");
|
|
693
|
-
const algorithms = new Set([
|
|
694
|
+
const algorithms = /* @__PURE__ */ new Set([
|
|
694
695
|
"MD5",
|
|
695
696
|
"md5",
|
|
696
697
|
"SHA-256",
|
|
@@ -1374,7 +1375,7 @@ function generateSeededBytes$1(n, seed) {
|
|
|
1374
1375
|
for (let i = 0; i < n; i++) bytes[i] = Math.floor(random() * 256);
|
|
1375
1376
|
return bytes;
|
|
1376
1377
|
}
|
|
1377
|
-
const MAX_BYTES$3 =
|
|
1378
|
+
const MAX_BYTES$3 = 102400;
|
|
1378
1379
|
const bytesRoute = (fastify) => {
|
|
1379
1380
|
fastify.get("/bytes/:n", { schema: bytesSchema }, async (request, reply) => {
|
|
1380
1381
|
const n = Number.parseInt(request.params.n, 10);
|
|
@@ -1501,7 +1502,7 @@ const DEFAULT_CODE = 200;
|
|
|
1501
1502
|
const DEFAULT_DELAY = 2;
|
|
1502
1503
|
const MAX_DURATION = 10;
|
|
1503
1504
|
const MAX_DELAY = 10;
|
|
1504
|
-
const MAX_BYTES$2 =
|
|
1505
|
+
const MAX_BYTES$2 = 10485760;
|
|
1505
1506
|
const dripRoute = (fastify) => {
|
|
1506
1507
|
fastify.get("/drip", { schema: dripSchema }, async (request, reply) => {
|
|
1507
1508
|
/* v8 ignore next 2 -- @preserve */
|
|
@@ -1627,7 +1628,7 @@ const rangeSchema = {
|
|
|
1627
1628
|
}
|
|
1628
1629
|
}
|
|
1629
1630
|
};
|
|
1630
|
-
const MAX_BYTES$1 =
|
|
1631
|
+
const MAX_BYTES$1 = 102400;
|
|
1631
1632
|
function sleep(ms) {
|
|
1632
1633
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1633
1634
|
}
|
|
@@ -1808,7 +1809,7 @@ function generateSeededBytes(n, seed) {
|
|
|
1808
1809
|
for (let i = 0; i < n; i++) bytes[i] = Math.floor(random() * 256);
|
|
1809
1810
|
return bytes;
|
|
1810
1811
|
}
|
|
1811
|
-
const MAX_BYTES =
|
|
1812
|
+
const MAX_BYTES = 102400;
|
|
1812
1813
|
const DEFAULT_CHUNK_SIZE = 10240;
|
|
1813
1814
|
const streamBytesRoute = (fastify) => {
|
|
1814
1815
|
fastify.get("/stream-bytes/:n", { schema: streamBytesSchema }, async (request, reply) => {
|
|
@@ -2042,6 +2043,18 @@ const putRoute = (fastify) => {
|
|
|
2042
2043
|
}));
|
|
2043
2044
|
};
|
|
2044
2045
|
//#endregion
|
|
2046
|
+
//#region src/public-files.ts
|
|
2047
|
+
const defaultPublicPath$1 = join(process.cwd(), "public");
|
|
2048
|
+
const defaultReader = (file) => readFileSync(join(defaultPublicPath$1, file));
|
|
2049
|
+
let reader = defaultReader;
|
|
2050
|
+
/**
|
|
2051
|
+
* Read a file from the package `public/` directory, or from the active reader.
|
|
2052
|
+
*/
|
|
2053
|
+
async function readPublicFile(file) {
|
|
2054
|
+
const bytes = await reader(file);
|
|
2055
|
+
return Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes);
|
|
2056
|
+
}
|
|
2057
|
+
//#endregion
|
|
2045
2058
|
//#region src/routes/images/index.ts
|
|
2046
2059
|
const imageSchema = {
|
|
2047
2060
|
description: "Returns an image based on Accept header (supports jpeg, png, svg, webp)",
|
|
@@ -2095,8 +2108,19 @@ const webpSchema = {
|
|
|
2095
2108
|
format: "binary"
|
|
2096
2109
|
} }
|
|
2097
2110
|
};
|
|
2111
|
+
async function sendImage(reply, file, contentType) {
|
|
2112
|
+
try {
|
|
2113
|
+
const imageBuffer = await readPublicFile(file);
|
|
2114
|
+
reply.type(contentType);
|
|
2115
|
+
return imageBuffer;
|
|
2116
|
+
} catch (error) {
|
|
2117
|
+
/* v8 ignore next -- @preserve */
|
|
2118
|
+
reply.code(500);
|
|
2119
|
+
/* v8 ignore next -- @preserve */
|
|
2120
|
+
return { error: `${error}` };
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2098
2123
|
const imageRoutes = (fastify) => {
|
|
2099
|
-
const publicPath = join(process.cwd(), "public");
|
|
2100
2124
|
fastify.get("/image", { schema: imageSchema }, async (request, reply) => {
|
|
2101
2125
|
const accept = request.headers.accept || "";
|
|
2102
2126
|
let file = "logo.png";
|
|
@@ -2114,147 +2138,19 @@ const imageRoutes = (fastify) => {
|
|
|
2114
2138
|
file = "logo.png";
|
|
2115
2139
|
contentType = "image/png";
|
|
2116
2140
|
}
|
|
2117
|
-
|
|
2118
|
-
const imageBuffer = readFileSync(join(publicPath, file));
|
|
2119
|
-
reply.type(contentType);
|
|
2120
|
-
return imageBuffer;
|
|
2121
|
-
} catch (error) {
|
|
2122
|
-
/* v8 ignore next -- @preserve */
|
|
2123
|
-
reply.code(500);
|
|
2124
|
-
/* v8 ignore next -- @preserve */
|
|
2125
|
-
return { error: `${error}` };
|
|
2126
|
-
}
|
|
2141
|
+
return sendImage(reply, file, contentType);
|
|
2127
2142
|
});
|
|
2128
2143
|
fastify.get("/image/jpeg", { schema: jpegSchema }, async (_request, reply) => {
|
|
2129
|
-
|
|
2130
|
-
const imageBuffer = readFileSync(join(publicPath, "logo.jpg"));
|
|
2131
|
-
reply.type("image/jpeg");
|
|
2132
|
-
return imageBuffer;
|
|
2133
|
-
} catch (error) {
|
|
2134
|
-
/* v8 ignore next -- @preserve */
|
|
2135
|
-
reply.code(500);
|
|
2136
|
-
/* v8 ignore next -- @preserve */
|
|
2137
|
-
return { error: `${error}` };
|
|
2138
|
-
}
|
|
2144
|
+
return sendImage(reply, "logo.jpg", "image/jpeg");
|
|
2139
2145
|
});
|
|
2140
2146
|
fastify.get("/image/png", { schema: pngSchema }, async (_request, reply) => {
|
|
2141
|
-
|
|
2142
|
-
const imageBuffer = readFileSync(join(publicPath, "logo.png"));
|
|
2143
|
-
reply.type("image/png");
|
|
2144
|
-
return imageBuffer;
|
|
2145
|
-
} catch (error) {
|
|
2146
|
-
/* v8 ignore next -- @preserve */
|
|
2147
|
-
reply.code(500);
|
|
2148
|
-
/* v8 ignore next -- @preserve */
|
|
2149
|
-
return { error: `${error}` };
|
|
2150
|
-
}
|
|
2147
|
+
return sendImage(reply, "logo.png", "image/png");
|
|
2151
2148
|
});
|
|
2152
2149
|
fastify.get("/image/svg", { schema: svgSchema }, async (_request, reply) => {
|
|
2153
|
-
|
|
2154
|
-
const imageBuffer = readFileSync(join(publicPath, "logo.svg"));
|
|
2155
|
-
reply.type("image/svg+xml");
|
|
2156
|
-
return imageBuffer;
|
|
2157
|
-
} catch (error) {
|
|
2158
|
-
/* v8 ignore next -- @preserve */
|
|
2159
|
-
reply.code(500);
|
|
2160
|
-
/* v8 ignore next -- @preserve */
|
|
2161
|
-
return { error: `${error}` };
|
|
2162
|
-
}
|
|
2150
|
+
return sendImage(reply, "logo.svg", "image/svg+xml");
|
|
2163
2151
|
});
|
|
2164
2152
|
fastify.get("/image/webp", { schema: webpSchema }, async (_request, reply) => {
|
|
2165
|
-
|
|
2166
|
-
const imageBuffer = readFileSync(join(publicPath, "logo.webp"));
|
|
2167
|
-
reply.type("image/webp");
|
|
2168
|
-
return imageBuffer;
|
|
2169
|
-
} catch (error) {
|
|
2170
|
-
/* v8 ignore next -- @preserve */
|
|
2171
|
-
reply.code(500);
|
|
2172
|
-
/* v8 ignore next -- @preserve */
|
|
2173
|
-
return { error: `${error}` };
|
|
2174
|
-
}
|
|
2175
|
-
});
|
|
2176
|
-
};
|
|
2177
|
-
//#endregion
|
|
2178
|
-
//#region src/routes/index.ts
|
|
2179
|
-
const indexRoute = (fastify) => {
|
|
2180
|
-
fastify.get("/", { schema: { hide: true } }, async (_request, reply) => {
|
|
2181
|
-
await reply.type("text/html").send(`
|
|
2182
|
-
<!doctype html>
|
|
2183
|
-
<html>
|
|
2184
|
-
<head>
|
|
2185
|
-
<title>{ mockhttp }</title>
|
|
2186
|
-
<meta charset="utf-8" />
|
|
2187
|
-
<meta
|
|
2188
|
-
name="viewport"
|
|
2189
|
-
content="width=device-width, initial-scale=1" />
|
|
2190
|
-
<meta name="description" content="MockHttp - A powerful HTTP mock server and httpbin replacement for API testing. Built with Fastify, TypeScript, and Docker support." />
|
|
2191
|
-
<meta name="keywords" content="mock, http, httpbin, testing, api, fastify, docker, typescript, rest, mock-server, api-testing, http-testing, httpbin-alternative" />
|
|
2192
|
-
<meta property="og:title" content="MockHttp - HTTP Mock Server" />
|
|
2193
|
-
<meta property="og:description" content="A powerful HTTP mock server and httpbin replacement for API testing. Built with Fastify, TypeScript, and Docker support." />
|
|
2194
|
-
<meta property="og:type" content="website" />
|
|
2195
|
-
<meta property="og:url" content="https://mockhttp.org" />
|
|
2196
|
-
<meta property="og:image" content="https://mockhttp.org/logo.png" />
|
|
2197
|
-
<meta property="og:site_name" content="MockHttp" />
|
|
2198
|
-
<meta name="twitter:card" content="summary" />
|
|
2199
|
-
<meta name="twitter:title" content="MockHttp - HTTP Mock Server" />
|
|
2200
|
-
<meta name="twitter:description" content="A powerful HTTP mock server and httpbin replacement for API testing." />
|
|
2201
|
-
<meta name="twitter:image" content="https://mockhttp.org/logo.png" />
|
|
2202
|
-
<style>
|
|
2203
|
-
:root {
|
|
2204
|
-
--scalar-custom-header-height: 70px;
|
|
2205
|
-
}
|
|
2206
|
-
.custom-header {
|
|
2207
|
-
height: var(--scalar-custom-header-height);
|
|
2208
|
-
background-color: var(--scalar-background-1);
|
|
2209
|
-
box-shadow: inset 0 -1px 0 var(--scalar-border-color);
|
|
2210
|
-
color: var(--scalar-color-1);
|
|
2211
|
-
font-size: var(--scalar-font-size-2);
|
|
2212
|
-
padding: 0 18px;
|
|
2213
|
-
position: sticky;
|
|
2214
|
-
justify-content: space-between;
|
|
2215
|
-
top: 0;
|
|
2216
|
-
z-index: 100;
|
|
2217
|
-
}
|
|
2218
|
-
.custom-header,
|
|
2219
|
-
.custom-header nav {
|
|
2220
|
-
display: flex;
|
|
2221
|
-
align-items: center;
|
|
2222
|
-
gap: 18px;
|
|
2223
|
-
}
|
|
2224
|
-
|
|
2225
|
-
.custom-header img {
|
|
2226
|
-
height: var(--scalar-custom-header-height);
|
|
2227
|
-
object-fit: contain;
|
|
2228
|
-
}
|
|
2229
|
-
|
|
2230
|
-
.custom-header a:hover {
|
|
2231
|
-
color: var(--scalar-color-2);
|
|
2232
|
-
}
|
|
2233
|
-
|
|
2234
|
-
.github-corner {
|
|
2235
|
-
fill: var(--scalar-border-color) !important;
|
|
2236
|
-
}
|
|
2237
|
-
|
|
2238
|
-
</style>
|
|
2239
|
-
</head>
|
|
2240
|
-
<body>
|
|
2241
|
-
<header class="custom-header scalar-app">
|
|
2242
|
-
<a href="/"><img src="/logo.svg" alt="{ mockhttp }" /></a>
|
|
2243
|
-
<a href="https://github.com/jaredwray/mockhttp" class="github-corner" aria-label="View source on GitHub">
|
|
2244
|
-
<svg width="70" height="70" viewBox="0 0 250 250" style="color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true">
|
|
2245
|
-
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
|
|
2246
|
-
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
|
|
2247
|
-
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
|
|
2248
|
-
</header>
|
|
2249
|
-
|
|
2250
|
-
<script
|
|
2251
|
-
id="api-reference"
|
|
2252
|
-
data-url="/docs/json"><\/script>
|
|
2253
|
-
|
|
2254
|
-
<script src="/scalar/browser/standalone.js"><\/script>
|
|
2255
|
-
</body>
|
|
2256
|
-
</html>
|
|
2257
|
-
`);
|
|
2153
|
+
return sendImage(reply, "logo.webp", "image/webp");
|
|
2258
2154
|
});
|
|
2259
2155
|
};
|
|
2260
2156
|
//#endregion
|
|
@@ -2438,46 +2334,78 @@ const userAgentRoute = (fastify) => {
|
|
|
2438
2334
|
};
|
|
2439
2335
|
//#endregion
|
|
2440
2336
|
//#region src/routes/response-formats/index.ts
|
|
2441
|
-
const
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
response: { 200: {
|
|
2337
|
+
const templateIndexParams = {
|
|
2338
|
+
type: "object",
|
|
2339
|
+
properties: { index: {
|
|
2445
2340
|
type: "string",
|
|
2446
|
-
description: "
|
|
2341
|
+
description: "Optional 1-based template index for stable, repeatable output. Omit for a random template."
|
|
2447
2342
|
} }
|
|
2448
2343
|
};
|
|
2344
|
+
const templateNotFoundResponse = {
|
|
2345
|
+
type: "object",
|
|
2346
|
+
description: "The requested template index does not exist",
|
|
2347
|
+
properties: { error: { type: "string" } }
|
|
2348
|
+
};
|
|
2349
|
+
const plainSchema = {
|
|
2350
|
+
description: "Returns plain text content. A random template is selected unless a 1-based template index is provided (e.g. /plain/1) for stable output.",
|
|
2351
|
+
tags: ["Response Formats"],
|
|
2352
|
+
params: templateIndexParams,
|
|
2353
|
+
response: {
|
|
2354
|
+
200: {
|
|
2355
|
+
type: "string",
|
|
2356
|
+
description: "Plain text content"
|
|
2357
|
+
},
|
|
2358
|
+
404: templateNotFoundResponse
|
|
2359
|
+
}
|
|
2360
|
+
};
|
|
2449
2361
|
const textSchema = {
|
|
2450
|
-
description: "Returns random text
|
|
2362
|
+
description: "Returns text content. A random template is selected unless a 1-based template index is provided (e.g. /text/1) for stable output.",
|
|
2451
2363
|
tags: ["Response Formats"],
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2364
|
+
params: templateIndexParams,
|
|
2365
|
+
response: {
|
|
2366
|
+
200: {
|
|
2367
|
+
type: "string",
|
|
2368
|
+
description: "Text content"
|
|
2369
|
+
},
|
|
2370
|
+
404: templateNotFoundResponse
|
|
2371
|
+
}
|
|
2456
2372
|
};
|
|
2457
2373
|
const htmlSchema = {
|
|
2458
|
-
description: "Returns random
|
|
2374
|
+
description: "Returns HTML content. A random template is selected unless a 1-based template index is provided (e.g. /html/1) for stable output.",
|
|
2459
2375
|
tags: ["Response Formats"],
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2376
|
+
params: templateIndexParams,
|
|
2377
|
+
response: {
|
|
2378
|
+
200: {
|
|
2379
|
+
type: "string",
|
|
2380
|
+
description: "HTML content"
|
|
2381
|
+
},
|
|
2382
|
+
404: templateNotFoundResponse
|
|
2383
|
+
}
|
|
2464
2384
|
};
|
|
2465
2385
|
const xmlSchema = {
|
|
2466
|
-
description: "Returns random
|
|
2386
|
+
description: "Returns XML content. A random template is selected unless a 1-based template index is provided (e.g. /xml/1) for stable output.",
|
|
2467
2387
|
tags: ["Response Formats"],
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2388
|
+
params: templateIndexParams,
|
|
2389
|
+
response: {
|
|
2390
|
+
200: {
|
|
2391
|
+
type: "string",
|
|
2392
|
+
description: "XML content"
|
|
2393
|
+
},
|
|
2394
|
+
404: templateNotFoundResponse
|
|
2395
|
+
}
|
|
2472
2396
|
};
|
|
2473
2397
|
const jsonSchema = {
|
|
2474
|
-
description: "Returns random
|
|
2398
|
+
description: "Returns JSON content. A random template is selected unless a 1-based template index is provided (e.g. /json/1) for stable output.",
|
|
2475
2399
|
tags: ["Response Formats"],
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2400
|
+
params: templateIndexParams,
|
|
2401
|
+
response: {
|
|
2402
|
+
200: {
|
|
2403
|
+
type: "object",
|
|
2404
|
+
description: "JSON content",
|
|
2405
|
+
additionalProperties: true
|
|
2406
|
+
},
|
|
2407
|
+
404: templateNotFoundResponse
|
|
2408
|
+
}
|
|
2481
2409
|
};
|
|
2482
2410
|
const denySchema = {
|
|
2483
2411
|
description: "Returns page denied by robots.txt rules",
|
|
@@ -2613,7 +2541,7 @@ const randomXmlContent = [
|
|
|
2613
2541
|
`<?xml version="1.0" encoding="UTF-8"?>
|
|
2614
2542
|
<root>
|
|
2615
2543
|
<message>Hello from MockHTTP</message>
|
|
2616
|
-
<timestamp
|
|
2544
|
+
<timestamp>2024-01-15T10:30:00.000Z</timestamp>
|
|
2617
2545
|
<status>success</status>
|
|
2618
2546
|
</root>`,
|
|
2619
2547
|
`<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -2656,19 +2584,19 @@ const randomXmlContent = [
|
|
|
2656
2584
|
<title>First Article</title>
|
|
2657
2585
|
<link>http://example.com/article1</link>
|
|
2658
2586
|
<description>This is the first article in our feed</description>
|
|
2659
|
-
<pubDate
|
|
2587
|
+
<pubDate>Mon, 15 Jan 2024 10:30:00 GMT</pubDate>
|
|
2660
2588
|
</item>
|
|
2661
2589
|
</channel>
|
|
2662
2590
|
</rss>`
|
|
2663
2591
|
];
|
|
2664
2592
|
const randomJsonContent = [
|
|
2665
|
-
|
|
2593
|
+
{
|
|
2666
2594
|
message: "Hello from MockHTTP",
|
|
2667
|
-
timestamp:
|
|
2595
|
+
timestamp: "2024-01-15T10:30:00.000Z",
|
|
2668
2596
|
status: "success",
|
|
2669
2597
|
code: 200
|
|
2670
|
-
}
|
|
2671
|
-
|
|
2598
|
+
},
|
|
2599
|
+
{
|
|
2672
2600
|
user: {
|
|
2673
2601
|
id: 1,
|
|
2674
2602
|
name: "John Doe",
|
|
@@ -2681,8 +2609,8 @@ const randomJsonContent = [
|
|
|
2681
2609
|
"write",
|
|
2682
2610
|
"delete"
|
|
2683
2611
|
]
|
|
2684
|
-
}
|
|
2685
|
-
|
|
2612
|
+
},
|
|
2613
|
+
{
|
|
2686
2614
|
products: [{
|
|
2687
2615
|
id: 101,
|
|
2688
2616
|
name: "Laptop",
|
|
@@ -2696,8 +2624,8 @@ const randomJsonContent = [
|
|
|
2696
2624
|
}],
|
|
2697
2625
|
total: 2,
|
|
2698
2626
|
page: 1
|
|
2699
|
-
}
|
|
2700
|
-
|
|
2627
|
+
},
|
|
2628
|
+
{ config: {
|
|
2701
2629
|
theme: "dark",
|
|
2702
2630
|
language: "en",
|
|
2703
2631
|
notifications: {
|
|
@@ -2709,8 +2637,8 @@ const randomJsonContent = [
|
|
|
2709
2637
|
profile: "public",
|
|
2710
2638
|
activity: "friends"
|
|
2711
2639
|
}
|
|
2712
|
-
} }
|
|
2713
|
-
|
|
2640
|
+
} },
|
|
2641
|
+
{ metrics: {
|
|
2714
2642
|
cpu: 45.2,
|
|
2715
2643
|
memory: 78.5,
|
|
2716
2644
|
disk: 62.3,
|
|
@@ -2733,60 +2661,71 @@ const randomJsonContent = [
|
|
|
2733
2661
|
status: "warning"
|
|
2734
2662
|
}
|
|
2735
2663
|
]
|
|
2736
|
-
} }
|
|
2664
|
+
} }
|
|
2737
2665
|
];
|
|
2666
|
+
const resolveTemplateIndex = (index, length) => {
|
|
2667
|
+
if (index === void 0) return Math.floor(Math.random() * length);
|
|
2668
|
+
const value = Number(index);
|
|
2669
|
+
if (!Number.isInteger(value) || value < 1 || value > length) return -1;
|
|
2670
|
+
return value - 1;
|
|
2671
|
+
};
|
|
2672
|
+
const templateNotFound = (reply, length) => reply.code(404).send({ error: `Template index must be between 1 and ${length}` });
|
|
2738
2673
|
const responseFormatRoutes = (fastify) => {
|
|
2739
|
-
const plainHandler = async (
|
|
2740
|
-
const
|
|
2674
|
+
const plainHandler = async (request, reply) => {
|
|
2675
|
+
const index = resolveTemplateIndex(request.params.index, randomTexts.length);
|
|
2676
|
+
if (index === -1) return templateNotFound(reply, randomTexts.length);
|
|
2741
2677
|
reply.type("text/plain");
|
|
2742
|
-
return
|
|
2678
|
+
return randomTexts[index];
|
|
2743
2679
|
};
|
|
2744
|
-
fastify.get("/plain", { schema: plainSchema }, plainHandler);
|
|
2745
|
-
fastify.post("/plain", { schema: plainSchema }, plainHandler);
|
|
2746
|
-
fastify.put("/plain", { schema: plainSchema }, plainHandler);
|
|
2747
|
-
fastify.patch("/plain", { schema: plainSchema }, plainHandler);
|
|
2748
|
-
fastify.delete("/plain", { schema: plainSchema }, plainHandler);
|
|
2749
|
-
const textHandler = async (
|
|
2750
|
-
const
|
|
2680
|
+
fastify.get("/plain/:index?", { schema: plainSchema }, plainHandler);
|
|
2681
|
+
fastify.post("/plain/:index?", { schema: plainSchema }, plainHandler);
|
|
2682
|
+
fastify.put("/plain/:index?", { schema: plainSchema }, plainHandler);
|
|
2683
|
+
fastify.patch("/plain/:index?", { schema: plainSchema }, plainHandler);
|
|
2684
|
+
fastify.delete("/plain/:index?", { schema: plainSchema }, plainHandler);
|
|
2685
|
+
const textHandler = async (request, reply) => {
|
|
2686
|
+
const index = resolveTemplateIndex(request.params.index, randomTexts.length);
|
|
2687
|
+
if (index === -1) return templateNotFound(reply, randomTexts.length);
|
|
2751
2688
|
reply.type("text/plain");
|
|
2752
|
-
return
|
|
2689
|
+
return randomTexts[index];
|
|
2753
2690
|
};
|
|
2754
|
-
fastify.get("/text", { schema: textSchema }, textHandler);
|
|
2755
|
-
fastify.post("/text", { schema: textSchema }, textHandler);
|
|
2756
|
-
fastify.put("/text", { schema: textSchema }, textHandler);
|
|
2757
|
-
fastify.patch("/text", { schema: textSchema }, textHandler);
|
|
2758
|
-
fastify.delete("/text", { schema: textSchema }, textHandler);
|
|
2759
|
-
const htmlHandler = async (
|
|
2760
|
-
const
|
|
2691
|
+
fastify.get("/text/:index?", { schema: textSchema }, textHandler);
|
|
2692
|
+
fastify.post("/text/:index?", { schema: textSchema }, textHandler);
|
|
2693
|
+
fastify.put("/text/:index?", { schema: textSchema }, textHandler);
|
|
2694
|
+
fastify.patch("/text/:index?", { schema: textSchema }, textHandler);
|
|
2695
|
+
fastify.delete("/text/:index?", { schema: textSchema }, textHandler);
|
|
2696
|
+
const htmlHandler = async (request, reply) => {
|
|
2697
|
+
const index = resolveTemplateIndex(request.params.index, randomHtmlContent.length);
|
|
2698
|
+
if (index === -1) return templateNotFound(reply, randomHtmlContent.length);
|
|
2761
2699
|
reply.type("text/html");
|
|
2762
|
-
return
|
|
2700
|
+
return randomHtmlContent[index];
|
|
2763
2701
|
};
|
|
2764
|
-
fastify.get("/html", { schema: htmlSchema }, htmlHandler);
|
|
2765
|
-
fastify.post("/html", { schema: htmlSchema }, htmlHandler);
|
|
2766
|
-
fastify.put("/html", { schema: htmlSchema }, htmlHandler);
|
|
2767
|
-
fastify.patch("/html", { schema: htmlSchema }, htmlHandler);
|
|
2768
|
-
fastify.delete("/html", { schema: htmlSchema }, htmlHandler);
|
|
2769
|
-
const xmlHandler = async (
|
|
2770
|
-
const
|
|
2702
|
+
fastify.get("/html/:index?", { schema: htmlSchema }, htmlHandler);
|
|
2703
|
+
fastify.post("/html/:index?", { schema: htmlSchema }, htmlHandler);
|
|
2704
|
+
fastify.put("/html/:index?", { schema: htmlSchema }, htmlHandler);
|
|
2705
|
+
fastify.patch("/html/:index?", { schema: htmlSchema }, htmlHandler);
|
|
2706
|
+
fastify.delete("/html/:index?", { schema: htmlSchema }, htmlHandler);
|
|
2707
|
+
const xmlHandler = async (request, reply) => {
|
|
2708
|
+
const index = resolveTemplateIndex(request.params.index, randomXmlContent.length);
|
|
2709
|
+
if (index === -1) return templateNotFound(reply, randomXmlContent.length);
|
|
2771
2710
|
reply.type("application/xml");
|
|
2772
|
-
return
|
|
2711
|
+
return randomXmlContent[index];
|
|
2773
2712
|
};
|
|
2774
|
-
fastify.get("/xml", { schema: xmlSchema }, xmlHandler);
|
|
2775
|
-
fastify.post("/xml", { schema: xmlSchema }, xmlHandler);
|
|
2776
|
-
fastify.put("/xml", { schema: xmlSchema }, xmlHandler);
|
|
2777
|
-
fastify.patch("/xml", { schema: xmlSchema }, xmlHandler);
|
|
2778
|
-
fastify.delete("/xml", { schema: xmlSchema }, xmlHandler);
|
|
2779
|
-
const jsonHandler = async (
|
|
2780
|
-
const
|
|
2781
|
-
|
|
2713
|
+
fastify.get("/xml/:index?", { schema: xmlSchema }, xmlHandler);
|
|
2714
|
+
fastify.post("/xml/:index?", { schema: xmlSchema }, xmlHandler);
|
|
2715
|
+
fastify.put("/xml/:index?", { schema: xmlSchema }, xmlHandler);
|
|
2716
|
+
fastify.patch("/xml/:index?", { schema: xmlSchema }, xmlHandler);
|
|
2717
|
+
fastify.delete("/xml/:index?", { schema: xmlSchema }, xmlHandler);
|
|
2718
|
+
const jsonHandler = async (request, reply) => {
|
|
2719
|
+
const index = resolveTemplateIndex(request.params.index, randomJsonContent.length);
|
|
2720
|
+
if (index === -1) return templateNotFound(reply, randomJsonContent.length);
|
|
2782
2721
|
reply.type("application/json");
|
|
2783
|
-
return
|
|
2722
|
+
return structuredClone(randomJsonContent[index]);
|
|
2784
2723
|
};
|
|
2785
|
-
fastify.get("/json", { schema: jsonSchema }, jsonHandler);
|
|
2786
|
-
fastify.post("/json", { schema: jsonSchema }, jsonHandler);
|
|
2787
|
-
fastify.put("/json", { schema: jsonSchema }, jsonHandler);
|
|
2788
|
-
fastify.patch("/json", { schema: jsonSchema }, jsonHandler);
|
|
2789
|
-
fastify.delete("/json", { schema: jsonSchema }, jsonHandler);
|
|
2724
|
+
fastify.get("/json/:index?", { schema: jsonSchema }, jsonHandler);
|
|
2725
|
+
fastify.post("/json/:index?", { schema: jsonSchema }, jsonHandler);
|
|
2726
|
+
fastify.put("/json/:index?", { schema: jsonSchema }, jsonHandler);
|
|
2727
|
+
fastify.patch("/json/:index?", { schema: jsonSchema }, jsonHandler);
|
|
2728
|
+
fastify.delete("/json/:index?", { schema: jsonSchema }, jsonHandler);
|
|
2790
2729
|
const denyHandler = async (_request, reply) => {
|
|
2791
2730
|
const denyMessages = [
|
|
2792
2731
|
`<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
|
|
@@ -2869,7 +2808,8 @@ const responseFormatRoutes = (fastify) => {
|
|
|
2869
2808
|
...data,
|
|
2870
2809
|
compressedSize: compressed.length
|
|
2871
2810
|
};
|
|
2872
|
-
const
|
|
2811
|
+
const updatedJsonString = JSON.stringify(updatedData);
|
|
2812
|
+
const updatedCompressed = gzipSync(updatedJsonString);
|
|
2873
2813
|
reply.header("Content-Encoding", "gzip");
|
|
2874
2814
|
reply.header("Content-Type", "application/json");
|
|
2875
2815
|
reply.type("application/octet-stream");
|
|
@@ -2925,7 +2865,8 @@ const responseFormatRoutes = (fastify) => {
|
|
|
2925
2865
|
...data,
|
|
2926
2866
|
compressedSize: compressed.length
|
|
2927
2867
|
};
|
|
2928
|
-
const
|
|
2868
|
+
const updatedJsonString = JSON.stringify(updatedData);
|
|
2869
|
+
const updatedCompressed = deflateSync(updatedJsonString);
|
|
2929
2870
|
reply.header("Content-Encoding", "deflate");
|
|
2930
2871
|
reply.header("Content-Type", "application/json");
|
|
2931
2872
|
reply.type("application/octet-stream");
|
|
@@ -2986,7 +2927,8 @@ const responseFormatRoutes = (fastify) => {
|
|
|
2986
2927
|
...data,
|
|
2987
2928
|
compressedSize: compressed.length
|
|
2988
2929
|
};
|
|
2989
|
-
const
|
|
2930
|
+
const updatedJsonString = JSON.stringify(updatedData);
|
|
2931
|
+
const updatedCompressed = brotliCompressSync(updatedJsonString);
|
|
2990
2932
|
reply.header("Content-Encoding", "br");
|
|
2991
2933
|
reply.header("Content-Type", "application/json");
|
|
2992
2934
|
reply.type("application/octet-stream");
|
|
@@ -3130,29 +3072,6 @@ const responseHeadersRoutes = (fastify) => {
|
|
|
3130
3072
|
});
|
|
3131
3073
|
};
|
|
3132
3074
|
//#endregion
|
|
3133
|
-
//#region src/routes/sitemap.ts
|
|
3134
|
-
const sitemapRoute = (fastify) => {
|
|
3135
|
-
fastify.get("/sitemap.xml", { schema: { hide: true } }, async (_request, reply) => {
|
|
3136
|
-
try {
|
|
3137
|
-
const host = _request.headers.host ?? "mockhttp.org";
|
|
3138
|
-
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
3139
|
-
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
3140
|
-
<url>
|
|
3141
|
-
<loc>${_request.headers["x-forwarded-proto"]?.includes("https") ? "https" : "http"}://${host}/</loc>
|
|
3142
|
-
<changefreq>monthly</changefreq>
|
|
3143
|
-
<priority>1.0</priority>
|
|
3144
|
-
</url>
|
|
3145
|
-
</urlset>`;
|
|
3146
|
-
await reply.type("text/xml").send(xml);
|
|
3147
|
-
} catch (error) {
|
|
3148
|
-
/* v8 ignore next -- @preserve */
|
|
3149
|
-
fastify.log.error(error);
|
|
3150
|
-
/* v8 ignore next -- @preserve */
|
|
3151
|
-
await reply.status(500).send({ error: "Internal Server Error" });
|
|
3152
|
-
}
|
|
3153
|
-
});
|
|
3154
|
-
};
|
|
3155
|
-
//#endregion
|
|
3156
3075
|
//#region src/routes/status-codes/index.ts
|
|
3157
3076
|
const statusCodes = [
|
|
3158
3077
|
{
|
|
@@ -3435,47 +3354,30 @@ const statusCodeRoute = (fastify) => {
|
|
|
3435
3354
|
fastify.patch("/status/:code?", { schema: statusSchema }, handler);
|
|
3436
3355
|
fastify.delete("/status/:code?", { schema: statusSchema }, handler);
|
|
3437
3356
|
};
|
|
3438
|
-
const fastifySwaggerConfig = { openapi: {
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
description: `
|
|
3357
|
+
const fastifySwaggerConfig = { openapi: { info: {
|
|
3358
|
+
title: "Mock HTTP API",
|
|
3359
|
+
description: `
|
|
3442
3360
|
A simple HTTP server that can be used to mock HTTP responses for testing purposes. Inspired by [httpbin](https://httpbin.org/) and built using \`nodejs\` and \`fastify\` with the idea of running it via https://mockhttp.org, via docker \`jaredwray/mockhttp\`, or nodejs \`npm install @jaredwray/mockhttp\`.
|
|
3443
3361
|
|
|
3444
3362
|
* [GitHub Repository](https://github.com/jaredwray/mockhttp)
|
|
3445
3363
|
* [Docker Image](https://hub.docker.com/r/jaredwray/mockhttp)
|
|
3446
3364
|
* [NPM Package](https://www.npmjs.com/package/@jaredwray/mockhttp)
|
|
3447
3365
|
|
|
3448
|
-
# About mockhttp.org
|
|
3366
|
+
# About mockhttp.org
|
|
3449
3367
|
|
|
3450
|
-
[mockhttp.org](https://mockhttp.org) is a free
|
|
3368
|
+
[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.
|
|
3451
3369
|
`,
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
},
|
|
3464
|
-
uiHooks: {
|
|
3465
|
-
/* v8 ignore next -- @preserve */
|
|
3466
|
-
onRequest(_request, _reply, next) {
|
|
3467
|
-
next();
|
|
3468
|
-
},
|
|
3469
|
-
/* v8 ignore next -- @preserve */
|
|
3470
|
-
preHandler(_request, _reply, next) {
|
|
3471
|
-
next();
|
|
3472
|
-
}
|
|
3473
|
-
},
|
|
3474
|
-
staticCSP: true,
|
|
3475
|
-
/* v8 ignore next -- @preserve */
|
|
3476
|
-
transformSpecification: (swaggerObject, _request, _reply) => swaggerObject,
|
|
3477
|
-
transformSpecificationClone: true
|
|
3478
|
-
});
|
|
3370
|
+
version: "2.0.0"
|
|
3371
|
+
} } };
|
|
3372
|
+
const withLocalServer = (spec) => {
|
|
3373
|
+
spec.servers = [{
|
|
3374
|
+
url: "",
|
|
3375
|
+
description: "This instance"
|
|
3376
|
+
}];
|
|
3377
|
+
return spec;
|
|
3378
|
+
};
|
|
3379
|
+
const registerOpenApiJson = async (fastify) => {
|
|
3380
|
+
fastify.get("/openapi.json", { schema: { hide: true } }, async () => withLocalServer(fastify.swagger()));
|
|
3479
3381
|
};
|
|
3480
3382
|
//#endregion
|
|
3481
3383
|
//#region src/tap-manager.ts
|
|
@@ -3578,13 +3480,29 @@ var TapManager = class {
|
|
|
3578
3480
|
};
|
|
3579
3481
|
//#endregion
|
|
3580
3482
|
//#region src/mock-http.ts
|
|
3483
|
+
function resolvePackageRoot(metaUrl) {
|
|
3484
|
+
if (!metaUrl) return process.cwd();
|
|
3485
|
+
return path.resolve(path.dirname(fileURLToPath(metaUrl)), "..");
|
|
3486
|
+
}
|
|
3487
|
+
const packageRoot = resolvePackageRoot(import.meta.url);
|
|
3488
|
+
const defaultSiteDistPath = path.join(packageRoot, "site", "dist");
|
|
3489
|
+
const defaultPublicPath = path.join(packageRoot, "public");
|
|
3490
|
+
const requestOrigin = (request) => {
|
|
3491
|
+
const host = request.headers.host || "mockhttp.org";
|
|
3492
|
+
const forwarded = request.headers["x-forwarded-proto"];
|
|
3493
|
+
return `${((Array.isArray(forwarded) ? forwarded[0] : forwarded) ?? request.protocol).includes("https") ? "https" : "http"}://${host}`;
|
|
3494
|
+
};
|
|
3581
3495
|
var MockHttp = class extends Hookified {
|
|
3582
3496
|
_port = 3e3;
|
|
3583
3497
|
_host = "0.0.0.0";
|
|
3584
3498
|
_autoDetectPort = true;
|
|
3585
3499
|
_helmet = true;
|
|
3500
|
+
_staticFiles = true;
|
|
3586
3501
|
_apiDocs = true;
|
|
3502
|
+
_siteDistPath = defaultSiteDistPath;
|
|
3587
3503
|
_logging = true;
|
|
3504
|
+
_pluginTimeout;
|
|
3505
|
+
_startBins = true;
|
|
3588
3506
|
_httpBin = {
|
|
3589
3507
|
httpMethods: true,
|
|
3590
3508
|
redirects: true,
|
|
@@ -3608,24 +3526,33 @@ var MockHttp = class extends Hookified {
|
|
|
3608
3526
|
_http1 = true;
|
|
3609
3527
|
_https;
|
|
3610
3528
|
_httpsCredentials;
|
|
3611
|
-
_server
|
|
3529
|
+
_server;
|
|
3612
3530
|
_taps = new TapManager();
|
|
3613
3531
|
_bins = new BinManager();
|
|
3614
3532
|
constructor(options) {
|
|
3615
3533
|
super(options?.hookOptions);
|
|
3616
3534
|
if (options?.port) this._port = options.port;
|
|
3617
3535
|
if (options?.host) this._host = options.host;
|
|
3536
|
+
if (options?.autoDetectPort !== void 0) this._autoDetectPort = options.autoDetectPort;
|
|
3618
3537
|
if (options?.helmet !== void 0) this._helmet = options.helmet;
|
|
3538
|
+
if (options?.staticFiles !== void 0) this._staticFiles = options.staticFiles;
|
|
3619
3539
|
if (options?.apiDocs !== void 0) this._apiDocs = options.apiDocs;
|
|
3540
|
+
if (options?.siteDistPath !== void 0) this._siteDistPath = path.resolve(options.siteDistPath);
|
|
3620
3541
|
if (options?.httpBin !== void 0) this._httpBin = options.httpBin;
|
|
3621
|
-
if (options?.rateLimit !== void 0)
|
|
3622
|
-
|
|
3542
|
+
if (options?.rateLimit !== void 0) {
|
|
3543
|
+
if (options.rateLimit === false) this._rateLimit = void 0;
|
|
3544
|
+
else this._rateLimit = options.rateLimit;
|
|
3545
|
+
}
|
|
3623
3546
|
if (options?.logging !== void 0) this._logging = options.logging;
|
|
3547
|
+
if (options?.pluginTimeout !== void 0) this._pluginTimeout = options.pluginTimeout;
|
|
3548
|
+
if (options?.startBins !== void 0) this._startBins = options.startBins;
|
|
3624
3549
|
if (options?.http2 !== void 0) this._http2 = options.http2;
|
|
3625
3550
|
if (options?.http1 !== void 0) this._http1 = options.http1;
|
|
3626
|
-
if (options?.https !== void 0)
|
|
3627
|
-
|
|
3628
|
-
|
|
3551
|
+
if (options?.https !== void 0) {
|
|
3552
|
+
if (options.https === true) this._https = { autoGenerate: true };
|
|
3553
|
+
else if (options.https === false) this._https = void 0;
|
|
3554
|
+
else this._https = options.https;
|
|
3555
|
+
}
|
|
3629
3556
|
}
|
|
3630
3557
|
/**
|
|
3631
3558
|
* The port to listen on. If not provided, defaults to 3000 and detects the next available port if in use.
|
|
@@ -3684,20 +3611,48 @@ var MockHttp = class extends Hookified {
|
|
|
3684
3611
|
this._helmet = helmet;
|
|
3685
3612
|
}
|
|
3686
3613
|
/**
|
|
3687
|
-
* Whether to
|
|
3614
|
+
* Whether to serve files from the package `public/` directory. Defaults to true.
|
|
3615
|
+
* @default true
|
|
3616
|
+
*/
|
|
3617
|
+
get staticFiles() {
|
|
3618
|
+
return this._staticFiles;
|
|
3619
|
+
}
|
|
3620
|
+
/**
|
|
3621
|
+
* Whether to serve files from the package `public/` directory. Defaults to true.
|
|
3622
|
+
* @default true
|
|
3623
|
+
*/
|
|
3624
|
+
set staticFiles(staticFiles) {
|
|
3625
|
+
this._staticFiles = staticFiles;
|
|
3626
|
+
}
|
|
3627
|
+
/**
|
|
3628
|
+
* Whether to serve the Docula documentation site and OpenAPI spec. Defaults to true.
|
|
3688
3629
|
* @default true
|
|
3689
3630
|
*/
|
|
3690
3631
|
get apiDocs() {
|
|
3691
3632
|
return this._apiDocs;
|
|
3692
3633
|
}
|
|
3693
3634
|
/**
|
|
3694
|
-
* Whether to
|
|
3635
|
+
* Whether to serve the Docula documentation site and OpenAPI spec. Defaults to true.
|
|
3695
3636
|
* @default true
|
|
3696
3637
|
*/
|
|
3697
3638
|
set apiDocs(apiDocs) {
|
|
3698
3639
|
this._apiDocs = apiDocs;
|
|
3699
3640
|
}
|
|
3700
3641
|
/**
|
|
3642
|
+
* Path to the built Docula site served when `apiDocs` is enabled.
|
|
3643
|
+
* @default the package `site/dist` directory
|
|
3644
|
+
*/
|
|
3645
|
+
get siteDistPath() {
|
|
3646
|
+
return this._siteDistPath;
|
|
3647
|
+
}
|
|
3648
|
+
/**
|
|
3649
|
+
* Path to the built Docula site served when `apiDocs` is enabled.
|
|
3650
|
+
* @default the package `site/dist` directory
|
|
3651
|
+
*/
|
|
3652
|
+
set siteDistPath(siteDistPath) {
|
|
3653
|
+
this._siteDistPath = path.resolve(siteDistPath);
|
|
3654
|
+
}
|
|
3655
|
+
/**
|
|
3701
3656
|
* Whether to enable logging. Defaults to true.
|
|
3702
3657
|
* @default true
|
|
3703
3658
|
*/
|
|
@@ -3712,6 +3667,32 @@ var MockHttp = class extends Hookified {
|
|
|
3712
3667
|
this._logging = logging;
|
|
3713
3668
|
}
|
|
3714
3669
|
/**
|
|
3670
|
+
* Fastify plugin boot timeout in milliseconds. `undefined` uses Fastify's default.
|
|
3671
|
+
*/
|
|
3672
|
+
get pluginTimeout() {
|
|
3673
|
+
return this._pluginTimeout;
|
|
3674
|
+
}
|
|
3675
|
+
/**
|
|
3676
|
+
* Fastify plugin boot timeout in milliseconds. `undefined` uses Fastify's default.
|
|
3677
|
+
*/
|
|
3678
|
+
set pluginTimeout(pluginTimeout) {
|
|
3679
|
+
this._pluginTimeout = pluginTimeout;
|
|
3680
|
+
}
|
|
3681
|
+
/**
|
|
3682
|
+
* Whether to start the request-bin cleanup timer during `initialize()`.
|
|
3683
|
+
* @default true
|
|
3684
|
+
*/
|
|
3685
|
+
get startBins() {
|
|
3686
|
+
return this._startBins;
|
|
3687
|
+
}
|
|
3688
|
+
/**
|
|
3689
|
+
* Whether to start the request-bin cleanup timer during `initialize()`.
|
|
3690
|
+
* @default true
|
|
3691
|
+
*/
|
|
3692
|
+
set startBins(startBins) {
|
|
3693
|
+
this._startBins = startBins;
|
|
3694
|
+
}
|
|
3695
|
+
/**
|
|
3715
3696
|
* HTTPS configuration. Set to true to auto-generate a self-signed certificate,
|
|
3716
3697
|
* or provide an HttpsOptions object with cert/key or auto-generation options.
|
|
3717
3698
|
*/
|
|
@@ -3795,6 +3776,7 @@ var MockHttp = class extends Hookified {
|
|
|
3795
3776
|
* The Fastify server instance.
|
|
3796
3777
|
*/
|
|
3797
3778
|
get server() {
|
|
3779
|
+
this._server ??= Fastify();
|
|
3798
3780
|
return this._server;
|
|
3799
3781
|
}
|
|
3800
3782
|
/**
|
|
@@ -3828,15 +3810,17 @@ var MockHttp = class extends Hookified {
|
|
|
3828
3810
|
this._bins = bins;
|
|
3829
3811
|
}
|
|
3830
3812
|
/**
|
|
3831
|
-
*
|
|
3813
|
+
* Register plugins and routes without listening. Use `inject()` against
|
|
3814
|
+
* `server`, or call `start()` to bind a port.
|
|
3832
3815
|
*/
|
|
3833
|
-
async
|
|
3816
|
+
async initialize() {
|
|
3834
3817
|
this._httpsCredentials = void 0;
|
|
3835
3818
|
if (this._https) this._httpsCredentials = await this.resolveHttpsCredentials(this._https);
|
|
3836
3819
|
try {
|
|
3837
3820
|
/* v8 ignore next -- @preserve */
|
|
3838
|
-
if (this._server) await this._server.close();
|
|
3821
|
+
if (this._server?.server.listening) await this._server.close();
|
|
3839
3822
|
const fastifyOptions = { ...getFastifyConfig(this._logging) };
|
|
3823
|
+
if (this._pluginTimeout !== void 0) fastifyOptions.pluginTimeout = this._pluginTimeout;
|
|
3840
3824
|
if (this._http2) fastifyOptions.http2 = true;
|
|
3841
3825
|
if (this._httpsCredentials) {
|
|
3842
3826
|
const httpsOptions = {
|
|
@@ -3856,22 +3840,14 @@ var MockHttp = class extends Hookified {
|
|
|
3856
3840
|
return reply.send(response);
|
|
3857
3841
|
}
|
|
3858
3842
|
});
|
|
3859
|
-
await this.
|
|
3860
|
-
root:
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
await this.server.register(fastifyStatic, {
|
|
3864
|
-
root: path.resolve("./public"),
|
|
3865
|
-
decorateReply: false
|
|
3843
|
+
if (this._staticFiles) await this.server.register(fastifyStatic, {
|
|
3844
|
+
root: defaultPublicPath,
|
|
3845
|
+
wildcard: false,
|
|
3846
|
+
index: false
|
|
3866
3847
|
});
|
|
3867
|
-
await this._server.register(sitemapRoute);
|
|
3868
3848
|
if (this._helmet) await this._server.register(fastifyHelmet, { contentSecurityPolicy: { directives: {
|
|
3869
3849
|
defaultSrc: ["'self'"],
|
|
3870
|
-
scriptSrc: [
|
|
3871
|
-
"'self'",
|
|
3872
|
-
"'unsafe-inline'",
|
|
3873
|
-
"'wasm-unsafe-eval'"
|
|
3874
|
-
],
|
|
3850
|
+
scriptSrc: ["'self'", "'unsafe-inline'"],
|
|
3875
3851
|
styleSrc: ["'self'", "'unsafe-inline'"],
|
|
3876
3852
|
imgSrc: [
|
|
3877
3853
|
"'self'",
|
|
@@ -3879,13 +3855,13 @@ var MockHttp = class extends Hookified {
|
|
|
3879
3855
|
"https:"
|
|
3880
3856
|
],
|
|
3881
3857
|
fontSrc: ["'self'", "data:"],
|
|
3882
|
-
connectSrc: ["'self'"],
|
|
3858
|
+
connectSrc: ["'self'", "https:"],
|
|
3883
3859
|
frameSrc: ["'self'"],
|
|
3884
3860
|
objectSrc: ["'none'"],
|
|
3885
3861
|
upgradeInsecureRequests: []
|
|
3886
3862
|
} } });
|
|
3887
3863
|
if (this._rateLimit) await this._server.register(fastifyRateLimit, this._rateLimit);
|
|
3888
|
-
if (this._apiDocs) await this.
|
|
3864
|
+
if (this._apiDocs) await this.registerSwagger();
|
|
3889
3865
|
const { httpMethods, redirects, requestInspection, responseInspection, responseFormats, statusCodes, cookies, anything, auth, images, dynamicData, bins } = this._httpBin;
|
|
3890
3866
|
if (httpMethods) await this.registerHttpMethods();
|
|
3891
3867
|
if (statusCodes) await this.registerStatusCodeRoutes();
|
|
@@ -3900,20 +3876,32 @@ var MockHttp = class extends Hookified {
|
|
|
3900
3876
|
if (dynamicData) await this.registerDynamicDataRoutes();
|
|
3901
3877
|
if (bins) {
|
|
3902
3878
|
await this.registerBinRoutes();
|
|
3903
|
-
this._bins.start();
|
|
3879
|
+
if (this._startBins) this._bins.start();
|
|
3904
3880
|
}
|
|
3881
|
+
if (this._apiDocs) await this.registerSite();
|
|
3882
|
+
} catch (error) {
|
|
3883
|
+
/* v8 ignore next -- @preserve */
|
|
3884
|
+
this.server.log.error(error);
|
|
3885
|
+
}
|
|
3886
|
+
}
|
|
3887
|
+
/**
|
|
3888
|
+
* Start the Fastify server. If the server is already running, it will be closed and restarted.
|
|
3889
|
+
*/
|
|
3890
|
+
async start() {
|
|
3891
|
+
await this.initialize();
|
|
3892
|
+
try {
|
|
3905
3893
|
if (this._autoDetectPort) {
|
|
3906
3894
|
const originalPort = this._port;
|
|
3907
3895
|
this._port = await this.detectPort();
|
|
3908
|
-
if (originalPort !== this._port) this.
|
|
3896
|
+
if (originalPort !== this._port) this.server.log.info(`Port ${originalPort} is in use, detected next available port: ${this._port}`);
|
|
3909
3897
|
}
|
|
3910
|
-
await this.
|
|
3898
|
+
await this.server.listen({
|
|
3911
3899
|
port: this._port,
|
|
3912
3900
|
host: this._host
|
|
3913
3901
|
});
|
|
3914
3902
|
} catch (error) {
|
|
3915
3903
|
/* v8 ignore next -- @preserve */
|
|
3916
|
-
this.
|
|
3904
|
+
this.server.log.error(error);
|
|
3917
3905
|
}
|
|
3918
3906
|
}
|
|
3919
3907
|
/**
|
|
@@ -3921,7 +3909,7 @@ var MockHttp = class extends Hookified {
|
|
|
3921
3909
|
*/
|
|
3922
3910
|
async close() {
|
|
3923
3911
|
this._bins.stop();
|
|
3924
|
-
await this._server.close();
|
|
3912
|
+
if (this._server) await this._server.close();
|
|
3925
3913
|
}
|
|
3926
3914
|
/**
|
|
3927
3915
|
* Detect the next available port to run on.
|
|
@@ -3932,21 +3920,51 @@ var MockHttp = class extends Hookified {
|
|
|
3932
3920
|
return detect(port);
|
|
3933
3921
|
}
|
|
3934
3922
|
/**
|
|
3935
|
-
*
|
|
3923
|
+
* Register OpenAPI generation and the Docula documentation site.
|
|
3936
3924
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
3937
3925
|
*/
|
|
3938
3926
|
async registerApiDocs(fastifyInstance) {
|
|
3939
|
-
|
|
3927
|
+
await this.registerSwagger(fastifyInstance);
|
|
3928
|
+
await this.registerSite(fastifyInstance);
|
|
3929
|
+
}
|
|
3930
|
+
/**
|
|
3931
|
+
* Register `@fastify/swagger` and the live `/openapi.json` spec route.
|
|
3932
|
+
* @param fastifyInstance - the server instance to register the routes on.
|
|
3933
|
+
*/
|
|
3934
|
+
async registerSwagger(fastifyInstance) {
|
|
3935
|
+
const fastify = fastifyInstance ?? this.server;
|
|
3940
3936
|
await fastify.register(fastifySwagger, fastifySwaggerConfig);
|
|
3941
|
-
await
|
|
3942
|
-
|
|
3937
|
+
await registerOpenApiJson(fastify);
|
|
3938
|
+
}
|
|
3939
|
+
/**
|
|
3940
|
+
* Serve the built Docula site from `siteDistPath` when the directory exists.
|
|
3941
|
+
* @param fastifyInstance - the server instance to register the routes on.
|
|
3942
|
+
*/
|
|
3943
|
+
async registerSite(fastifyInstance) {
|
|
3944
|
+
const fastify = fastifyInstance ?? this.server;
|
|
3945
|
+
if (!existsSync(this._siteDistPath)) {
|
|
3946
|
+
fastify.log.warn(`Docula site not found at ${this._siteDistPath}; skipping static docs`);
|
|
3947
|
+
return;
|
|
3948
|
+
}
|
|
3949
|
+
const sitemapPath = path.join(this._siteDistPath, "sitemap.xml");
|
|
3950
|
+
if (existsSync(sitemapPath)) fastify.get("/sitemap.xml", { schema: { hide: true } }, async (request, reply) => {
|
|
3951
|
+
const xml = await fsPromises.readFile(sitemapPath, "utf8");
|
|
3952
|
+
return reply.type("application/xml").send(xml.replaceAll("https://mockhttp.org", requestOrigin(request)));
|
|
3953
|
+
});
|
|
3954
|
+
await fastify.register(fastifyStatic, {
|
|
3955
|
+
root: this._siteDistPath,
|
|
3956
|
+
prefix: "/",
|
|
3957
|
+
decorateReply: !fastify.hasReplyDecorator("sendFile"),
|
|
3958
|
+
index: ["index.html"],
|
|
3959
|
+
wildcard: true
|
|
3960
|
+
});
|
|
3943
3961
|
}
|
|
3944
3962
|
/**
|
|
3945
3963
|
* Register the HTTP methods routes.
|
|
3946
3964
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
3947
3965
|
*/
|
|
3948
3966
|
async registerHttpMethods(fastifyInstance) {
|
|
3949
|
-
const fastify = fastifyInstance ?? this.
|
|
3967
|
+
const fastify = fastifyInstance ?? this.server;
|
|
3950
3968
|
await fastify.register(getRoute);
|
|
3951
3969
|
await fastify.register(postRoute);
|
|
3952
3970
|
await fastify.register(deleteRoute);
|
|
@@ -3958,14 +3976,14 @@ var MockHttp = class extends Hookified {
|
|
|
3958
3976
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
3959
3977
|
*/
|
|
3960
3978
|
async registerStatusCodeRoutes(fastifyInstance) {
|
|
3961
|
-
await (fastifyInstance ?? this.
|
|
3979
|
+
await (fastifyInstance ?? this.server).register(statusCodeRoute);
|
|
3962
3980
|
}
|
|
3963
3981
|
/**
|
|
3964
3982
|
* Register the request inspection routes.
|
|
3965
3983
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
3966
3984
|
*/
|
|
3967
3985
|
async registerRequestInspectionRoutes(fastifyInstance) {
|
|
3968
|
-
const fastify = fastifyInstance ?? this.
|
|
3986
|
+
const fastify = fastifyInstance ?? this.server;
|
|
3969
3987
|
await fastify.register(ipRoute);
|
|
3970
3988
|
await fastify.register(headersRoute);
|
|
3971
3989
|
await fastify.register(userAgentRoute);
|
|
@@ -3975,20 +3993,20 @@ var MockHttp = class extends Hookified {
|
|
|
3975
3993
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
3976
3994
|
*/
|
|
3977
3995
|
async registerResponseInspectionRoutes(fastifyInstance) {
|
|
3978
|
-
const fastify = fastifyInstance ?? this.
|
|
3996
|
+
const fastify = fastifyInstance ?? this.server;
|
|
3979
3997
|
await fastify.register(cacheRoutes);
|
|
3980
3998
|
await fastify.register(etagRoutes);
|
|
3981
3999
|
await fastify.register(responseHeadersRoutes);
|
|
3982
4000
|
}
|
|
3983
4001
|
async registerResponseFormatRoutes(fastifyInstance) {
|
|
3984
|
-
await (fastifyInstance ?? this.
|
|
4002
|
+
await (fastifyInstance ?? this.server).register(responseFormatRoutes);
|
|
3985
4003
|
}
|
|
3986
4004
|
/**
|
|
3987
4005
|
* Register the redirect routes.
|
|
3988
4006
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
3989
4007
|
*/
|
|
3990
4008
|
async registerRedirectRoutes(fastifyInstance) {
|
|
3991
|
-
const fastify = fastifyInstance ?? this.
|
|
4009
|
+
const fastify = fastifyInstance ?? this.server;
|
|
3992
4010
|
await fastify.register(absoluteRedirectRoute);
|
|
3993
4011
|
await fastify.register(relativeRedirectRoute);
|
|
3994
4012
|
await fastify.register(redirectToRoute);
|
|
@@ -3998,7 +4016,7 @@ var MockHttp = class extends Hookified {
|
|
|
3998
4016
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
3999
4017
|
*/
|
|
4000
4018
|
async registerCookieRoutes(fastifyInstance) {
|
|
4001
|
-
const fastify = fastifyInstance ?? this.
|
|
4019
|
+
const fastify = fastifyInstance ?? this.server;
|
|
4002
4020
|
await fastify.register(fastifyCookie);
|
|
4003
4021
|
await fastify.register(getCookiesRoute);
|
|
4004
4022
|
await fastify.register(postCookieRoute);
|
|
@@ -4009,14 +4027,14 @@ var MockHttp = class extends Hookified {
|
|
|
4009
4027
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
4010
4028
|
*/
|
|
4011
4029
|
async registerAnythingRoutes(fastifyInstance) {
|
|
4012
|
-
await (fastifyInstance ?? this.
|
|
4030
|
+
await (fastifyInstance ?? this.server).register(anythingRoute);
|
|
4013
4031
|
}
|
|
4014
4032
|
/**
|
|
4015
4033
|
* Register the auth routes.
|
|
4016
4034
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
4017
4035
|
*/
|
|
4018
4036
|
async registerAuthRoutes(fastifyInstance) {
|
|
4019
|
-
const fastify = fastifyInstance ?? this.
|
|
4037
|
+
const fastify = fastifyInstance ?? this.server;
|
|
4020
4038
|
await fastify.register(basicAuthRoute);
|
|
4021
4039
|
await fastify.register(hiddenBasicAuthRoute);
|
|
4022
4040
|
await fastify.register(bearerAuthRoute);
|
|
@@ -4027,14 +4045,14 @@ var MockHttp = class extends Hookified {
|
|
|
4027
4045
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
4028
4046
|
*/
|
|
4029
4047
|
async registerImageRoutes(fastifyInstance) {
|
|
4030
|
-
await (fastifyInstance ?? this.
|
|
4048
|
+
await (fastifyInstance ?? this.server).register(imageRoutes);
|
|
4031
4049
|
}
|
|
4032
4050
|
/**
|
|
4033
4051
|
* Register the dynamic data routes.
|
|
4034
4052
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
4035
4053
|
*/
|
|
4036
4054
|
async registerDynamicDataRoutes(fastifyInstance) {
|
|
4037
|
-
const fastify = fastifyInstance ?? this.
|
|
4055
|
+
const fastify = fastifyInstance ?? this.server;
|
|
4038
4056
|
await fastify.register(uuidRoute);
|
|
4039
4057
|
await fastify.register(bytesRoute);
|
|
4040
4058
|
await fastify.register(streamBytesRoute);
|
|
@@ -4050,7 +4068,7 @@ var MockHttp = class extends Hookified {
|
|
|
4050
4068
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
4051
4069
|
*/
|
|
4052
4070
|
async registerBinRoutes(fastifyInstance) {
|
|
4053
|
-
const fastify = fastifyInstance ?? this.
|
|
4071
|
+
const fastify = fastifyInstance ?? this.server;
|
|
4054
4072
|
await fastify.register(binsManagementRoute(this._bins));
|
|
4055
4073
|
await fastify.register(binsCaptureRoute(this._bins));
|
|
4056
4074
|
}
|