@jaredwray/mockhttp 1.0.1 → 1.1.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 +175 -1
- package/dist/index.d.ts +27 -0
- package/dist/index.js +3197 -29
- package/package.json +27 -15
- package/public/logo.jpg +0 -0
- package/public/logo.png +0 -0
- package/public/logo.webp +0 -0
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ then run `mockhttp` in your code.
|
|
|
60
60
|
import { mockhttp } from '@jaredwray/mockhttp';
|
|
61
61
|
await mockhttp.start(); // start the server
|
|
62
62
|
const response = await fetch('http://localhost:3000/get');
|
|
63
|
-
console.log(
|
|
63
|
+
console.log(response);
|
|
64
64
|
await mockhttp.stop(); // stop the server
|
|
65
65
|
```
|
|
66
66
|
|
|
@@ -247,6 +247,164 @@ const tap = mock.taps.inject(
|
|
|
247
247
|
);
|
|
248
248
|
```
|
|
249
249
|
|
|
250
|
+
# Rate Limiting
|
|
251
|
+
|
|
252
|
+
MockHttp supports rate limiting using [@fastify/rate-limit](https://github.com/fastify/fastify-rate-limit). Rate limiting is **enabled by default** at **1000 requests per minute** with **localhost (127.0.0.1 and ::1) excluded** from rate limiting.
|
|
253
|
+
|
|
254
|
+
## Default Rate Limiting
|
|
255
|
+
|
|
256
|
+
By default, MockHttp applies the following rate limit:
|
|
257
|
+
- **1000 requests per minute** per IP address
|
|
258
|
+
- **Localhost is excluded** - requests from 127.0.0.1 and ::1 bypass rate limiting (ideal for local development and testing)
|
|
259
|
+
|
|
260
|
+
```javascript
|
|
261
|
+
import { MockHttp } from '@jaredwray/mockhttp';
|
|
262
|
+
|
|
263
|
+
const mock = new MockHttp();
|
|
264
|
+
await mock.start();
|
|
265
|
+
// Rate limiting is active (1000 req/min) except for localhost
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Customizing Rate Limiting
|
|
269
|
+
|
|
270
|
+
To customize rate limiting, pass a `rateLimit` configuration object when creating your MockHttp instance:
|
|
271
|
+
|
|
272
|
+
```javascript
|
|
273
|
+
import { MockHttp } from '@jaredwray/mockhttp';
|
|
274
|
+
|
|
275
|
+
const mock = new MockHttp({
|
|
276
|
+
rateLimit: {
|
|
277
|
+
max: 100, // Maximum 100 requests
|
|
278
|
+
timeWindow: '1 minute' // Per 1 minute window
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
await mock.start();
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Common Configuration Options
|
|
286
|
+
|
|
287
|
+
The `rateLimit` option accepts all [@fastify/rate-limit options](https://github.com/fastify/fastify-rate-limit#options):
|
|
288
|
+
|
|
289
|
+
### Basic Rate Limiting
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
// Limit to 50 requests per minute
|
|
293
|
+
const mock = new MockHttp({
|
|
294
|
+
rateLimit: {
|
|
295
|
+
max: 50,
|
|
296
|
+
timeWindow: '1 minute'
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Stricter Limits with Custom Error Response
|
|
302
|
+
|
|
303
|
+
```javascript
|
|
304
|
+
const mock = new MockHttp({
|
|
305
|
+
rateLimit: {
|
|
306
|
+
max: 30,
|
|
307
|
+
timeWindow: 60000, // 1 minute in milliseconds
|
|
308
|
+
errorResponseBuilder: (req, context) => ({
|
|
309
|
+
statusCode: 429,
|
|
310
|
+
error: 'Too Many Requests',
|
|
311
|
+
message: `Rate limit exceeded. Try again in ${context.after}`
|
|
312
|
+
})
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Allow List (Exclude Specific IPs)
|
|
318
|
+
|
|
319
|
+
```javascript
|
|
320
|
+
const mock = new MockHttp({
|
|
321
|
+
rateLimit: {
|
|
322
|
+
max: 100,
|
|
323
|
+
timeWindow: '1 minute',
|
|
324
|
+
allowList: ['127.0.0.1', '192.168.1.100'] // These IPs bypass rate limiting
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Custom Key Generator (Rate Limit by Header)
|
|
330
|
+
|
|
331
|
+
```javascript
|
|
332
|
+
const mock = new MockHttp({
|
|
333
|
+
rateLimit: {
|
|
334
|
+
max: 100,
|
|
335
|
+
timeWindow: '1 minute',
|
|
336
|
+
keyGenerator: (request) => {
|
|
337
|
+
// Rate limit by API key instead of IP
|
|
338
|
+
return request.headers['x-api-key'] || request.ip;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Advanced Configuration
|
|
345
|
+
|
|
346
|
+
```javascript
|
|
347
|
+
const mock = new MockHttp({
|
|
348
|
+
rateLimit: {
|
|
349
|
+
global: true, // Apply to all routes
|
|
350
|
+
max: 100, // Max requests
|
|
351
|
+
timeWindow: '1 minute', // Time window
|
|
352
|
+
cache: 10000, // Cache size for tracking clients
|
|
353
|
+
skipOnError: false, // Don't skip on storage errors
|
|
354
|
+
ban: 10, // Ban after 10 rate limit violations
|
|
355
|
+
continueExceeding: false, // Don't reset window on each request
|
|
356
|
+
enableDraftSpec: true, // Use IETF draft spec headers
|
|
357
|
+
addHeaders: { // Customize rate limit headers
|
|
358
|
+
'x-ratelimit-limit': true,
|
|
359
|
+
'x-ratelimit-remaining': true,
|
|
360
|
+
'x-ratelimit-reset': true
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Disabling Rate Limiting
|
|
367
|
+
|
|
368
|
+
To disable rate limiting completely, set the `rateLimit` option to `false`:
|
|
369
|
+
|
|
370
|
+
```javascript
|
|
371
|
+
const mock = new MockHttp({
|
|
372
|
+
rateLimit: false // Completely disable rate limiting
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
await mock.start();
|
|
376
|
+
// No rate limiting is applied to any requests
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
**Note:** To change rate limiting settings after the server has started, you must restart the server:
|
|
380
|
+
|
|
381
|
+
```javascript
|
|
382
|
+
const mock = new MockHttp();
|
|
383
|
+
await mock.start(); // Starts with default rate limiting
|
|
384
|
+
|
|
385
|
+
// To change or disable rate limiting:
|
|
386
|
+
await mock.close();
|
|
387
|
+
mock.rateLimit = undefined; // or set new options
|
|
388
|
+
await mock.start(); // Restarts with new settings
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## Available Options
|
|
392
|
+
|
|
393
|
+
| Option | Type | Default | Description |
|
|
394
|
+
|--------|------|---------|-------------|
|
|
395
|
+
| `max` | number \| function | `1000` | Maximum requests per time window |
|
|
396
|
+
| `timeWindow` | number \| string | `60000` | Duration of rate limit window (milliseconds or string like '1 minute') |
|
|
397
|
+
| `cache` | number | `5000` | LRU cache size for tracking clients |
|
|
398
|
+
| `allowList` | array \| function | `[]` | IPs or function to exclude from rate limiting |
|
|
399
|
+
| `keyGenerator` | function | IP-based | Function to generate unique client identifier |
|
|
400
|
+
| `errorResponseBuilder` | function | Default 429 | Custom error response function |
|
|
401
|
+
| `skipOnError` | boolean | `false` | Skip rate limiting if storage errors occur |
|
|
402
|
+
| `ban` | number | `-1` | Ban client after N violations (disabled by default) |
|
|
403
|
+
| `continueExceeding` | boolean | `false` | Renew time window on each request while limited |
|
|
404
|
+
| `enableDraftSpec` | boolean | `false` | Use IETF draft specification headers |
|
|
405
|
+
|
|
406
|
+
For the complete list of options, see the [@fastify/rate-limit documentation](https://github.com/fastify/fastify-rate-limit#options).
|
|
407
|
+
|
|
250
408
|
# API Reference
|
|
251
409
|
|
|
252
410
|
## MockHttp Class
|
|
@@ -264,7 +422,18 @@ new MockHttp(options?)
|
|
|
264
422
|
- `autoDetectPort?`: boolean - Auto-detect next available port if in use (default: true)
|
|
265
423
|
- `helmet?`: boolean - Use Helmet for security headers (default: true)
|
|
266
424
|
- `apiDocs?`: boolean - Enable Swagger API documentation (default: true)
|
|
425
|
+
- `rateLimit?`: RateLimitPluginOptions - Configure rate limiting (default: 1000 req/min, localhost excluded)
|
|
267
426
|
- `httpBin?`: HttpBinOptions - Configure which httpbin routes to enable
|
|
427
|
+
- `httpMethods?`: boolean - Enable HTTP method routes (default: true)
|
|
428
|
+
- `redirects?`: boolean - Enable redirect routes (default: true)
|
|
429
|
+
- `requestInspection?`: boolean - Enable request inspection routes (default: true)
|
|
430
|
+
- `responseInspection?`: boolean - Enable response inspection routes (default: true)
|
|
431
|
+
- `statusCodes?`: boolean - Enable status code routes (default: true)
|
|
432
|
+
- `responseFormats?`: boolean - Enable response format routes (default: true)
|
|
433
|
+
- `cookies?`: boolean - Enable cookie routes (default: true)
|
|
434
|
+
- `anything?`: boolean - Enable anything routes (default: true)
|
|
435
|
+
- `auth?`: boolean - Enable authentication routes (default: true)
|
|
436
|
+
- `images?`: boolean - Enable image routes (default: true)
|
|
268
437
|
- `hookOptions?`: HookifiedOptions - Hookified options
|
|
269
438
|
|
|
270
439
|
### Properties
|
|
@@ -274,6 +443,7 @@ new MockHttp(options?)
|
|
|
274
443
|
- `autoDetectPort`: boolean - Get/set auto-detect port behavior
|
|
275
444
|
- `helmet`: boolean - Get/set Helmet security headers
|
|
276
445
|
- `apiDocs`: boolean - Get/set API documentation
|
|
446
|
+
- `rateLimit`: RateLimitPluginOptions | undefined - Get/set rate limiting options
|
|
277
447
|
- `httpBin`: HttpBinOptions - Get/set httpbin route options
|
|
278
448
|
- `server`: FastifyInstance - Get/set the Fastify server instance
|
|
279
449
|
- `taps`: TapManager - Get/set the TapManager instance
|
|
@@ -334,6 +504,10 @@ Register "anything" catch-all routes.
|
|
|
334
504
|
|
|
335
505
|
Register authentication routes (basic, bearer, digest, hidden-basic).
|
|
336
506
|
|
|
507
|
+
#### `async registerImageRoutes(fastifyInstance?)`
|
|
508
|
+
|
|
509
|
+
Register image routes (jpeg, png, svg, webp) with content negotiation support.
|
|
510
|
+
|
|
337
511
|
## Taps (Response Injection)
|
|
338
512
|
|
|
339
513
|
Access the TapManager via `mockHttp.taps` to inject custom responses.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RateLimitPluginOptions } from '@fastify/rate-limit';
|
|
1
2
|
import { FastifyRequest, FastifyInstance } from 'fastify';
|
|
2
3
|
import { Hookified, HookifiedOptions } from 'hookified';
|
|
3
4
|
|
|
@@ -130,6 +131,7 @@ type HttpBinOptions = {
|
|
|
130
131
|
cookies?: boolean;
|
|
131
132
|
anything?: boolean;
|
|
132
133
|
auth?: boolean;
|
|
134
|
+
images?: boolean;
|
|
133
135
|
};
|
|
134
136
|
type MockHttpOptions = {
|
|
135
137
|
/**
|
|
@@ -157,6 +159,11 @@ type MockHttpOptions = {
|
|
|
157
159
|
* Whether to use Swagger UI. Defaults to true.
|
|
158
160
|
*/
|
|
159
161
|
httpBin?: HttpBinOptions;
|
|
162
|
+
/**
|
|
163
|
+
* Rate limiting options. Defaults to 1000 requests per minute (localhost excluded).
|
|
164
|
+
* Set to undefined to disable rate limiting, or provide custom options to configure.
|
|
165
|
+
*/
|
|
166
|
+
rateLimit?: boolean | RateLimitPluginOptions;
|
|
160
167
|
/**
|
|
161
168
|
* Hookified options.
|
|
162
169
|
*/
|
|
@@ -169,6 +176,7 @@ declare class MockHttp extends Hookified {
|
|
|
169
176
|
private _helmet;
|
|
170
177
|
private _apiDocs;
|
|
171
178
|
private _httpBin;
|
|
179
|
+
private _rateLimit?;
|
|
172
180
|
private _server;
|
|
173
181
|
private _taps;
|
|
174
182
|
constructor(options?: MockHttpOptions);
|
|
@@ -230,6 +238,20 @@ declare class MockHttp extends Hookified {
|
|
|
230
238
|
* HTTP Bin options. Defaults to all enabled.
|
|
231
239
|
*/
|
|
232
240
|
set httpBin(httpBinary: HttpBinOptions);
|
|
241
|
+
/**
|
|
242
|
+
* Rate limiting options. Defaults to 1000 requests per minute (localhost excluded).
|
|
243
|
+
* Set to undefined to disable rate limiting, or provide custom options to configure.
|
|
244
|
+
* @default { max: 1000, timeWindow: "1 minute", allowList: ["127.0.0.1", "::1"] }
|
|
245
|
+
*/
|
|
246
|
+
get rateLimit(): RateLimitPluginOptions | undefined;
|
|
247
|
+
/**
|
|
248
|
+
* Rate limiting options. Defaults to 1000 requests per minute (localhost excluded).
|
|
249
|
+
* Set to undefined to disable rate limiting, or provide custom options to configure.
|
|
250
|
+
*
|
|
251
|
+
* Note: Changing this property requires restarting the server (close() then start()) for changes to take effect.
|
|
252
|
+
* @default { max: 1000, timeWindow: "1 minute", allowList: ["127.0.0.1", "::1"] }
|
|
253
|
+
*/
|
|
254
|
+
set rateLimit(rateLimit: RateLimitPluginOptions | undefined);
|
|
233
255
|
/**
|
|
234
256
|
* The Fastify server instance.
|
|
235
257
|
*/
|
|
@@ -305,6 +327,11 @@ declare class MockHttp extends Hookified {
|
|
|
305
327
|
* @param fastifyInstance - the server instance to register the routes on.
|
|
306
328
|
*/
|
|
307
329
|
registerAuthRoutes(fastifyInstance?: FastifyInstance): Promise<void>;
|
|
330
|
+
/**
|
|
331
|
+
* Register the image routes.
|
|
332
|
+
* @param fastifyInstance - the server instance to register the routes on.
|
|
333
|
+
*/
|
|
334
|
+
registerImageRoutes(fastifyInstance?: FastifyInstance): Promise<void>;
|
|
308
335
|
}
|
|
309
336
|
|
|
310
337
|
declare const start: () => Promise<MockHttp>;
|