@jaredwray/mockhttp 1.5.1 → 1.6.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/README.md +18 -2
- package/dist/index.mjs +49 -12
- package/package.json +17 -26
package/README.md
CHANGED
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
[](https://hub.docker.com/r/jaredwray/mockhttp)
|
|
9
9
|
[](https://mockhttp.org)
|
|
10
10
|
|
|
11
|
-
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`.
|
|
11
|
+
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`.
|
|
12
12
|
|
|
13
13
|
# Features
|
|
14
14
|
* All the features of [httpbin](https://httpbin.org/)
|
|
15
|
-
* Taps - Inject custom responses for testing and
|
|
15
|
+
* Taps - Inject custom responses for testing and development
|
|
16
16
|
* `@fastify/helmet` built in by default
|
|
17
17
|
* Built with `nodejs`, `typescript`, and `fastify`
|
|
18
18
|
* Deploy via `docker` or `nodejs`
|
|
@@ -30,6 +30,7 @@ A simple HTTP server that can be used to mock HTTP responses for testing purpose
|
|
|
30
30
|
- [Response Injection (Tap Feature)](#response-injection-tap-feature)
|
|
31
31
|
- [Rate Limiting](#rate-limiting)
|
|
32
32
|
- [Logging](#logging)
|
|
33
|
+
- [Flexible URL Matching](#flexible-url-matching)
|
|
33
34
|
- [API Reference](#api-reference)
|
|
34
35
|
- [About mockhttp.org](#about-mockhttporg)
|
|
35
36
|
- [Contributing](#contributing)
|
|
@@ -608,6 +609,21 @@ You can also disable logging via the `LOGGING` environment variable:
|
|
|
608
609
|
LOGGING=false node your-app.js
|
|
609
610
|
```
|
|
610
611
|
|
|
612
|
+
# Flexible URL Matching
|
|
613
|
+
|
|
614
|
+
MockHttp ignores trailing path segments that come after the parsable portion of a URL. This is useful when a client appends extra data to a known endpoint — instead of returning 404, MockHttp serves the closest matching route.
|
|
615
|
+
|
|
616
|
+
For example, all of these are served by `/status/:code`:
|
|
617
|
+
|
|
618
|
+
```
|
|
619
|
+
GET /status/429
|
|
620
|
+
GET /status/429/
|
|
621
|
+
GET /status/429/foo
|
|
622
|
+
GET /status/429/foo/bar
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
The rewrite preserves the query string and only triggers when a more specific route exists; URLs whose first path segment doesn't correspond to a registered route still return 404.
|
|
626
|
+
|
|
611
627
|
# API Reference
|
|
612
628
|
|
|
613
629
|
## MockHttp Class
|
package/dist/index.mjs
CHANGED
|
@@ -246,16 +246,47 @@ async function generateCertificateFiles(options) {
|
|
|
246
246
|
}
|
|
247
247
|
//#endregion
|
|
248
248
|
//#region src/fastify-config.ts
|
|
249
|
+
function isSpecificMatch(route) {
|
|
250
|
+
if (!route) return false;
|
|
251
|
+
const params = route.params;
|
|
252
|
+
return params === void 0 || params["*"] === void 0;
|
|
253
|
+
}
|
|
254
|
+
function rewriteUrl(req) {
|
|
255
|
+
const originalUrl = req.url ?? "/";
|
|
256
|
+
const method = req.method;
|
|
257
|
+
if (!method) return originalUrl;
|
|
258
|
+
const queryIdx = originalUrl.indexOf("?");
|
|
259
|
+
const path = queryIdx >= 0 ? originalUrl.slice(0, queryIdx) : originalUrl;
|
|
260
|
+
const query = queryIdx >= 0 ? originalUrl.slice(queryIdx) : "";
|
|
261
|
+
if (isSpecificMatch(this.findRoute({
|
|
262
|
+
method,
|
|
263
|
+
url: path
|
|
264
|
+
}))) return originalUrl;
|
|
265
|
+
const segments = path.split("/").filter(Boolean);
|
|
266
|
+
while (segments.length >= 1) {
|
|
267
|
+
const candidatePath = `/${segments.join("/")}`;
|
|
268
|
+
if (candidatePath !== path && isSpecificMatch(this.findRoute({
|
|
269
|
+
method,
|
|
270
|
+
url: candidatePath
|
|
271
|
+
}))) return candidatePath + query;
|
|
272
|
+
if (segments.length === 1) break;
|
|
273
|
+
segments.pop();
|
|
274
|
+
}
|
|
275
|
+
return originalUrl;
|
|
276
|
+
}
|
|
249
277
|
function getFastifyConfig(logging = true) {
|
|
250
|
-
return {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
278
|
+
return {
|
|
279
|
+
logger: logging ? { transport: {
|
|
280
|
+
target: "pino-pretty",
|
|
281
|
+
options: {
|
|
282
|
+
colorize: true,
|
|
283
|
+
translateTime: true,
|
|
284
|
+
ignore: "pid,hostname",
|
|
285
|
+
singleLine: true
|
|
286
|
+
}
|
|
287
|
+
} } : false,
|
|
288
|
+
rewriteUrl
|
|
289
|
+
};
|
|
259
290
|
}
|
|
260
291
|
//#endregion
|
|
261
292
|
//#region src/routes/anything/index.ts
|
|
@@ -328,6 +359,7 @@ const anythingRoute = (fastify) => {
|
|
|
328
359
|
};
|
|
329
360
|
const noValidation = {
|
|
330
361
|
schema: anythingSchema,
|
|
362
|
+
/* v8 ignore next -- @preserve */
|
|
331
363
|
validatorCompiler: () => () => true
|
|
332
364
|
};
|
|
333
365
|
fastify.get("/anything", noValidation, handler);
|
|
@@ -869,6 +901,7 @@ const delayRoute = (fastify) => {
|
|
|
869
901
|
/* v8 ignore next -- @preserve */
|
|
870
902
|
const host = request.headers.host || "localhost";
|
|
871
903
|
return {
|
|
904
|
+
/* v8 ignore next -- @preserve */
|
|
872
905
|
args: request.query || {},
|
|
873
906
|
data: "",
|
|
874
907
|
files: {},
|
|
@@ -1176,6 +1209,7 @@ const streamRoute = (fastify) => {
|
|
|
1176
1209
|
for (let i = 0; i < lines; i++) {
|
|
1177
1210
|
const data = {
|
|
1178
1211
|
id: i,
|
|
1212
|
+
/* v8 ignore next -- @preserve */
|
|
1179
1213
|
args: request.query || {},
|
|
1180
1214
|
headers: request.headers,
|
|
1181
1215
|
origin: request.ip,
|
|
@@ -2867,17 +2901,17 @@ const fastifySwaggerConfig = { openapi: {
|
|
|
2867
2901
|
info: {
|
|
2868
2902
|
title: "Mock HTTP API",
|
|
2869
2903
|
description: `
|
|
2870
|
-
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\`.
|
|
2904
|
+
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\`.
|
|
2871
2905
|
|
|
2872
2906
|
* [GitHub Repository](https://github.com/jaredwray/mockhttp)
|
|
2873
2907
|
* [Docker Image](https://hub.docker.com/r/jaredwray/mockhttp)
|
|
2874
|
-
* [NPM Package](https://www.npmjs.com/package
|
|
2908
|
+
* [NPM Package](https://www.npmjs.com/package/@jaredwray/mockhttp)
|
|
2875
2909
|
|
|
2876
2910
|
# About mockhttp.org
|
|
2877
2911
|
|
|
2878
2912
|
[mockhttp.org](https://mockhttp.org) is a free service that runs this codebase and allows you to use it for testing purposes. It is a simple way to mock HTTP responses for testing purposes. Ran via [Cloudflare](https://cloudflare.com) and [Google Cloud Run](https://cloud.google.com/run/) across 7 regions globally and can do millions of requests per second.
|
|
2879
2913
|
`,
|
|
2880
|
-
version: "1.
|
|
2914
|
+
version: "1.6.1"
|
|
2881
2915
|
},
|
|
2882
2916
|
consumes: ["application/json"],
|
|
2883
2917
|
produces: ["application/json"]
|
|
@@ -2890,14 +2924,17 @@ const registerSwaggerUi = async (fastify) => {
|
|
|
2890
2924
|
deepLinking: false
|
|
2891
2925
|
},
|
|
2892
2926
|
uiHooks: {
|
|
2927
|
+
/* v8 ignore next -- @preserve */
|
|
2893
2928
|
onRequest(_request, _reply, next) {
|
|
2894
2929
|
next();
|
|
2895
2930
|
},
|
|
2931
|
+
/* v8 ignore next -- @preserve */
|
|
2896
2932
|
preHandler(_request, _reply, next) {
|
|
2897
2933
|
next();
|
|
2898
2934
|
}
|
|
2899
2935
|
},
|
|
2900
2936
|
staticCSP: true,
|
|
2937
|
+
/* v8 ignore next -- @preserve */
|
|
2901
2938
|
transformSpecification: (swaggerObject, _request, _reply) => swaggerObject,
|
|
2902
2939
|
transformSpecificationClone: true
|
|
2903
2940
|
});
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jaredwray/mockhttp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "Mock Http - Easy way to mock http with httpbin replacement",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.mts",
|
|
8
|
+
"packageManager": "pnpm@11.1.3",
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=22.18.0"
|
|
11
|
+
},
|
|
8
12
|
"directories": {
|
|
9
13
|
"test": "test"
|
|
10
14
|
},
|
|
@@ -53,27 +57,27 @@
|
|
|
53
57
|
},
|
|
54
58
|
"homepage": "https://github.com/jaredwray/mockhttp#readme",
|
|
55
59
|
"devDependencies": {
|
|
56
|
-
"@biomejs/biome": "^2.4.
|
|
57
|
-
"@swc/core": "^1.15.
|
|
60
|
+
"@biomejs/biome": "^2.4.15",
|
|
61
|
+
"@swc/core": "^1.15.33",
|
|
58
62
|
"@types/html-escaper": "^3.0.4",
|
|
59
|
-
"@vitest/coverage-v8": "^4.1.
|
|
63
|
+
"@vitest/coverage-v8": "^4.1.6",
|
|
60
64
|
"rimraf": "^6.1.3",
|
|
61
|
-
"tsdown": "^0.
|
|
65
|
+
"tsdown": "^0.22.0",
|
|
62
66
|
"tsx": "^4.21.0",
|
|
63
|
-
"typescript": "6.0.
|
|
64
|
-
"vitest": "^4.1.
|
|
67
|
+
"typescript": "6.0.3",
|
|
68
|
+
"vitest": "^4.1.6"
|
|
65
69
|
},
|
|
66
70
|
"dependencies": {
|
|
67
71
|
"@fastify/cookie": "^11.0.2",
|
|
68
72
|
"@fastify/helmet": "^13.0.2",
|
|
69
73
|
"@fastify/rate-limit": "^10.3.0",
|
|
70
|
-
"@fastify/static": "^9.1.
|
|
74
|
+
"@fastify/static": "^9.1.3",
|
|
71
75
|
"@fastify/swagger": "^9.7.0",
|
|
72
|
-
"@fastify/swagger-ui": "^5.2.
|
|
73
|
-
"@scalar/api-reference": "^1.
|
|
76
|
+
"@fastify/swagger-ui": "^5.2.6",
|
|
77
|
+
"@scalar/api-reference": "^1.55.3",
|
|
74
78
|
"detect-port": "^2.1.0",
|
|
75
|
-
"fastify": "^5.8.
|
|
76
|
-
"hookified": "^2.
|
|
79
|
+
"fastify": "^5.8.5",
|
|
80
|
+
"hookified": "^2.2.0",
|
|
77
81
|
"html-escaper": "^3.0.3",
|
|
78
82
|
"pino": "^10.3.1",
|
|
79
83
|
"pino-pretty": "^13.1.3"
|
|
@@ -82,18 +86,5 @@
|
|
|
82
86
|
"dist",
|
|
83
87
|
"public",
|
|
84
88
|
"LICENCE"
|
|
85
|
-
]
|
|
86
|
-
"pnpm": {
|
|
87
|
-
"overrides": {
|
|
88
|
-
"set-cookie-parser": "2.7.2"
|
|
89
|
-
},
|
|
90
|
-
"onlyBuiltDependencies": [
|
|
91
|
-
"@swc/core",
|
|
92
|
-
"core-js",
|
|
93
|
-
"esbuild",
|
|
94
|
-
"protobufjs",
|
|
95
|
-
"unrs-resolver",
|
|
96
|
-
"vue-demi"
|
|
97
|
-
]
|
|
98
|
-
}
|
|
89
|
+
]
|
|
99
90
|
}
|