@jaredwray/mockhttp 2.0.0 → 2.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 +11 -1
- package/dist/index.mjs +2 -1
- package/package.json +1 -1
- package/site/dist/api/index.html +2 -2
- package/site/dist/api/swagger.json +1 -1
- package/site/dist/changelog/index.html +34 -17
- package/site/dist/changelog/page/2/index.html +17 -18
- package/site/dist/changelog/{v0-1-0 → v2-1-0}/index.html +45 -22
- package/site/dist/changelog-latest.json +13 -13
- package/site/dist/changelog.json +13 -13
- package/site/dist/docs/bins/index.html +42 -4
- package/site/dist/docs/configuration/index.html +42 -4
- package/site/dist/docs/hosted/index.html +47 -8
- package/site/dist/docs/how-to-deploy/cloudflare/index.html +655 -0
- package/site/dist/docs/how-to-deploy/docker/index.html +664 -0
- package/site/dist/docs/how-to-deploy/wasmer/index.html +625 -0
- package/site/dist/docs/https/index.html +42 -4
- package/site/dist/docs/index.html +44 -5
- package/site/dist/docs/library/index.html +42 -4
- package/site/dist/docs/taps/index.html +42 -4
- package/site/dist/feed.xml +1 -1
- package/site/dist/index.html +44 -5
- package/site/dist/llms-full.txt +254 -29
- package/site/dist/llms.txt +5 -2
- package/site/dist/search-index.json +1 -1
- package/site/dist/sitemap.xml +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"records":[{"id":"/docs/","title":"Getting Started","titles":[],"text":"A simple HTTP server for mocking responses in tests. Inspired by httpbin and built with Node.js and Fastify. Run it at mockhttp.org , with Docker ( jaredwray/mockhttp ), or in Node.js ( npm install @jaredwray/mockhttp ).","url":"/docs/"},{"id":"/docs/#features","title":"Features","titles":["Getting Started"],"text":"All the features of httpbin Taps — inject custom responses for testing and development Bins — capture and inspect incoming HTTP requests (great for webhook debugging) @fastify/helmet built in by default Built with Node.js, TypeScript, and Fastify Deploy via Docker or Node.js Free hosted service at mockhttp.org , running on Cloudflare Documentation site and interactive OpenAPI reference Auto-detect the next port that is not in use HTTPS and HTTP/2 , plus rate limiting, logging, and URL matching","url":"/docs/#features"},{"id":"/docs/#deploy-via-docker","title":"Deploy via Docker","titles":["Getting Started"],"text":"docker run -d -p 3000:3000 jaredwray/mockhttp","url":"/docs/#deploy-via-docker"},{"id":"/docs/#deploy-via-docker-compose","title":"Deploy via Docker Compose","titles":["Getting Started"],"text":"services: mockhttp: image: jaredwray/mockhttp:latest ports: - \"3000:3000\" If you want to run it on a different port, just change the 3000 to whatever port you want and add in the environment variable PORT to the environment. services: mockhttp: image: jaredwray/mockhttp:latest ports: - \"3001:3001\" environment: - PORT=3001 You can see an example of this in the docker-compose.yaml file.","url":"/docs/#deploy-via-docker-compose"},{"id":"/docs/#deploy-via-nodejs","title":"Deploy via Node.js","titles":["Getting Started"],"text":"npm install @jaredwray/mockhttp --save then run mockhttp in your code. import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp (); await mock. start (); // start the server const response = await fetch ( 'http://localhost:3000/get' ); console . log (response); await mock. close (); // stop the server","url":"/docs/#deploy-via-nodejs"},{"id":"/docs/https/","title":"HTTPS and HTTP/2","titles":[],"text":"MockHttp supports HTTPS with auto-generated self-signed certificates or your own custom certificates. No external dependencies are required — certificate generation uses only Node.js built-in crypto .","url":"/docs/https/"},{"id":"/docs/https/#auto-generated-certificate","title":"Auto-Generated Certificate","titles":["HTTPS and HTTP/2"],"text":"The simplest way to enable HTTPS is to pass https: true . A self-signed certificate for localhost is generated automatically: import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp ({ https : true }); await mock. start (); console . log (mock. isHttps ); // true // Use Fastify's built-in inject() for testing (no TLS setup needed) const response = await mock. server . inject ({ method : 'GET' , url : '/get' }); console . log (response. statusCode ); // 200 await mock. close (); Note: Self-signed certificates are not trusted by default. When making real HTTPS requests (e.g. with fetch ), set NODE_TLS_REJECT_UNAUTHORIZED=0 in your test environment or use a custom HTTPS agent.","url":"/docs/https/#auto-generated-certificate"},{"id":"/docs/https/#custom-certificate-options","title":"Custom Certificate Options","titles":["HTTPS and HTTP/2"],"text":"You can customize the auto-generated certificate by passing certificateOptions : const mock = new MockHttp ({ https : { certificateOptions : { commonName : 'my-test-server' , validityDays : 30 , keySize : 4096 , altNames : [ { type : 'dns' , value : 'example.local' }, { type : 'dns' , value : '*.example.local' }, { type : 'ip' , value : '192.168.1.100' }, ], }, }, }); await mock. start (); // Make requests... await mock. close ();","url":"/docs/https/#custom-certificate-options"},{"id":"/docs/https/#provide-your-own-certificate","title":"Provide Your Own Certificate","titles":["HTTPS and HTTP/2"],"text":"You can supply your own PEM-encoded certificate and key, either as strings or file paths: // Using PEM strings const mock = new MockHttp ({ https : { cert : '-----BEGIN CERTIFICATE-----\\n...' , key : '-----BEGIN PRIVATE KEY-----\\n...' , }, }); await mock. start (); // Make requests... await mock. close (); // Using file paths const mock = new MockHttp ({ https : { cert : '/path/to/cert.pem' , key : '/path/to/key.pem' , }, }); await mock. start (); // Make requests... await mock. close ();","url":"/docs/https/#provide-your-own-certificate"},{"id":"/docs/https/#standalone-certificate-generation","title":"Standalone Certificate Generation","titles":["HTTPS and HTTP/2"],"text":"You can also generate certificates independently using the exported utility functions: import { generateCertificate, generateCertificateFiles } from '@jaredwray/mockhttp' ; // Generate in-memory PEM strings const { cert, key } = generateCertificate ({ commonName : 'my-app' , validityDays : 90 , }); // Generate and write to disk const result = await generateCertificateFiles ({ certPath : './certs/cert.pem' , keyPath : './certs/key.pem' , commonName : 'my-app' , });","url":"/docs/https/#standalone-certificate-generation"},{"id":"/docs/https/#https-options-reference","title":"HTTPS Options Reference","titles":["HTTPS and HTTP/2"],"text":"Option Type Default Description cert string — PEM-encoded certificate string or file path key string — PEM-encoded private key string or file path autoGenerate boolean true Auto-generate a self-signed certificate when cert/key are not provided certificateOptions CertificateOptions — Options for the auto-generated certificate","url":"/docs/https/#https-options-reference"},{"id":"/docs/https/#certificate-options","title":"Certificate Options","titles":["HTTPS and HTTP/2","HTTPS Options Reference"],"text":"Option Type Default Description commonName string 'localhost' Certificate subject Common Name (CN) altNames Array<{ type, value }> [dns:localhost, ip:127.0.0.1, ip:::1] Subject Alternative Names with type 'dns' or 'ip' validityDays number 365 Certificate validity period in days keySize number 2048 RSA key size in bits","url":"/docs/https/#certificate-options"},{"id":"/docs/https/#http2-support","title":"HTTP/2 Support","titles":["HTTPS and HTTP/2"],"text":"MockHttp supports HTTP/2 in two modes: h2 — HTTP/2 over TLS (used by browsers), enabled with both http2: true and https: true h2c — HTTP/2 cleartext (no TLS), enabled with just http2: true , useful for service-to-service testing","url":"/docs/https/#http2-support"},{"id":"/docs/https/#http2-over-tls-h2","title":"HTTP/2 over TLS (h2)","titles":["HTTPS and HTTP/2","HTTP/2 Support"],"text":"import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp ({ http2 : true , https : true }); await mock. start (); console . log (mock. http2 ); // true console . log (mock. isHttps ); // true const response = await mock. server . inject ({ method : 'GET' , url : '/get' }); console . log (response. statusCode ); // 200 await mock. close (); By default, HTTP/1.1 clients can still connect via ALPN negotiation ( http1 defaults to true ). To disable HTTP/1.1 fallback: const mock = new MockHttp ({ http2 : true , https : true , http1 : false }); await mock. start ();","url":"/docs/https/#http2-over-tls-h2"},{"id":"/docs/https/#http2-cleartext-h2c","title":"HTTP/2 Cleartext (h2c)","titles":["HTTPS and HTTP/2","HTTP/2 Support"],"text":"const mock = new MockHttp ({ http2 : true }); await mock. start (); console . log (mock. http2 ); // true await mock. close (); Note: Browsers do not support h2c. This mode is useful for testing gRPC or service-to-service communication.","url":"/docs/https/#http2-cleartext-h2c"},{"id":"/docs/https/#http2-via-environment-variable","title":"HTTP/2 via Environment Variable","titles":["HTTPS and HTTP/2","HTTP/2 Support"],"text":"HTTP2= true node your-app.js","url":"/docs/https/#http2-via-environment-variable"},{"id":"/docs/taps/","title":"Taps","titles":[],"text":"The injection/tap feature allows you to \"tap into\" the request flow and inject custom responses for specific requests. This is particularly useful for: Offline testing - Mock external API responses without network access Testing edge cases - Simulate errors, timeouts, or specific response scenarios Development - Work on your application without depending on external services","url":"/docs/taps/"},{"id":"/docs/taps/#what-is-a-tap","title":"What is a \"Tap\"?","titles":["Taps"],"text":"A \"tap\" is a reference to an injected response, similar to \"wiretapping\" - you're intercepting requests and returning predefined responses. Each tap can be removed when you're done with it, restoring normal server behavior.","url":"/docs/taps/#what-is-a-tap"},{"id":"/docs/taps/#basic-usage","title":"Basic Usage","titles":["Taps"],"text":"import { mockhttp } from '@jaredwray/mockhttp' ; const mock = new mockhttp (); await mock. start (); // Inject a simple response const tap = mock. taps . inject ( { response : \"Hello, World!\" , statusCode : 200 , headers : { \"Content-Type\" : \"text/plain\" } }, { url : \"/api/greeting\" , method : \"GET\" } ); // Make requests - they will get the injected response const response = await fetch ( 'http://localhost:3000/api/greeting' ); console . log ( await response. text ()); // \"Hello, World!\" // Remove the injection when done mock. taps . removeInjection (tap); await mock. close ();","url":"/docs/taps/#basic-usage"},{"id":"/docs/taps/#advanced-examples","title":"Advanced Examples","titles":["Taps"],"text":"","url":"/docs/taps/#advanced-examples"},{"id":"/docs/taps/#inject-json-response","title":"Inject JSON Response","titles":["Taps","Advanced Examples"],"text":"const tap = mock. taps . inject ( { response : { message : \"Success\" , data : { id : 123 } }, statusCode : 200 }, { url : \"/api/users/123\" } );","url":"/docs/taps/#inject-json-response"},{"id":"/docs/taps/#wildcard-url-matching","title":"Wildcard URL Matching","titles":["Taps","Advanced Examples"],"text":"// Match all requests under /api/ const tap = mock. taps . inject ( { response : \"API is mocked\" , statusCode : 503 }, { url : \"/api/*\" } );","url":"/docs/taps/#wildcard-url-matching"},{"id":"/docs/taps/#multiple-injections","title":"Multiple Injections","titles":["Taps","Advanced Examples"],"text":"const tap1 = mock. taps . inject ( { response : \"Users data\" }, { url : \"/api/users\" } ); const tap2 = mock. taps . inject ( { response : \"Posts data\" }, { url : \"/api/posts\" } ); // View all active injections console . log (mock. taps . injections ); // Map of all active taps // Remove specific injections mock. taps . removeInjection (tap1); mock. taps . removeInjection (tap2);","url":"/docs/taps/#multiple-injections"},{"id":"/docs/taps/#match-by-http-method","title":"Match by HTTP Method","titles":["Taps","Advanced Examples"],"text":"// Only intercept POST requests const tap = mock. taps . inject ( { response : \"Created\" , statusCode : 201 }, { url : \"/api/users\" , method : \"POST\" } );","url":"/docs/taps/#match-by-http-method"},{"id":"/docs/taps/#match-by-headers","title":"Match by Headers","titles":["Taps","Advanced Examples"],"text":"const tap = mock. taps . inject ( { response : \"Authenticated response\" }, { url : \"/api/secure\" , headers : { \"authorization\" : \"Bearer token123\" } } );","url":"/docs/taps/#match-by-headers"},{"id":"/docs/taps/#catch-all-injection","title":"Catch-All Injection","titles":["Taps","Advanced Examples"],"text":"// Match ALL requests (no matcher specified) const tap = mock. taps . inject ({ response : \"Server is in maintenance mode\" , statusCode : 503 });","url":"/docs/taps/#catch-all-injection"},{"id":"/docs/taps/#dynamic-function-response","title":"Dynamic Function Response","titles":["Taps","Advanced Examples"],"text":"You can provide a function that dynamically generates the response based on the incoming request: // Function response with access to the request object const tap = mock. taps . inject ( ( request ) => { return { response : { message : `You requested ${request.url} ` , method : request. method , timestamp : new Date (). toISOString () }, statusCode : 200 , headers : { \"X-Request-Path\" : request. url } }; }, { url : \"/api/*\" } ); // Conditional responses based on request const tap = mock. taps . inject ( ( request ) => { // Return error for URLs containing 'error' if (request. url . includes ( 'error' )) { return { response : { error : \"Something went wrong\" }, statusCode : 500 }; } // Return success for everything else return { response : { status : \"success\" }, statusCode : 200 }; }); // Dynamic headers based on request const tap = mock. taps . inject ( ( request ) => ({ response : \"OK\" , statusCode : 200 , headers : { \"X-Original-Method\" : request. method , \"X-Original-URL\" : request. url , \"X-Original-Host\" : request. hostname } }), { url : \"/api/mirror\" } );","url":"/docs/taps/#dynamic-function-response"},{"id":"/docs/bins/","title":"Bins","titles":[],"text":"Bins are ephemeral URL endpoints that capture incoming HTTP requests so you can inspect them later. They're the inverse of Taps: instead of injecting a response, they record everything they receive. Useful for: Debugging webhooks — point Stripe / GitHub / Slack at a bin URL and see exactly what they send Exercising client SDKs — verify your SDK sends the request shape you expect Recording fixtures — capture real traffic to replay in tests later There are two URL prefixes: /bins — JSON management API: create, list, inspect, delete bins /b/:id — the capture URL. Any HTTP method, any sub-path, any body sent here is stored against bin :id","url":"/docs/bins/"},{"id":"/docs/bins/#quick-start","title":"Quick Start","titles":["Bins"],"text":"# 1. create a bin curl -s -X POST http://localhost:3000/bins # → { \"id\": \"abc123def456\", \"url\": \"http://localhost:3000/b/abc123def456\", # \"createdAt\": \"2026-05-18T12:00:00.000Z\", # \"expiresAt\": \"2026-05-19T12:00:00.000Z\", # \"requestCount\": 0 } # 2. send anything to the capture URL curl -X POST \"http://localhost:3000/b/abc123def456/webhook?source=stripe\" \\ -H 'content-type: application/json' \\ -d '{\"event\":\"payment.succeeded\"}' # → { \"ok\": true, \"binId\": \"abc123def456\", \"requestId\": \"f9c2e1a40b3d\" } # 3. list captured requests (newest first) curl http://localhost:3000/bins/abc123def456/requests","url":"/docs/bins/#quick-start"},{"id":"/docs/bins/#endpoints","title":"Endpoints","titles":["Bins"],"text":"Method Path Description POST /bins Create a new bin GET /bins List all active bins GET /bins/:id Get bin metadata GET /bins/:id/requests List captured requests (newest first) GET /bins/:id/requests/:reqId Get a single captured request DELETE /bins/:id/requests Clear all captured requests in a bin DELETE /bins/:id Delete a bin ANY /b/:id and /b/:id/* Capture requests sent to a bin","url":"/docs/bins/#endpoints"},{"id":"/docs/bins/#end-to-end-webhook-debugging-example","title":"End-to-End Webhook Debugging Example","titles":["Bins"],"text":"A complete walkthrough using curl: BASE=http://localhost:3000 # Create the bin and grab its id ID=$(curl -s -X POST $BASE /bins | jq -r . id ) echo \"Bin URL: $BASE /b/ $ID \" # Simulate a Stripe webhook curl -s -X POST \" $BASE /b/ $ID /stripe/events?secret=whsec_test\" \\ -H 'content-type: application/json' \\ -H 'stripe-signature: t=1700000000,v1=abc123' \\ -d '{\"id\":\"evt_1\",\"type\":\"payment_intent.succeeded\",\"data\":{\"object\":{\"amount\":2000}}}' # Simulate a GitHub webhook curl -s -X POST \" $BASE /b/ $ID /github\" \\ -H 'content-type: application/json' \\ -H 'x-github-event: pull_request' \\ -d '{\"action\":\"opened\",\"number\":42}' # Inspect everything that arrived curl -s \" $BASE /bins/ $ID /requests\" | jq # Drill into the most recent one RID=$(curl -s \" $BASE /bins/ $ID /requests\" | jq -r '.requests[0].id' ) curl -s \" $BASE /bins/ $ID /requests/ $RID \" | jq # { # \"id\": \"f9c2e1a40b3d\", # \"binId\": \"abc123def456\", # \"method\": \"POST\", # \"url\": \"/github\", # \"path\": \"/github\", # \"query\": {}, # \"headers\": { # \"host\": \"localhost:3000\", # \"content-type\": \"application/json\", # \"x-github-event\": \"pull_request\" # }, # \"remoteAddress\": \"127.0.0.1\", # \"contentType\": \"application/json\", # \"bodySize\": 32, # \"body\": \"{\\\"action\\\":\\\"opened\\\",\\\"number\\\":42}\", # \"bodyEncoding\": \"utf8\", # \"truncated\": false, # \"capturedAt\": \"2026-05-18T12:00:01.234Z\" # } # Clean up curl -s -X DELETE \" $BASE /bins/ $ID /requests\" # clear captures, keep the bin curl -s -X DELETE \" $BASE /bins/ $ID \" # delete the bin entirely","url":"/docs/bins/#end-to-end-webhook-debugging-example"},{"id":"/docs/bins/#captured-request-shape","title":"Captured Request Shape","titles":["Bins"],"text":"{ \"id\" : \"f9c2e1a40b3d\" , \"binId\" : \"abc123def456\" , \"method\" : \"POST\" , \"url\" : \"/webhook?source=stripe\" , \"path\" : \"/webhook\" , \"query\" : { \"source\" : \"stripe\" } , \"headers\" : { \"content-type\" : \"application/json\" , \"...\" : \"...\" } , \"remoteAddress\" : \"127.0.0.1\" , \"contentType\" : \"application/json\" , \"bodySize\" : 32 , \"body\" : \"{\\\"event\\\":\\\"payment.succeeded\\\"}\" , \"bodyEncoding\" : \"utf8\" , \"truncated\" : false , \"capturedAt\" : \"2026-05-18T12:00:00.000Z\" } url is the request URL relative to the bin (everything after /b/:id ). path is the sub-path only, without the query string. bodyEncoding is \"utf8\" for text content types (text/*, application/json, application/xml, application/x-www-form-urlencoded, application/javascript), \"base64\" for everything else (binary payloads), or \"none\" when no body was sent. truncated is true when the body exceeded maxBodySize and was cut off. bodySize reflects the original length.","url":"/docs/bins/#captured-request-shape"},{"id":"/docs/bins/#body-encoding-examples","title":"Body Encoding Examples","titles":["Bins"],"text":"","url":"/docs/bins/#body-encoding-examples"},{"id":"/docs/bins/#text-content-utf-8","title":"Text Content (UTF-8)","titles":["Bins","Body Encoding Examples"],"text":"JSON, XML, form-encoded, plain text, and JavaScript are stored as UTF-8 strings so you can read them directly: curl -X POST \"http://localhost:3000/b/ $ID \" \\ -H 'content-type: application/json' \\ -d '{\"hello\":\"world\"}' curl -s \"http://localhost:3000/bins/ $ID /requests\" | jq '.requests[0] | {bodyEncoding, body}' # { # \"bodyEncoding\": \"utf8\", # \"body\": \"{\\\"hello\\\":\\\"world\\\"}\" # }","url":"/docs/bins/#text-content-utf-8"},{"id":"/docs/bins/#binary-content-base64","title":"Binary Content (Base64)","titles":["Bins","Body Encoding Examples"],"text":"Any non-text content type is base64-encoded, preserving the bytes exactly: # Upload a PNG to the bin curl -X POST \"http://localhost:3000/b/ $ID /upload\" \\ -H 'content-type: image/png' \\ --data-binary @logo.png curl -s \"http://localhost:3000/bins/ $ID /requests\" | jq '.requests[0] | {bodyEncoding, bodySize}' # { # \"bodyEncoding\": \"base64\", # \"bodySize\": 14823 # } # Decode the body back to bytes curl -s \"http://localhost:3000/bins/ $ID /requests\" \\ | jq -r '.requests[0].body' | base64 -d > recovered.png","url":"/docs/bins/#binary-content-base64"},{"id":"/docs/bins/#truncation","title":"Truncation","titles":["Bins","Body Encoding Examples"],"text":"Bodies larger than maxBodySize (1 MiB by default) are cut off and flagged: // In test setup import { MockHttp , BinManager } from '@jaredwray/mockhttp' ; const mock = new MockHttp (); mock. bins = new BinManager ({ maxBodySize : 1024 }); // 1 KiB cap await mock. start (); # Send 5000 bytes to a bin with a 1 KiB cap head -c 5000 /dev/urandom | curl -X POST \"http://localhost:3000/b/ $ID \" \\ -H 'content-type: application/octet-stream' \\ --data-binary @- curl -s \"http://localhost:3000/bins/ $ID /requests\" | jq '.requests[0] | {bodySize, truncated, body_len: (.body | length)}' # { # \"bodySize\": 5000, ← original size # \"truncated\": true, # \"body_len\": 1368 ← base64 of the first 1024 bytes # }","url":"/docs/bins/#truncation"},{"id":"/docs/bins/#fifo-eviction-example","title":"FIFO Eviction Example","titles":["Bins"],"text":"Once a bin reaches maxRequestsPerBin captures (100 by default), the oldest ones are dropped: # Send 105 requests for i in $( seq 1 105); do curl -s -X POST \"http://localhost:3000/b/ $ID /event/ $i \" > /dev/null done # The bin holds the most recent 100; the first 5 are gone curl -s \"http://localhost:3000/bins/ $ID /requests\" | jq '.requests | length' # 100 # Newest is at the top curl -s \"http://localhost:3000/bins/ $ID /requests\" | jq '.requests[0].path' # \"/event/105\"","url":"/docs/bins/#fifo-eviction-example"},{"id":"/docs/bins/#programmatic-access","title":"Programmatic Access","titles":["Bins"],"text":"The bin manager is exposed on the MockHttp instance as mock.bins . This makes it easy to drive bins from a test suite without going through HTTP: import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp ({ logging : false }); await mock. start (); // Create a bin const bin = mock. bins . createBin (); console . log ( `Webhook target: http://localhost: ${mock.port} /b/ ${bin.id} ` ); // ... point your code-under-test at that URL ... // Read captured requests (newest first) const requests = mock. bins . getRequests (bin. id ); console . log ( `Captured ${requests.length} requests` ); for ( const req of requests) { console . log ( ` ${req.method} ${req.path} ( ${req.bodySize} bytes)` ); } // Clean up mock. bins . deleteBin (bin. id ); await mock. close (); // also stops the bin cleanup timer","url":"/docs/bins/#programmatic-access"},{"id":"/docs/bins/#using-bins-in-a-vitest-test","title":"Using Bins in a Vitest Test","titles":["Bins","Programmatic Access"],"text":"import { afterAll, beforeAll, expect, test } from 'vitest' ; import { MockHttp } from '@jaredwray/mockhttp' ; let mock : MockHttp ; beforeAll ( async () => { mock = new MockHttp ({ logging : false }); await mock. start (); }); afterAll ( async () => { await mock. close (); }); test ( 'my SDK sends the right webhook payload' , async () => { const bin = mock. bins . createBin (); const webhookUrl = `http://localhost: ${mock.port} /b/ ${bin.id} ` ; // Drive your SDK at the bin await mySdk. notify (webhookUrl, { event : 'user.created' , id : 42 }); // Assert on what actually arrived const [captured] = mock. bins . getRequests (bin. id ); expect (captured. method ). toBe ( 'POST' ); expect (captured. contentType ). toBe ( 'application/json' ); expect ( JSON . parse (captured. body !)). toEqual ({ event : 'user.created' , id : 42 , }); expect (captured. headers [ 'x-signature' ]). toBeDefined (); });","url":"/docs/bins/#using-bins-in-a-vitest-test"},{"id":"/docs/bins/#configuration","title":"Configuration","titles":["Bins"],"text":"Bins are enabled by default. To disable the routes entirely: const mock = new MockHttp ({ httpBin : { bins : false }, }); To tune limits, replace the default BinManager before starting: import { MockHttp , BinManager } from '@jaredwray/mockhttp' ; const mock = new MockHttp (); mock. bins = new BinManager ({ defaultTtlMs : 60 * 60 * 1000 , // 1 hour (default: 24h) maxRequestsPerBin : 500 , // (default: 100) maxBodySize : 5 * 1024 * 1024 , // 5 MiB (default: 1 MiB) idLength : 16 , // (default: 12) cleanupIntervalMs : 30 * 1000 , // sweep every 30s (default: 60s) }); await mock. start ();","url":"/docs/bins/#configuration"},{"id":"/docs/bins/#defaults","title":"Defaults","titles":["Bins","Configuration"],"text":"Option Default Description defaultTtlMs 86400000 (24h) Bin lifetime. Expired bins return 404 and are lazily removed. maxRequestsPerBin 100 When exceeded, oldest captures are dropped (FIFO). maxBodySize 1048576 (1 MiB) Larger bodies are truncated; truncated: true is set on the capture. idLength 12 Length of generated bin and request ids. cleanupIntervalMs 60000 (1 min) How often expired bins are swept. The timer is unref() 'd so it never keeps the process alive.","url":"/docs/bins/#defaults"},{"id":"/docs/bins/#pluggable-storage","title":"Pluggable Storage","titles":["Bins","Configuration"],"text":"BinManager accepts a store: BinStore so you can plug in alternative backends (Redis, SQLite, etc.) without changing the rest of the codebase. The default InMemoryBinStore keeps state in process memory. import { BinManager , InMemoryBinStore , type Bin , type BinStore , type CapturedRequest , } from '@jaredwray/mockhttp' ; class RedisBinStore implements BinStore { createBin ( bin : Bin ): void { /* SET bin:${bin.id} ... */ } getBin ( id : string ): Bin | undefined { /* GET ... */ } listBins (): Bin [] { /* SCAN ... */ } deleteBin ( id : string ): boolean { /* DEL ... */ } addRequest ( binId : string , req : CapturedRequest , max : number ): void { /* LPUSH bin:${binId}:requests + LTRIM to max */ } getRequests ( binId : string ): CapturedRequest [] { /* LRANGE ... */ } getRequest ( binId : string , reqId : string ): CapturedRequest | undefined { /* ... */ } clearRequests ( binId : string ): void { /* DEL bin:${binId}:requests */ } cleanupExpired ( now : number ): string [] { /* scan + delete */ return []; } } mock. bins = new BinManager ({ store : new RedisBinStore () });","url":"/docs/bins/#pluggable-storage"},{"id":"/docs/configuration/","title":"Configuration","titles":[],"text":"MockHttp supports rate limiting using @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.","url":"/docs/configuration/"},{"id":"/docs/configuration/#default-rate-limiting","title":"Default Rate Limiting","titles":["Configuration"],"text":"By default, MockHttp applies the following rate limit: 1000 requests per minute per IP address Localhost is excluded - requests from 127.0.0.1 and ::1 bypass rate limiting (ideal for local development and testing) import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp (); await mock. start (); // Rate limiting is active (1000 req/min) except for localhost","url":"/docs/configuration/#default-rate-limiting"},{"id":"/docs/configuration/#customizing-rate-limiting","title":"Customizing Rate Limiting","titles":["Configuration"],"text":"To customize rate limiting, pass a rateLimit configuration object when creating your MockHttp instance: import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp ({ rateLimit : { max : 100 , // Maximum 100 requests timeWindow : '1 minute' // Per 1 minute window } }); await mock. start ();","url":"/docs/configuration/#customizing-rate-limiting"},{"id":"/docs/configuration/#common-configuration-options","title":"Common Configuration Options","titles":["Configuration"],"text":"The rateLimit option accepts all @fastify/rate-limit options :","url":"/docs/configuration/#common-configuration-options"},{"id":"/docs/configuration/#basic-rate-limiting","title":"Basic Rate Limiting","titles":["Configuration","Common Configuration Options"],"text":"// Limit to 50 requests per minute const mock = new MockHttp ({ rateLimit : { max : 50 , timeWindow : '1 minute' } });","url":"/docs/configuration/#basic-rate-limiting"},{"id":"/docs/configuration/#stricter-limits-with-custom-error-response","title":"Stricter Limits with Custom Error Response","titles":["Configuration","Common Configuration Options"],"text":"const mock = new MockHttp ({ rateLimit : { max : 30 , timeWindow : 60000 , // 1 minute in milliseconds errorResponseBuilder : ( req, context ) => ({ statusCode : 429 , error : 'Too Many Requests' , message : `Rate limit exceeded. Try again in ${context.after} ` }) } });","url":"/docs/configuration/#stricter-limits-with-custom-error-response"},{"id":"/docs/configuration/#allow-list-exclude-specific-ips","title":"Allow List (Exclude Specific IPs)","titles":["Configuration","Common Configuration Options"],"text":"const mock = new MockHttp ({ rateLimit : { max : 100 , timeWindow : '1 minute' , allowList : [ '127.0.0.1' , '192.168.1.100' ] // These IPs bypass rate limiting } });","url":"/docs/configuration/#allow-list-exclude-specific-ips"},{"id":"/docs/configuration/#custom-key-generator-rate-limit-by-header","title":"Custom Key Generator (Rate Limit by Header)","titles":["Configuration","Common Configuration Options"],"text":"const mock = new MockHttp ({ rateLimit : { max : 100 , timeWindow : '1 minute' , keyGenerator : ( request ) => { // Rate limit by API key instead of IP return request. headers [ 'x-api-key' ] || request. ip ; } } });","url":"/docs/configuration/#custom-key-generator-rate-limit-by-header"},{"id":"/docs/configuration/#advanced-configuration","title":"Advanced Configuration","titles":["Configuration","Common Configuration Options"],"text":"const mock = new MockHttp ({ rateLimit : { global : true , // Apply to all routes max : 100 , // Max requests timeWindow : '1 minute' , // Time window cache : 10000 , // Cache size for tracking clients skipOnError : false , // Don't skip on storage errors ban : 10 , // Ban after 10 rate limit violations continueExceeding : false , // Don't reset window on each request enableDraftSpec : true , // Use IETF draft spec headers addHeaders : { // Customize rate limit headers 'x-ratelimit-limit' : true , 'x-ratelimit-remaining' : true , 'x-ratelimit-reset' : true } } });","url":"/docs/configuration/#advanced-configuration"},{"id":"/docs/configuration/#disabling-rate-limiting","title":"Disabling Rate Limiting","titles":["Configuration"],"text":"To disable rate limiting completely, set the rateLimit option to false : const mock = new MockHttp ({ rateLimit : false // Completely disable rate limiting }); await mock. start (); // No rate limiting is applied to any requests Note: To change rate limiting settings after the server has started, you must restart the server: const mock = new MockHttp (); await mock. start (); // Starts with default rate limiting // To change or disable rate limiting: await mock. close (); mock. rateLimit = undefined ; // or set new options await mock. start (); // Restarts with new settings","url":"/docs/configuration/#disabling-rate-limiting"},{"id":"/docs/configuration/#available-options","title":"Available Options","titles":["Configuration"],"text":"Option Type Default Description max number | function 1000 Maximum requests per time window timeWindow number | string 60000 Duration of rate limit window (milliseconds or string like '1 minute') cache number 5000 LRU cache size for tracking clients allowList array | function [] IPs or function to exclude from rate limiting keyGenerator function IP-based Function to generate unique client identifier errorResponseBuilder function Default 429 Custom error response function skipOnError boolean false Skip rate limiting if storage errors occur ban number -1 Ban client after N violations (disabled by default) continueExceeding boolean false Renew time window on each request while limited enableDraftSpec boolean false Use IETF draft specification headers For the complete list of options, see the @fastify/rate-limit documentation .","url":"/docs/configuration/#available-options"},{"id":"/docs/configuration/#logging","title":"Logging","titles":["Configuration"],"text":"MockHttp uses Pino for logging via Fastify's built-in logger. Logging is enabled by default but can be disabled when needed.","url":"/docs/configuration/#logging"},{"id":"/docs/configuration/#disabling-logging","title":"Disabling Logging","titles":["Configuration","Logging"],"text":"import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp ({ logging : false }); await mock. start (); // Server runs silently without any log output You can also disable logging via the LOGGING environment variable: LOGGING= false node your-app.js","url":"/docs/configuration/#disabling-logging"},{"id":"/docs/configuration/#flexible-url-matching","title":"Flexible URL Matching","titles":["Configuration"],"text":"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. For example, all of these are served by /status/:code : GET /status/429 GET /status/429/ GET /status/429/foo GET /status/429/foo/bar 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.","url":"/docs/configuration/#flexible-url-matching"},{"id":"/docs/library/","title":"Library API","titles":[],"text":"","url":"/docs/library/"},{"id":"/docs/library/#mockhttp-class","title":"MockHttp Class","titles":["Library API"],"text":"","url":"/docs/library/#mockhttp-class"},{"id":"/docs/library/#constructor","title":"Constructor","titles":["Library API","MockHttp Class"],"text":"new MockHttp (options?) Parameters: options? (MockHttpOptions): port? : number - The port to listen on (default: 3000) host? : string - The host to listen on (default: '0.0.0.0') autoDetectPort? : boolean - Auto-detect next available port if in use (default: true) helmet? : boolean - Use Helmet for security headers (default: true) apiDocs? : boolean - Serve the Docula documentation site and OpenAPI spec (default: true) siteDistPath? : string - Path to the built Docula site (default: the package site/dist directory) rateLimit? : RateLimitPluginOptions - Configure rate limiting (default: 1000 req/min, localhost excluded) logging? : boolean - Enable logging (default: true) staticFiles? : boolean - Serve files from the package public/ directory (default: true) pluginTimeout? : number - Fastify plugin boot timeout in milliseconds; 0 disables it (default: Fastify's timeout) startBins? : boolean - Start the request-bin cleanup timer during initialize() (default: true) httpBin? : HttpBinOptions - Configure which httpbin routes to enable httpMethods? : boolean - Enable HTTP method routes (default: true) redirects? : boolean - Enable redirect routes (default: true) requestInspection? : boolean - Enable request inspection routes (default: true) responseInspection? : boolean - Enable response inspection routes (default: true) statusCodes? : boolean - Enable status code routes (default: true) responseFormats? : boolean - Enable response format routes (default: true) cookies? : boolean - Enable cookie routes (default: true) anything? : boolean - Enable anything routes (default: true) auth? : boolean - Enable authentication routes (default: true) images? : boolean - Enable image routes (default: true) bins? : boolean - Enable request bin routes /bins and /b/:id (default: true) https? : boolean | HttpsOptions - Enable HTTPS with auto-generated or custom certificates (default: undefined/disabled) http2? : boolean - Enable HTTP/2 support (default: false) http1? : boolean - Allow HTTP/1.1 fallback when using HTTP/2 with HTTPS (default: true) hookOptions? : HookifiedOptions - Hookified options","url":"/docs/library/#constructor"},{"id":"/docs/library/#properties","title":"Properties","titles":["Library API","MockHttp Class"],"text":"port : number - Get/set the server port host : string - Get/set the server host autoDetectPort : boolean - Get/set auto-detect port behavior helmet : boolean - Get/set Helmet security headers apiDocs : boolean - Get/set whether the documentation site and OpenAPI spec are served siteDistPath : string - Get/set the path to the built Docula site logging : boolean - Get/set logging enabled state staticFiles : boolean - Get/set whether files from public/ are served pluginTimeout : number | undefined - Get/set Fastify plugin boot timeout startBins : boolean - Get/set whether bin cleanup starts during initialize() rateLimit : RateLimitPluginOptions | undefined - Get/set rate limiting options httpBin : HttpBinOptions - Get/set httpbin route options https : HttpsOptions | undefined - Get/set HTTPS configuration isHttps : boolean - Whether the server is running with HTTPS http2 : boolean - Get/set HTTP/2 support http1 : boolean - Get/set HTTP/1.1 fallback for HTTP/2 with HTTPS server : FastifyInstance - Get/set the Fastify server instance taps : TapManager - Get/set the TapManager instance bins : BinManager - Get/set the BinManager instance for request bins","url":"/docs/library/#properties"},{"id":"/docs/library/#methods","title":"Methods","titles":["Library API","MockHttp Class"],"text":"","url":"/docs/library/#methods"},{"id":"/docs/library/#async-initialize","title":"async initialize()","titles":["Library API","MockHttp Class","Methods"],"text":"Register plugins and routes without listening. Use server.inject() afterwards, or call start() to bind a port.","url":"/docs/library/#async-initialize"},{"id":"/docs/library/#async-start","title":"async start()","titles":["Library API","MockHttp Class","Methods"],"text":"Start the Fastify server. If already running, it will be closed and restarted.","url":"/docs/library/#async-start"},{"id":"/docs/library/#async-close","title":"async close()","titles":["Library API","MockHttp Class","Methods"],"text":"Stop the Fastify server.","url":"/docs/library/#async-close"},{"id":"/docs/library/#async-detectport","title":"async detectPort()","titles":["Library API","MockHttp Class","Methods"],"text":"Detect the next available port. Returns: number - The available port","url":"/docs/library/#async-detectport"},{"id":"/docs/library/#async-registerapidocsfastifyinstance","title":"async registerApiDocs(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register OpenAPI generation and the Docula documentation site.","url":"/docs/library/#async-registerapidocsfastifyinstance"},{"id":"/docs/library/#async-registerswaggerfastifyinstance","title":"async registerSwagger(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register @fastify/swagger and the live /openapi.json spec route.","url":"/docs/library/#async-registerswaggerfastifyinstance"},{"id":"/docs/library/#async-registersitefastifyinstance","title":"async registerSite(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Serve the built Docula site from siteDistPath when the directory exists.","url":"/docs/library/#async-registersitefastifyinstance"},{"id":"/docs/library/#async-registerhttpmethodsfastifyinstance","title":"async registerHttpMethods(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register HTTP method routes (GET, POST, PUT, PATCH, DELETE).","url":"/docs/library/#async-registerhttpmethodsfastifyinstance"},{"id":"/docs/library/#async-registerstatuscoderoutesfastifyinstance","title":"async registerStatusCodeRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register status code routes.","url":"/docs/library/#async-registerstatuscoderoutesfastifyinstance"},{"id":"/docs/library/#async-registerrequestinspectionroutesfastifyinstance","title":"async registerRequestInspectionRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register request inspection routes (headers, ip, user-agent).","url":"/docs/library/#async-registerrequestinspectionroutesfastifyinstance"},{"id":"/docs/library/#async-registerresponseinspectionroutesfastifyinstance","title":"async registerResponseInspectionRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register response inspection routes (cache, etag, response-headers).","url":"/docs/library/#async-registerresponseinspectionroutesfastifyinstance"},{"id":"/docs/library/#async-registerresponseformatroutesfastifyinstance","title":"async registerResponseFormatRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register response format routes (json, xml, html, etc.).","url":"/docs/library/#async-registerresponseformatroutesfastifyinstance"},{"id":"/docs/library/#async-registerredirectroutesfastifyinstance","title":"async registerRedirectRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register redirect routes (absolute, relative, redirect-to).","url":"/docs/library/#async-registerredirectroutesfastifyinstance"},{"id":"/docs/library/#async-registercookieroutesfastifyinstance","title":"async registerCookieRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register cookie routes (get, set, delete).","url":"/docs/library/#async-registercookieroutesfastifyinstance"},{"id":"/docs/library/#async-registeranythingroutesfastifyinstance","title":"async registerAnythingRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register \"anything\" catch-all routes.","url":"/docs/library/#async-registeranythingroutesfastifyinstance"},{"id":"/docs/library/#async-registerauthroutesfastifyinstance","title":"async registerAuthRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register authentication routes (basic, bearer, digest, hidden-basic).","url":"/docs/library/#async-registerauthroutesfastifyinstance"},{"id":"/docs/library/#async-registerimageroutesfastifyinstance","title":"async registerImageRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register image routes (jpeg, png, svg, webp) with content negotiation support.","url":"/docs/library/#async-registerimageroutesfastifyinstance"},{"id":"/docs/library/#async-registerbinroutesfastifyinstance","title":"async registerBinRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register the request bin routes — management at /bins and capture at /b/:id .","url":"/docs/library/#async-registerbinroutesfastifyinstance"},{"id":"/docs/library/#bins-request-capture","title":"Bins (Request Capture)","titles":["Library API"],"text":"Access the BinManager via mockHttp.bins to manage request bins programmatically. See Request Bins for usage examples.","url":"/docs/library/#bins-request-capture"},{"id":"/docs/library/#binscreatebin","title":"bins.createBin()","titles":["Library API","Bins (Request Capture)"],"text":"Create a new bin with the configured TTL. Returns: Bin — { id, createdAt, expiresAt, requestCount }","url":"/docs/library/#binscreatebin"},{"id":"/docs/library/#binsgetbinid","title":"bins.getBin(id)","titles":["Library API","Bins (Request Capture)"],"text":"Look up a bin by id. Returns undefined if the bin does not exist or has expired (and lazily removes the expired entry). Returns: Bin | undefined","url":"/docs/library/#binsgetbinid"},{"id":"/docs/library/#binslistbins","title":"bins.listBins()","titles":["Library API","Bins (Request Capture)"],"text":"List all non-expired bins. Returns: Bin[]","url":"/docs/library/#binslistbins"},{"id":"/docs/library/#binsdeletebinid","title":"bins.deleteBin(id)","titles":["Library API","Bins (Request Capture)"],"text":"Delete a bin and all its captured requests. Returns: boolean — true if the bin existed","url":"/docs/library/#binsdeletebinid"},{"id":"/docs/library/#binsgetrequestsbinid","title":"bins.getRequests(binId)","titles":["Library API","Bins (Request Capture)"],"text":"List captured requests for a bin, newest first. Returns: CapturedRequest[]","url":"/docs/library/#binsgetrequestsbinid"},{"id":"/docs/library/#binsgetrequestbinid-reqid","title":"bins.getRequest(binId, reqId)","titles":["Library API","Bins (Request Capture)"],"text":"Look up a single captured request. Returns: CapturedRequest | undefined","url":"/docs/library/#binsgetrequestbinid-reqid"},{"id":"/docs/library/#binsclearrequestsbinid","title":"bins.clearRequests(binId)","titles":["Library API","Bins (Request Capture)"],"text":"Clear all captured requests in a bin (the bin itself is preserved).","url":"/docs/library/#binsclearrequestsbinid"},{"id":"/docs/library/#binsrecordrequestbinid-raw","title":"bins.recordRequest(binId, raw)","titles":["Library API","Bins (Request Capture)"],"text":"Manually record a captured request. Returns undefined if the bin does not exist or is expired. Normally invoked by the capture route, but available for programmatic use. Returns: CapturedRequest | undefined","url":"/docs/library/#binsrecordrequestbinid-raw"},{"id":"/docs/library/#binsstart--binsstop","title":"bins.start() / bins.stop()","titles":["Library API","Bins (Request Capture)"],"text":"Start or stop the periodic cleanup of expired bins. MockHttp.start() and MockHttp.close() call these automatically. The interval is unref() 'd so it never keeps the Node process alive.","url":"/docs/library/#binsstart--binsstop"},{"id":"/docs/library/#binsmaxbodysize--binsmaxrequestsperbin--binsdefaultttlms","title":"bins.maxBodySize / bins.maxRequestsPerBin / bins.defaultTtlMs","titles":["Library API","Bins (Request Capture)"],"text":"Read-only getters for the currently-configured limits.","url":"/docs/library/#binsmaxbodysize--binsmaxrequestsperbin--binsdefaultttlms"},{"id":"/docs/library/#taps-response-injection","title":"Taps (Response Injection)","titles":["Library API"],"text":"Access the TapManager via mockHttp.taps to inject custom responses.","url":"/docs/library/#taps-response-injection"},{"id":"/docs/library/#tapsinjectresponse-matcher","title":"taps.inject(response, matcher?)","titles":["Library API","Taps (Response Injection)"],"text":"Injects a custom response for requests matching the criteria. Parameters: response (InjectionResponse | InjectionResponseFunction): Static Response (InjectionResponse): response : string | object | Buffer - The response body statusCode? : number - HTTP status code (default: 200) headers? : object - Response headers Function Response (InjectionResponseFunction): A function that receives the Fastify request object and returns an InjectionResponse (request: FastifyRequest) => InjectionResponse Allows dynamic response generation based on request properties (url, method, headers, etc.) matcher? (InjectionMatcher) - Optional matching criteria: url? : string - URL path (supports wildcards with * ) method? : string - HTTP method (GET, POST, etc.) hostname? : string - Hostname to match headers? : object - Headers that must be present Returns: InjectionTap - A tap object with a unique id that can be used to remove the injection","url":"/docs/library/#tapsinjectresponse-matcher"},{"id":"/docs/library/#tapsremoveinjectiontaporid","title":"taps.removeInjection(tapOrId)","titles":["Library API"],"text":"Removes an injection. Parameters: tapOrId : InjectionTap | string - The tap object or tap ID to remove Returns: boolean - true if removed, false if not found","url":"/docs/library/#tapsremoveinjectiontaporid"},{"id":"/docs/library/#tapsinjections","title":"taps.injections","titles":["Library API","taps.removeInjection(tapOrId)"],"text":"A getter that returns a Map of all active injection taps. Returns: Map<string, InjectionTap> - Map of all active injections with tap IDs as keys","url":"/docs/library/#tapsinjections"},{"id":"/docs/library/#tapsclear","title":"taps.clear()","titles":["Library API"],"text":"Removes all injections.","url":"/docs/library/#tapsclear"},{"id":"/docs/library/#tapshasinjections","title":"taps.hasInjections","titles":["Library API"],"text":"A getter that returns whether there are any active injections. Returns: boolean - true if there are active injections, false otherwise","url":"/docs/library/#tapshasinjections"},{"id":"/docs/hosted/","title":"Hosted Service","titles":[],"text":"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. Getting Started is served at / and /docs , other guides at /docs/... , and the interactive HTTP API reference at /api . Mock endpoints such as /get and /post are unchanged.","url":"/docs/hosted/"},{"id":"/changelog/v2-0-0/","title":"v2.0.0","titles":[],"text":"","url":"/changelog/v2-0-0/"},{"id":"/changelog/v2-0-0/#jaredwraymockhttp200--2026-09-18","title":"@jaredwray/mockhttp@2.0.0 — 2026-09-18","titles":["v2.0.0"],"text":"Replace Scalar with a Docula site, run mockhttp.org on a Worker, and add initialize().","url":"/changelog/v2-0-0/#jaredwraymockhttp200--2026-09-18"},{"id":"/changelog/v2-0-0/#features","title":"Features","titles":["v2.0.0","@jaredwray/mockhttp@2.0.0 — 2026-09-18"],"text":"replace Scalar with a Docula documentation site (#209) # Before 1.10.0 After 1.10.0 GET / → Scalar UI Docula Getting Started GET /docs → Swagger UI Docula docs GET /docs/json → OpenAPI JSON 404 GET /api/ → (none) Interactive OpenAPI GET /openapi.json → (none) Live OpenAPI spec GET /get → unchanged unchanged migrate production deploy from GCP Cloud Run to Cloudflare Containers (#207) run mockhttp.org on a Cloudflare Worker only (#218) const mock = new MockHttp ({ logging : false , autoDetectPort : false , staticFiles : false , pluginTimeout : 0 , startBins : false , }); await mock. initialize (); // register routes without listen() const response = await mock. server . inject ({ method : \"GET\" , url : \"/get\" }); use the Docula docs index as the homepage (#219)","url":"/changelog/v2-0-0/#features"},{"id":"/changelog/v2-0-0/#internal","title":"Internal","titles":["v2.0.0","@jaredwray/mockhttp@2.0.0 — 2026-09-18"],"text":"lower Cloudflare Containers max instances to 3 (#208) upgrade @biomejs/biome 2.5.8 → 2.5.13, vitest 4.1.10 → 5.0.0 (#210) upgrade @swc/core 1.15.47 → 1.16.2, tsdown 0.22.14 → 0.23.0, tsx 4.23.12 → 4.23.13 (#211) upgrade package manager pnpm 11.21.0 → 12.4.1 (#212) upgrade GitHub Actions (codecov, CodeQL, zizmor, Socket Firewall) (#213) pin Dev Container image to javascript-node 5.2.1-24-trixie (#214) upgrade fastify 5.11.3 → 5.12.4, @fastify/helmet 13.1.0 → 13.1.1 (#215) upgrade hookified 3.0.2 → 3.0.3 (#216) pin Docker Node.js runtime image to node:24.20.0-alpine3.24 (#217)","url":"/changelog/v2-0-0/#internal"},{"id":"/changelog/v2-0-0/#contributors","title":"Contributors","titles":["v2.0.0","@jaredwray/mockhttp@2.0.0 — 2026-09-18"],"text":"@jaredwray (13)","url":"/changelog/v2-0-0/#contributors"},{"id":"/changelog/v2-0-0/#full-list-of-changes","title":"Full List of Changes","titles":["v2.0.0","@jaredwray/mockhttp@2.0.0 — 2026-09-18"],"text":"Migrate production deploy from GCP Cloud Run to Cloudflare Containers by @jaredwray in #207 Lower Cloudflare Containers max instances to 3 by @jaredwray in #208 Replace Scalar with a Docula documentation site by @jaredwray in #209 root - chore: upgrade code quality dependencies by @jaredwray in #210 root - chore: upgrade TypeScript and build tooling by @jaredwray in #211 root - chore: upgrade package manager by @jaredwray in #212 root - chore: upgrade GitHub Actions by @jaredwray in #213 root - chore: pin Dev Container images by @jaredwray in #214 root - chore: upgrade fastify dependencies by @jaredwray in #215 root - chore: upgrade hookified by @jaredwray in #216 root - chore: upgrade Docker Node.js runtime image by @jaredwray in #217 Run mockhttp.org on a Cloudflare Worker only by @jaredwray in #218 Use the Docula docs index as the homepage by @jaredwray in #219 Full diff: https://github.com/jaredwray/mockhttp/compare/v1.9.0...v1.10.0","url":"/changelog/v2-0-0/#full-list-of-changes"},{"id":"/changelog/v1-9-0/","title":"v1.9.0","titles":[],"text":"","url":"/changelog/v1-9-0/"},{"id":"/changelog/v1-9-0/#jaredwraymockhttp190--2026-08-19","title":"@jaredwray/mockhttp@1.9.0 — 2026-08-19","titles":["v1.9.0"],"text":"Stable indexed response-format templates, plus security hardening and dependency refreshes.","url":"/changelog/v1-9-0/#jaredwraymockhttp190--2026-08-19"},{"id":"/changelog/v1-9-0/#features","title":"Features","titles":["v1.9.0","@jaredwray/mockhttp@1.9.0 — 2026-08-19"],"text":"add stable response format output via optional template index (#181) # Same index → byte-identical JSON. Omit the index for the previous random pick. curl http://localhost:3000/json/1 curl http://localhost:3000/html/1 curl http://localhost:3000/json/99 # → 404 {\"error\":\"Template index must be between 1 and 5\"}","url":"/changelog/v1-9-0/#features"},{"id":"/changelog/v1-9-0/#bug-fixes","title":"Bug Fixes","titles":["v1.9.0","@jaredwray/mockhttp@1.9.0 — 2026-08-19"],"text":"clone JSON template per request to protect stable output (#181)","url":"/changelog/v1-9-0/#bug-fixes"},{"id":"/changelog/v1-9-0/#internal","title":"Internal","titles":["v1.9.0","@jaredwray/mockhttp@1.9.0 — 2026-08-19"],"text":"assert trailing-slash index requests fail loudly with 404 (#181) land security docs through zizmor (#182) stage npm publishes instead of publishing live (#190) gate staged publishes on Aikido scan-release (#191) prefer tilde ranges for runtime deps (#192) record repository lockdown (#193) remove set-cookie-parser override (#194) remove @ungap/structured-clone override (#195) remove glob override (#196) upgrade @biomejs/biome 2.5.3 → 2.5.8 (#197) upgrade TypeScript 6.0.3 → 7.0.2, tsdown 0.22.2 → 0.22.14, tsx 4.23.0 → 4.23.12, @swc/core 1.15.43 → 1.15.47 (#198) upgrade package manager pnpm 11.20.0 → 11.21.0 (#200) upgrade fastify 5.10.0 → 5.11.3, @fastify/cookie, @fastify/rate-limit, @fastify/static, @fastify/swagger, @fastify/swagger-ui (#201) upgrade @scalar/api-reference 1.62.5 → 1.64.1 (#202) upgrade hookified 3.0.1 → 3.0.2 (#203) prefer caret ranges over tilde (#204) pin Docker Node.js runtime image to node:24.19.0-alpine3.24 (#205)","url":"/changelog/v1-9-0/#internal"},{"id":"/changelog/v1-9-0/#contributors","title":"Contributors","titles":["v1.9.0","@jaredwray/mockhttp@1.9.0 — 2026-08-19"],"text":"@jaredwray (15)","url":"/changelog/v1-9-0/#contributors"},{"id":"/changelog/v1-9-0/#full-list-of-changes","title":"Full List of Changes","titles":["v1.9.0","@jaredwray/mockhttp@1.9.0 — 2026-08-19"],"text":"feat: add stable response format output via optional template index by @jaredwray in #181 mockhttp - chore: defense - land security docs through zizmor by @jaredwray in #182 mockhttp - chore: defense - stage npm publishes instead of publishing live by @jaredwray in #190 mockhttp - chore: defense - gate staged publishes on Aikido scan-release by @jaredwray in #191 mockhttp - chore: defense - prefer tilde ranges for runtime deps by @jaredwray in #192 mockhttp - chore: defense - record repository lockdown by @jaredwray in #193 root - chore: remove set-cookie-parser override by @jaredwray in #194 root - chore: remove @ungap/structured-clone override by @jaredwray in #195 root - chore: remove glob override by @jaredwray in #196 root - chore: upgrade code quality dependencies by @jaredwray in #197 root - chore: upgrade TypeScript and build tooling by @jaredwray in #198 root - chore: upgrade package manager by @jaredwray in #200 root - chore: upgrade fastify dependencies by @jaredwray in #201 root - chore: upgrade @scalar/api-reference by @jaredwray in #202 root - chore: upgrade hookified by @jaredwray in #203 root - chore: defense - prefer caret ranges over tilde by @jaredwray in #204 root - chore: upgrade Docker Node.js runtime image by @jaredwray in #205 Full diff: https://github.com/jaredwray/mockhttp/compare/v1.8.1...v1.9.0","url":"/changelog/v1-9-0/#full-list-of-changes"},{"id":"/changelog/v1-8-1/","title":"v1.8.1","titles":[],"text":"","url":"/changelog/v1-8-1/"},{"id":"/changelog/v1-8-1/#jaredwraymockhttp181--2026-07-18","title":"@jaredwray/mockhttp@1.8.1 — 2026-07-18","titles":["v1.8.1"],"text":"Dependency maintenance: refresh runtime and build dependencies (incl. @fastify/static v10).","url":"/changelog/v1-8-1/#jaredwraymockhttp181--2026-07-18"},{"id":"/changelog/v1-8-1/#internal","title":"Internal","titles":["v1.8.1","@jaredwray/mockhttp@1.8.1 — 2026-07-18"],"text":"update fastify, @fastify/cookie, @fastify/helmet, @fastify/rate-limit, @fastify/swagger, @fastify/swagger-ui to latest ( 62d073a , #174) update @fastify/static to 10 (major) ( 71501e3 , #178) update @scalar/api-reference to latest ( 7efd744 , #176) update hookified to latest ( f46b91a , #177) update @biomejs/biome, @swc/core, tsx to latest ( 68584a6 , #175) update test tooling — vitest, @vitest/coverage-v8 ( c3461d3 , #166)","url":"/changelog/v1-8-1/#internal"},{"id":"/changelog/v1-8-1/#contributors","title":"Contributors","titles":["v1.8.1","@jaredwray/mockhttp@1.8.1 — 2026-07-18"],"text":"@jaredwray (6)","url":"/changelog/v1-8-1/#contributors"},{"id":"/changelog/v1-8-1/#full-list-of-changes","title":"Full List of Changes","titles":["v1.8.1","@jaredwray/mockhttp@1.8.1 — 2026-07-18"],"text":"chore: update test tooling (vitest, @vitest/coverage-v8) by @jaredwray in #166 chore: update fastify, @fastify/cookie, @fastify/helmet, @fastify/rate-limit, @fastify/swagger, @fastify/swagger-ui to latest by @jaredwray in #174 chore: update @biomejs/biome, @swc/core, tsx to latest by @jaredwray in #175 chore: update @scalar/api-reference to latest by @jaredwray in #176 chore: update hookified to latest by @jaredwray in #177 chore: update @fastify/static to 10 (major) by @jaredwray in #178 Full diff: https://github.com/jaredwray/mockhttp/compare/v1.8.0...v1.8.1","url":"/changelog/v1-8-1/#full-list-of-changes"},{"id":"/changelog/v1-8-0/","title":"v1.8.0","titles":[],"text":"","url":"/changelog/v1-8-0/"},{"id":"/changelog/v1-8-0/#jaredwraymockhttp180--2026-06-18","title":"@jaredwray/mockhttp@1.8.0 — 2026-06-18","titles":["v1.8.0"],"text":"Add request bins for capturing and inspecting HTTP requests; refresh runtime and build dependencies.","url":"/changelog/v1-8-0/#jaredwraymockhttp180--2026-06-18"},{"id":"/changelog/v1-8-0/#features","title":"Features","titles":["v1.8.0","@jaredwray/mockhttp@1.8.0 — 2026-06-18"],"text":"add request bins for inspecting captured HTTP requests ( 41e3d20 , #150) Mint an ephemeral URL, send arbitrary requests to it, and read back what was captured — useful for webhook debugging. # Create a bin, send a request to it, then inspect what was captured ID=$(curl -s -X POST http://localhost:3000/bins | jq -r . id ) curl -X POST \"http://localhost:3000/b/ $ID /webhook?source=stripe\" \\ -H 'content-type: application/json' \\ -d '{\"event\":\"payment.succeeded\"}' curl \"http://localhost:3000/bins/ $ID /requests\" | jq","url":"/changelog/v1-8-0/#features"},{"id":"/changelog/v1-8-0/#documentation","title":"Documentation","titles":["v1.8.0","@jaredwray/mockhttp@1.8.0 — 2026-06-18"],"text":"expand Request Bins section with end-to-end examples and API reference ( c860005 , #150)","url":"/changelog/v1-8-0/#documentation"},{"id":"/changelog/v1-8-0/#internal","title":"Internal","titles":["v1.8.0","@jaredwray/mockhttp@1.8.0 — 2026-06-18"],"text":"cover MockHttp bin integration; harden against negative maxRequestsPerBin ( d6356c1 , #150) run deploy-site test and build in parallel, gate deploy on both ( 133115d , #149) upgrade hookified 2.2.0 → 3.0.0 ( 58e0717 , #157) upgrade @scalar/api-reference 1.55.3 → 1.59.3 ( 1209de0 , #156) upgrade @fastify/swagger-ui 5.2.6 → 6.0.0 ( b37285c , #155) upgrade @fastify/rate-limit 10.3.0 → 11.0.0 ( 3c7e14a , #154) upgrade GitHub Actions — checkout v7, codecov-action v7 ( 318c34a , #153) upgrade TypeScript and build tooling — @swc/core, tsx, tsdown ( c474f8d , #152) upgrade code quality dependencies — biome, vitest ( b06c1e6 , #151)","url":"/changelog/v1-8-0/#internal"},{"id":"/changelog/v1-8-0/#contributors","title":"Contributors","titles":["v1.8.0","@jaredwray/mockhttp@1.8.0 — 2026-06-18"],"text":"@jaredwray (11)","url":"/changelog/v1-8-0/#contributors"},{"id":"/changelog/v1-8-0/#full-list-of-changes","title":"Full List of Changes","titles":["v1.8.0","@jaredwray/mockhttp@1.8.0 — 2026-06-18"],"text":"ci(deploy-site): run test and build in parallel by @jaredwray in #149 feat: add request bins for inspecting captured HTTP requests by @jaredwray in #150 root - chore: upgrade code quality dependencies by @jaredwray in #151 root - chore: upgrade TypeScript and build tooling by @jaredwray in #152 root - chore: upgrade GitHub Actions (breaking) by @jaredwray in #153 root - chore: upgrade @fastify/rate-limit (breaking) by @jaredwray in #154 root - chore: upgrade @fastify/swagger-ui (breaking) by @jaredwray in #155 root - chore: upgrade @scalar/api-reference by @jaredwray in #156 root - chore: upgrade hookified (breaking) by @jaredwray in #157 Full diff: https://github.com/jaredwray/mockhttp/compare/v1.6.1...v1.7.0","url":"/changelog/v1-8-0/#full-list-of-changes"},{"id":"/changelog/v1-7-0/","title":"v1.7.0","titles":[],"text":"","url":"/changelog/v1-7-0/"},{"id":"/changelog/v1-7-0/#jaredwraymockhttp161--2026-05-18","title":"@jaredwray/mockhttp@1.6.1 — 2026-05-18","titles":["v1.7.0"],"text":"Routine maintenance: dependency refresh (fastify, @scalar/api-reference, hookified), pnpm 11 supply-chain baseline, and GitHub Actions major upgrades.","url":"/changelog/v1-7-0/#jaredwraymockhttp161--2026-05-18"},{"id":"/changelog/v1-7-0/#internal","title":"Internal","titles":["v1.7.0","@jaredwray/mockhttp@1.6.1 — 2026-05-18"],"text":"upgrade hookified 2.1.1 → 2.2.0 ( e431858 , #147) upgrade @scalar/api-reference 1.52.1 → 1.55.3 ( e07afea , #146) upgrade @fastify/static 9.1.0→9.1.3, @fastify/swagger-ui 5.2.5→5.2.6, fastify 5.8.4→5.8.5 ( bcfddf6 , #145) upgrade GitHub Actions to latest majors (checkout v6, setup-node v6, upload-artifact v7, download-artifact v8, codeql v4, etc.) ( a47cf91 , #144) bump engines.node to >=22.18.0 for tsdown 0.22.0 ( 5ab1512 , #143) upgrade TypeScript 6.0.2 → 6.0.3, tsdown 0.21.7 → 0.22.0, @swc/core 1.15.24 → 1.15.33 ( 5cef6c7 , #143) upgrade Biome 2.4.11 → 2.4.15 and Vitest 4.1.4 → 4.1.6 ( edfdf90 , #142) disable setup-node v5 package-manager-cache to fix corepack ordering ( 8bf7cd1 , #141) address review feedback on pnpm 11 upgrade ( ca65ce5 , #141) upgrade to pnpm 11 via corepack with defense-in-depth workspace baseline ( 1d93b64 , #141)","url":"/changelog/v1-7-0/#internal"},{"id":"/changelog/v1-7-0/#contributors","title":"Contributors","titles":["v1.7.0","@jaredwray/mockhttp@1.6.1 — 2026-05-18"],"text":"@jaredwray (10)","url":"/changelog/v1-7-0/#contributors"},{"id":"/changelog/v1-7-0/#full-list-of-changes","title":"Full List of Changes","titles":["v1.7.0","@jaredwray/mockhttp@1.6.1 — 2026-05-18"],"text":"chore: upgrade to pnpm 11 via corepack with defense-in-depth workspace by @jaredwray in #141 root - chore: upgrade code quality dependencies by @jaredwray in #142 root - chore: upgrade TypeScript and build tooling by @jaredwray in #143 root - chore: upgrade GitHub Actions (breaking) by @jaredwray in #144 root - chore: upgrade fastify dependencies by @jaredwray in #145 root - chore: upgrade @scalar/api-reference by @jaredwray in #146 root - chore: upgrade hookified by @jaredwray in #147 Full diff: https://github.com/jaredwray/mockhttp/compare/v1.6.0...v1.6.1","url":"/changelog/v1-7-0/#full-list-of-changes"},{"id":"/changelog/v1-6-0/","title":"v1.6.0","titles":[],"text":"","url":"/changelog/v1-6-0/"},{"id":"/changelog/v1-6-0/#jaredwraymockhttp160--2026-05-16","title":"@jaredwray/mockhttp@1.6.0 — 2026-05-16","titles":["v1.6.0"],"text":"Flexible URL matching: trailing path segments fall back to the parsable route prefix (fixes #137).","url":"/changelog/v1-6-0/#jaredwraymockhttp160--2026-05-16"},{"id":"/changelog/v1-6-0/#features","title":"Features","titles":["v1.6.0","@jaredwray/mockhttp@1.6.0 — 2026-05-16"],"text":"ignore trailing path segments after the parsable portion ( 6f82897 , #139) A Fastify rewriteUrl hook progressively strips trailing segments when only the static catch-all wildcard or nothing matches. Query strings are preserved and the first path segment is never stripped, so genuinely unknown URLs still 404. # Before — only an exact match worked: GET /status/429 → 429 GET /status/429/foo → 404 # After — trailing segments fall back to the parsable prefix: GET /status/429 → 429 GET /status/429/foo → 429 (served by /status/:code) GET /status/429/foo/bar/ → 429 GET /status/429?x=1 → 429 (query preserved) GET /totally/unknown → 404 (first segment never stripped)","url":"/changelog/v1-6-0/#features"},{"id":"/changelog/v1-6-0/#documentation","title":"Documentation","titles":["v1.6.0","@jaredwray/mockhttp@1.6.0 — 2026-05-16"],"text":"document flexible URL matching behavior in the README ( 148ed17 , #139)","url":"/changelog/v1-6-0/#documentation"},{"id":"/changelog/v1-6-0/#internal","title":"Internal","titles":["v1.6.0","@jaredwray/mockhttp@1.6.0 — 2026-05-16"],"text":"extract query string before initial route check; add trailing-slash path coverage ( 5f298ea , #139) fix typos in README and src/swagger.ts ( be2b014 , #138)","url":"/changelog/v1-6-0/#internal"},{"id":"/changelog/v1-6-0/#contributors","title":"Contributors","titles":["v1.6.0","@jaredwray/mockhttp@1.6.0 — 2026-05-16"],"text":"@jaredwray — #139 @mrazauskas — #138 (first contribution 🎉) Full diff: https://github.com/jaredwray/mockhttp/compare/v1.5.1...v1.6.0","url":"/changelog/v1-6-0/#contributors"},{"id":"/changelog/v1-5-1/","title":"v1.5.1","titles":[],"text":"","url":"/changelog/v1-5-1/"},{"id":"/changelog/v1-5-1/#whats-changed","title":"What's Changed","titles":["v1.5.1"],"text":"chore: upgrading biome, vitest, swc to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/130 chore: upgrading fastify to 5.8.4 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/131 chore: upgrading hookified to 2.1.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/132 chore: upgrading @scalar/api-reference to 1.52.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/133 chore: migrating from tsup to tsdown by @jaredwray in https://github.com/jaredwray/mockhttp/pull/134 chore: updating all github actions by @jaredwray in https://github.com/jaredwray/mockhttp/pull/135 fix: docker publish and updating tsdown by @jaredwray in https://github.com/jaredwray/mockhttp/pull/136 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.5.0...v1.5.1","url":"/changelog/v1-5-1/#whats-changed"},{"id":"/changelog/v1-5-0/","title":"v1.5.0","titles":[],"text":"","url":"/changelog/v1-5-0/"},{"id":"/changelog/v1-5-0/#whats-changed","title":"What's Changed","titles":["v1.5.0"],"text":"chore: upgrading swc, biome, vitest, and rimraf by @jaredwray in https://github.com/jaredwray/mockhttp/pull/127 chore: upgrading fastify and scalar by @jaredwray in https://github.com/jaredwray/mockhttp/pull/128 feat: adding in http2 support by @jaredwray in https://github.com/jaredwray/mockhttp/pull/129 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.4.0...v1.5.0","url":"/changelog/v1-5-0/#whats-changed"},{"id":"/changelog/v1-4-0/","title":"v1.4.0","titles":[],"text":"","url":"/changelog/v1-4-0/"},{"id":"/changelog/v1-4-0/#whats-changed","title":"What's Changed","titles":["v1.4.0"],"text":"chore: removing route export files from code coverage by @jaredwray in https://github.com/jaredwray/mockhttp/pull/117 chore: upgrading vitest and support modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/118 chore: upgrading fastify and supporting modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/119 chore: upgrading pino to 10.3.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/120 chore: upgrading hookified to 1.15.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/121 feat: adding mock certificate support for ssl testing by @jaredwray in https://github.com/jaredwray/mockhttp/pull/123 feat: adding mock certificate support for ssl testing by @jaredwray in https://github.com/jaredwray/mockhttp/pull/122 chore: getting test coverage back to normal levels by @jaredwray in https://github.com/jaredwray/mockhttp/pull/124 feat: adding in https support in docs by @jaredwray in https://github.com/jaredwray/mockhttp/pull/125 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.3.0...v1.4.0","url":"/changelog/v1-4-0/#whats-changed"},{"id":"/changelog/v1-3-0/","title":"v1.3.0","titles":[],"text":"","url":"/changelog/v1-3-0/"},{"id":"/changelog/v1-3-0/#whats-changed","title":"What's Changed","titles":["v1.3.0"],"text":"fix: [Aikido] Fix security issue in glob via minor version upgrade from 11.0.3 to 11.1.0 by @aikido-autofix[bot] in https://github.com/jaredwray/mockhttp/pull/107 chore: upgrading vitest to 4.0.16 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/109 chore: upgrading hookified to 1.15.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/110 chore: upgrading pino to 10.1.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/111 chore: upgrading fastify modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/112 feat: adding in meta descriptions by @jaredwray in https://github.com/jaredwray/mockhttp/pull/113 chore: pin set-cookie-parser to 2.7.2 to mitigate prototype pollution by @jaredwray in https://github.com/jaredwray/mockhttp/pull/114 feat: implement httpbin Dynamic Data endpoints by @jaredwray in https://github.com/jaredwray/mockhttp/pull/115","url":"/changelog/v1-3-0/#whats-changed"},{"id":"/changelog/v1-3-0/#new-contributors","title":"New Contributors","titles":["v1.3.0"],"text":"@aikido-autofix[bot] made their first contribution in https://github.com/jaredwray/mockhttp/pull/107 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.2.0...v1.3.0","url":"/changelog/v1-3-0/#new-contributors"},{"id":"/changelog/v1-2-0/","title":"v1.2.0","titles":[],"text":"","url":"/changelog/v1-2-0/"},{"id":"/changelog/v1-2-0/#whats-changed","title":"What's Changed","titles":["v1.2.0"],"text":"chore: moving to nodejs 24 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/100 chore: upgradint tsup to 8.5.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/101 chore: upgrading hookified to 1.14.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/102 chore: upgrading vitest to 4.0.15 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/103 chore: upgrading @scalar/api-reference to 1.40.4 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/104 chore: upgrading @biomejs/biome to 2.3.8 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/105 feat: ability to disable logging by @jaredwray in https://github.com/jaredwray/mockhttp/pull/106 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.1.0...v1.2.0","url":"/changelog/v1-2-0/#whats-changed"},{"id":"/changelog/v1-1-0/","title":"v1.1.0","titles":[],"text":"","url":"/changelog/v1-1-0/"},{"id":"/changelog/v1-1-0/#whats-changed","title":"What's Changed","titles":["v1.1.0"],"text":"chore: removing minify as it causes debugging issues by @jaredwray in https://github.com/jaredwray/mockhttp/pull/91 fix: updating readme with correct spelling by @jaredwray in https://github.com/jaredwray/mockhttp/pull/92 chore: upgrading vitest to 4.0.8 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/93 chore: upgrading pino to 10.1.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/94 chore: upgrading hookified to 1.13.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/95 chore: upgrading fastify to 5.6.2 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/96 feat: adding in image routes by @jaredwray in https://github.com/jaredwray/mockhttp/pull/97 feat: adding in rate limit options by @jaredwray in https://github.com/jaredwray/mockhttp/pull/98 feat: making rate limiting enabled by default by @jaredwray in https://github.com/jaredwray/mockhttp/pull/99 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.0.1...v1.1.0","url":"/changelog/v1-1-0/#whats-changed"},{"id":"/changelog/v1-0-1/","title":"v1.0.1","titles":[],"text":"","url":"/changelog/v1-0-1/"},{"id":"/changelog/v1-0-1/#whats-changed","title":"What's Changed","titles":["v1.0.1"],"text":"fix: delete endpoing allows string, JSON, or any by @jaredwray in https://github.com/jaredwray/mockhttp/pull/90 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.0.0...v1.0.1","url":"/changelog/v1-0-1/#whats-changed"},{"id":"/changelog/v1-0-0/","title":"v1.0.0","titles":[],"text":"","url":"/changelog/v1-0-0/"},{"id":"/changelog/v1-0-0/#whats-changed","title":"What's Changed","titles":["v1.0.0"],"text":"fix: docker no longer runs as default user by @jaredwray in https://github.com/jaredwray/mockhttp/pull/80 chore: upgrading @biomejs/biome to 2.2.5 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/81 chore: upgrading pino to 10.0.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/82 chore: upgrading hookified to 1.12.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/83 chore: upgrading fastify to 5.6.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/84 feat: adding in injection taps by @jaredwray in https://github.com/jaredwray/mockhttp/pull/85 fix: delete should allow strings or json to be passed by @jaredwray in https://github.com/jaredwray/mockhttp/pull/86 feat: adding minification to build by @jaredwray in https://github.com/jaredwray/mockhttp/pull/87 feat: adding function for tap injections by @jaredwray in https://github.com/jaredwray/mockhttp/pull/88 feat: updating documentation for taps by @jaredwray in https://github.com/jaredwray/mockhttp/pull/89 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.9.0...v1.0.0","url":"/changelog/v1-0-0/#whats-changed"},{"id":"/changelog/v0-9-0/","title":"v0.9.0","titles":[],"text":"","url":"/changelog/v0-9-0/"},{"id":"/changelog/v0-9-0/#whats-changed","title":"What's Changed","titles":["v0.9.0"],"text":"feat: adding in multiple http methods for plain, html, and text by @jaredwray in https://github.com/jaredwray/mockhttp/pull/78 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.8.0...v0.9.0","url":"/changelog/v0-9-0/#whats-changed"},{"id":"/changelog/v0-8-0/","title":"v0.8.0","titles":[],"text":"","url":"/changelog/v0-8-0/"},{"id":"/changelog/v0-8-0/#whats-changed","title":"What's Changed","titles":["v0.8.0"],"text":"feat: adding in plain endpoint by @jaredwray in https://github.com/jaredwray/mockhttp/pull/74 feat: adding in text endpoint by @jaredwray in https://github.com/jaredwray/mockhttp/pull/75 feat: adding in html endpoint by @jaredwray in https://github.com/jaredwray/mockhttp/pull/76 fix: removing eslint by @jaredwray in https://github.com/jaredwray/mockhttp/pull/77 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.7.0...v0.8.0","url":"/changelog/v0-8-0/#whats-changed"},{"id":"/changelog/v0-7-0/","title":"v0.7.0","titles":[],"text":"","url":"/changelog/v0-7-0/"},{"id":"/changelog/v0-7-0/#whats-changed","title":"What's Changed","titles":["v0.7.0"],"text":"feat: adding in custom traffic badge by @jaredwray in https://github.com/jaredwray/mockhttp/pull/65 feat: adding in auth with basic, bearer, digest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/66 chore: upgrading typescript to 5.9.2 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/67 chore: upgrading codecov to v5 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/68 chore: upgrading pino to 9.9.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/69 chore: upgrading hookified to 1.12.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/70 chore: upgrading fastify to 5.5.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/71 chore: migrating from xo to biome by @jaredwray in https://github.com/jaredwray/mockhttp/pull/72 fix: adding error on warnings for biome check by @jaredwray in https://github.com/jaredwray/mockhttp/pull/73 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.6.1...v0.6.2","url":"/changelog/v0-7-0/#whats-changed"},{"id":"/changelog/v0-6-1/","title":"v0.6.1","titles":[],"text":"","url":"/changelog/v0-6-1/"},{"id":"/changelog/v0-6-1/#whats-changed","title":"What's Changed","titles":["v0.6.1"],"text":"chore: adding in min for cloud run by @jaredwray in https://github.com/jaredwray/mockhttp/pull/60 chore: upgrading xo to 1.2.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/61 chore: upgrading vitest to 3.2.4 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/62 chore: upgrading @scalar/api-reference to 1.32.9 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/63 chore: upgrading hookified to 1.10.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/64 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.6.0...v0.6.1","url":"/changelog/v0-6-1/#whats-changed"},{"id":"/changelog/v0-6-0/","title":"v0.6.0","titles":[],"text":"","url":"/changelog/v0-6-0/"},{"id":"/changelog/v0-6-0/#whats-changed","title":"What's Changed","titles":["v0.6.0"],"text":"fix: adding in application/json for return time on cookies by @jaredwray in https://github.com/jaredwray/mockhttp/pull/52 chore: upgrading vitest to 3.2.3 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/53 chore: upgrading tsup to 8.5.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/54 chore: upgrading pino to 9.7.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/55 chore: upgrading hookified to 1.9.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/56 chore: upgrading xo to 1.1.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/57 chore: upgrading fastify to 5.4.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/58 feat: adding in the anything route from httpbin by @jaredwray in https://github.com/jaredwray/mockhttp/pull/59 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.5.0...v0.6.0","url":"/changelog/v0-6-0/#whats-changed"},{"id":"/changelog/v0-5-0/","title":"v0.5.0","titles":[],"text":"","url":"/changelog/v0-5-0/"},{"id":"/changelog/v0-5-0/#whats-changed","title":"What's Changed","titles":["v0.5.0"],"text":"chore: updating github actions and scripts by @jaredwray in https://github.com/jaredwray/mockhttp/pull/45 chore: upgrading @swc/core and tsx to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/46 chore: upgrading vitest to 3.1.3 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/47 chore: upgrading hookified to 1.9.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/48 chore: upgrading fastify to 5.3.2 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/49 feat: moving docker to get external packaging by @jaredwray in https://github.com/jaredwray/mockhttp/pull/50 feat: adding in cookies from httpbin by @jaredwray in https://github.com/jaredwray/mockhttp/pull/51 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.4.3...v0.5.0","url":"/changelog/v0-5-0/#whats-changed"},{"id":"/changelog/v0-4-3/","title":"v0.4.3","titles":[],"text":"","url":"/changelog/v0-4-3/"},{"id":"/changelog/v0-4-3/#whats-changed","title":"What's Changed","titles":["v0.4.3"],"text":"fix: fixing workflows to use npm for docker by @jaredwray in https://github.com/jaredwray/mockhttp/pull/44 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.4.2...v0.4.3","url":"/changelog/v0-4-3/#whats-changed"},{"id":"/changelog/v0-4-2/","title":"v0.4.2","titles":[],"text":"","url":"/changelog/v0-4-2/"},{"id":"/changelog/v0-4-2/#whats-changed","title":"What's Changed","titles":["v0.4.2"],"text":"fix: updating the description in swagger definition by @jaredwray in https://github.com/jaredwray/mockhttp/pull/34 feat: adding in auto port detection by @jaredwray in https://github.com/jaredwray/mockhttp/pull/35 chore: migrating to pnpm for workflows by @jaredwray in https://github.com/jaredwray/mockhttp/pull/36 chore: upgrading vitest to 3.1.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/37 chore: upgrading typescript to 5.8.3 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/38 chore: upgrading hookified to 1.8.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/39 chore: upgrading fastify to 5.2.2 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/40 chore: upgrading @swc/core to 1.11.16 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/41 chore: upgrading @scalar/api-reference to 1.28.12 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/42 feat: adding in docker compose example by @jaredwray in https://github.com/jaredwray/mockhttp/pull/43 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.4.1...v0.4.2","url":"/changelog/v0-4-2/#whats-changed"},{"id":"/changelog/v0-4-1/","title":"v0.4.1","titles":[],"text":"","url":"/changelog/v0-4-1/"},{"id":"/changelog/v0-4-1/#whats-changed","title":"What's Changed","titles":["v0.4.1"],"text":"chore: upgrading tsup, tsx, and typescript to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/29 chore: upgrading vitest to 3.0.7 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/30 chore: upgrading hookified to 1.7.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/31 chore: upgrading swc to 1.11.5 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/32 chore: upgrading fastify and scalar modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/33 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.4.0...v0.4.1","url":"/changelog/v0-4-1/#whats-changed"},{"id":"/changelog/v0-4-0/","title":"v0.4.0","titles":[],"text":"","url":"/changelog/v0-4-0/"},{"id":"/changelog/v0-4-0/#whats-changed","title":"What's Changed","titles":["v0.4.0"],"text":"feat: adding in the start of mockhttp class by @jaredwray in https://github.com/jaredwray/mockhttp/pull/28 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.3.0...v0.4.0","url":"/changelog/v0-4-0/#whats-changed"},{"id":"/changelog/v0-3-0/","title":"v0.3.0","titles":[],"text":"","url":"/changelog/v0-3-0/"},{"id":"/changelog/v0-3-0/#whats-changed","title":"What's Changed","titles":["v0.3.0"],"text":"chore: upgrading vitest to 3.0.4 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/21 chore: upgrading typescript to 5.7.3 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/22 chore: upgrading tsup and scalar to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/23 chore: upgrading fastify to 5.2.1 and modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/24 feat: moving concurrency on cloud run to 500 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/25 feat: adding in description on main page by @jaredwray in https://github.com/jaredwray/mockhttp/pull/26 feat: adding in redirects by @jaredwray in https://github.com/jaredwray/mockhttp/pull/27 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.2.3...v0.3.0","url":"/changelog/v0-3-0/#whats-changed"},{"id":"/changelog/v0-2-3/","title":"v0.2.3","titles":[],"text":"","url":"/changelog/v0-2-3/"},{"id":"/changelog/v0-2-3/#whats-changed","title":"What's Changed","titles":["v0.2.3"],"text":"removing CORS as its is not needed by @jaredwray in https://github.com/jaredwray/mockhttp/pull/17 feat: adding in robots.txt file by @jaredwray in https://github.com/jaredwray/mockhttp/pull/18 feat: adding in sitemap.xml by @jaredwray in https://github.com/jaredwray/mockhttp/pull/19 chore: upgrading modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/20 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.2.2...v0.2.3","url":"/changelog/v0-2-3/#whats-changed"},{"id":"/changelog/v0-2-2/","title":"v0.2.2","titles":[],"text":"","url":"/changelog/v0-2-2/"},{"id":"/changelog/v0-2-2/#whats-changed","title":"What's Changed","titles":["v0.2.2"],"text":"Adding in docker description and CORS for allowing logo.svg access","url":"/changelog/v0-2-2/#whats-changed"},{"id":"/changelog/v0-2-1/","title":"v0.2.1","titles":[],"text":"","url":"/changelog/v0-2-1/"},{"id":"/changelog/v0-2-1/#whats-changed","title":"What's Changed","titles":["v0.2.1"],"text":"moving to logging on a single line by @jaredwray in https://github.com/jaredwray/mockhttp/pull/15 upgrading scalar to 1.25.82 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/16 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.2.0...v0.2.1","url":"/changelog/v0-2-1/#whats-changed"},{"id":"/changelog/v0-2-0/","title":"v0.2.0","titles":[],"text":"","url":"/changelog/v0-2-0/"},{"id":"/changelog/v0-2-0/#whats-changed","title":"What's Changed","titles":["v0.2.0"],"text":"response inspection by @jaredwray in https://github.com/jaredwray/mockhttp/pull/14 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.1.0...v0.2.0","url":"/changelog/v0-2-0/#whats-changed"},{"id":"/changelog/v0-1-0/","title":"v0.1.0","titles":[],"text":"","url":"/changelog/v0-1-0/"},{"id":"/changelog/v0-1-0/#whats-changed","title":"What's Changed","titles":["v0.1.0"],"text":"adding in contributing and code of conduct by @jaredwray in https://github.com/jaredwray/mockhttp/pull/1 migrating to correct folder format by @jaredwray in https://github.com/jaredwray/mockhttp/pull/2 adding in logo and favicon by @jaredwray in https://github.com/jaredwray/mockhttp/pull/3 adding in headers and user-agent endpoints by @jaredwray in https://github.com/jaredwray/mockhttp/pull/4 moving to scalar by @jaredwray in https://github.com/jaredwray/mockhttp/pull/5 adding in status codes by @jaredwray in https://github.com/jaredwray/mockhttp/pull/6 adding in unit tests and workflows by @jaredwray in https://github.com/jaredwray/mockhttp/pull/7 fixing the title that had an extra space by @jaredwray in https://github.com/jaredwray/mockhttp/pull/8 moving to scalar locally instead of via CDN by @jaredwray in https://github.com/jaredwray/mockhttp/pull/9 adding in dynamic version from package.json by @jaredwray in https://github.com/jaredwray/mockhttp/pull/10 adding in fastify helmet by @jaredwray in https://github.com/jaredwray/mockhttp/pull/11 upgrading xo to 0.60.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/12 updating build to tsup and upgrading vitest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/13","url":"/changelog/v0-1-0/#whats-changed"},{"id":"/changelog/v0-1-0/#new-contributors","title":"New Contributors","titles":["v0.1.0"],"text":"@jaredwray made their first contribution in https://github.com/jaredwray/mockhttp/pull/1 Full Changelog : https://github.com/jaredwray/mockhttp/commits/v0.1.0","url":"/changelog/v0-1-0/#new-contributors"}]}
|
|
1
|
+
{"records":[{"id":"/docs/","title":"Getting Started","titles":[],"text":"A simple HTTP server for mocking responses in tests. Inspired by httpbin and built with Node.js and Fastify. Run it at mockhttp.org , with Docker ( jaredwray/mockhttp ), or in Node.js ( npm install @jaredwray/mockhttp ).","url":"/docs/"},{"id":"/docs/#features","title":"Features","titles":["Getting Started"],"text":"All the features of httpbin Taps — inject custom responses for testing and development Bins — capture and inspect incoming HTTP requests (great for webhook debugging) @fastify/helmet built in by default Built with Node.js, TypeScript, and Fastify Run it in Node.js, or deploy with Docker , Cloudflare Workers , or Wasmer Edge Free hosted service at mockhttp.org , running on Cloudflare Documentation site and interactive OpenAPI reference Auto-detect the next port that is not in use HTTPS and HTTP/2 , plus rate limiting, logging, and URL matching","url":"/docs/#features"},{"id":"/docs/#deploy-via-docker","title":"Deploy via Docker","titles":["Getting Started"],"text":"docker run -d -p 3000:3000 jaredwray/mockhttp","url":"/docs/#deploy-via-docker"},{"id":"/docs/#deploy-via-docker-compose","title":"Deploy via Docker Compose","titles":["Getting Started"],"text":"services: mockhttp: image: jaredwray/mockhttp:latest ports: - \"3000:3000\" If you want to run it on a different port, just change the 3000 to whatever port you want and add in the environment variable PORT to the environment. services: mockhttp: image: jaredwray/mockhttp:latest ports: - \"3001:3001\" environment: - PORT=3001 You can see an example of this in the docker-compose.yaml file.","url":"/docs/#deploy-via-docker-compose"},{"id":"/docs/#deploy-via-nodejs","title":"Deploy via Node.js","titles":["Getting Started"],"text":"npm install @jaredwray/mockhttp --save then run mockhttp in your code. import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp (); await mock. start (); // start the server const response = await fetch ( 'http://localhost:3000/get' ); console . log (response); await mock. close (); // stop the server Step-by-step deploy guides: Docker , Cloudflare , and Wasmer .","url":"/docs/#deploy-via-nodejs"},{"id":"/docs/https/","title":"HTTPS and HTTP/2","titles":[],"text":"MockHttp supports HTTPS with auto-generated self-signed certificates or your own custom certificates. No external dependencies are required — certificate generation uses only Node.js built-in crypto .","url":"/docs/https/"},{"id":"/docs/https/#auto-generated-certificate","title":"Auto-Generated Certificate","titles":["HTTPS and HTTP/2"],"text":"The simplest way to enable HTTPS is to pass https: true . A self-signed certificate for localhost is generated automatically: import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp ({ https : true }); await mock. start (); console . log (mock. isHttps ); // true // Use Fastify's built-in inject() for testing (no TLS setup needed) const response = await mock. server . inject ({ method : 'GET' , url : '/get' }); console . log (response. statusCode ); // 200 await mock. close (); Note: Self-signed certificates are not trusted by default. When making real HTTPS requests (e.g. with fetch ), set NODE_TLS_REJECT_UNAUTHORIZED=0 in your test environment or use a custom HTTPS agent.","url":"/docs/https/#auto-generated-certificate"},{"id":"/docs/https/#custom-certificate-options","title":"Custom Certificate Options","titles":["HTTPS and HTTP/2"],"text":"You can customize the auto-generated certificate by passing certificateOptions : const mock = new MockHttp ({ https : { certificateOptions : { commonName : 'my-test-server' , validityDays : 30 , keySize : 4096 , altNames : [ { type : 'dns' , value : 'example.local' }, { type : 'dns' , value : '*.example.local' }, { type : 'ip' , value : '192.168.1.100' }, ], }, }, }); await mock. start (); // Make requests... await mock. close ();","url":"/docs/https/#custom-certificate-options"},{"id":"/docs/https/#provide-your-own-certificate","title":"Provide Your Own Certificate","titles":["HTTPS and HTTP/2"],"text":"You can supply your own PEM-encoded certificate and key, either as strings or file paths: // Using PEM strings const mock = new MockHttp ({ https : { cert : '-----BEGIN CERTIFICATE-----\\n...' , key : '-----BEGIN PRIVATE KEY-----\\n...' , }, }); await mock. start (); // Make requests... await mock. close (); // Using file paths const mock = new MockHttp ({ https : { cert : '/path/to/cert.pem' , key : '/path/to/key.pem' , }, }); await mock. start (); // Make requests... await mock. close ();","url":"/docs/https/#provide-your-own-certificate"},{"id":"/docs/https/#standalone-certificate-generation","title":"Standalone Certificate Generation","titles":["HTTPS and HTTP/2"],"text":"You can also generate certificates independently using the exported utility functions: import { generateCertificate, generateCertificateFiles } from '@jaredwray/mockhttp' ; // Generate in-memory PEM strings const { cert, key } = generateCertificate ({ commonName : 'my-app' , validityDays : 90 , }); // Generate and write to disk const result = await generateCertificateFiles ({ certPath : './certs/cert.pem' , keyPath : './certs/key.pem' , commonName : 'my-app' , });","url":"/docs/https/#standalone-certificate-generation"},{"id":"/docs/https/#https-options-reference","title":"HTTPS Options Reference","titles":["HTTPS and HTTP/2"],"text":"Option Type Default Description cert string — PEM-encoded certificate string or file path key string — PEM-encoded private key string or file path autoGenerate boolean true Auto-generate a self-signed certificate when cert/key are not provided certificateOptions CertificateOptions — Options for the auto-generated certificate","url":"/docs/https/#https-options-reference"},{"id":"/docs/https/#certificate-options","title":"Certificate Options","titles":["HTTPS and HTTP/2","HTTPS Options Reference"],"text":"Option Type Default Description commonName string 'localhost' Certificate subject Common Name (CN) altNames Array<{ type, value }> [dns:localhost, ip:127.0.0.1, ip:::1] Subject Alternative Names with type 'dns' or 'ip' validityDays number 365 Certificate validity period in days keySize number 2048 RSA key size in bits","url":"/docs/https/#certificate-options"},{"id":"/docs/https/#http2-support","title":"HTTP/2 Support","titles":["HTTPS and HTTP/2"],"text":"MockHttp supports HTTP/2 in two modes: h2 — HTTP/2 over TLS (used by browsers), enabled with both http2: true and https: true h2c — HTTP/2 cleartext (no TLS), enabled with just http2: true , useful for service-to-service testing","url":"/docs/https/#http2-support"},{"id":"/docs/https/#http2-over-tls-h2","title":"HTTP/2 over TLS (h2)","titles":["HTTPS and HTTP/2","HTTP/2 Support"],"text":"import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp ({ http2 : true , https : true }); await mock. start (); console . log (mock. http2 ); // true console . log (mock. isHttps ); // true const response = await mock. server . inject ({ method : 'GET' , url : '/get' }); console . log (response. statusCode ); // 200 await mock. close (); By default, HTTP/1.1 clients can still connect via ALPN negotiation ( http1 defaults to true ). To disable HTTP/1.1 fallback: const mock = new MockHttp ({ http2 : true , https : true , http1 : false }); await mock. start ();","url":"/docs/https/#http2-over-tls-h2"},{"id":"/docs/https/#http2-cleartext-h2c","title":"HTTP/2 Cleartext (h2c)","titles":["HTTPS and HTTP/2","HTTP/2 Support"],"text":"const mock = new MockHttp ({ http2 : true }); await mock. start (); console . log (mock. http2 ); // true await mock. close (); Note: Browsers do not support h2c. This mode is useful for testing gRPC or service-to-service communication.","url":"/docs/https/#http2-cleartext-h2c"},{"id":"/docs/https/#http2-via-environment-variable","title":"HTTP/2 via Environment Variable","titles":["HTTPS and HTTP/2","HTTP/2 Support"],"text":"HTTP2= true node your-app.js","url":"/docs/https/#http2-via-environment-variable"},{"id":"/docs/taps/","title":"Taps","titles":[],"text":"The injection/tap feature allows you to \"tap into\" the request flow and inject custom responses for specific requests. This is particularly useful for: Offline testing - Mock external API responses without network access Testing edge cases - Simulate errors, timeouts, or specific response scenarios Development - Work on your application without depending on external services","url":"/docs/taps/"},{"id":"/docs/taps/#what-is-a-tap","title":"What is a \"Tap\"?","titles":["Taps"],"text":"A \"tap\" is a reference to an injected response, similar to \"wiretapping\" - you're intercepting requests and returning predefined responses. Each tap can be removed when you're done with it, restoring normal server behavior.","url":"/docs/taps/#what-is-a-tap"},{"id":"/docs/taps/#basic-usage","title":"Basic Usage","titles":["Taps"],"text":"import { mockhttp } from '@jaredwray/mockhttp' ; const mock = new mockhttp (); await mock. start (); // Inject a simple response const tap = mock. taps . inject ( { response : \"Hello, World!\" , statusCode : 200 , headers : { \"Content-Type\" : \"text/plain\" } }, { url : \"/api/greeting\" , method : \"GET\" } ); // Make requests - they will get the injected response const response = await fetch ( 'http://localhost:3000/api/greeting' ); console . log ( await response. text ()); // \"Hello, World!\" // Remove the injection when done mock. taps . removeInjection (tap); await mock. close ();","url":"/docs/taps/#basic-usage"},{"id":"/docs/taps/#advanced-examples","title":"Advanced Examples","titles":["Taps"],"text":"","url":"/docs/taps/#advanced-examples"},{"id":"/docs/taps/#inject-json-response","title":"Inject JSON Response","titles":["Taps","Advanced Examples"],"text":"const tap = mock. taps . inject ( { response : { message : \"Success\" , data : { id : 123 } }, statusCode : 200 }, { url : \"/api/users/123\" } );","url":"/docs/taps/#inject-json-response"},{"id":"/docs/taps/#wildcard-url-matching","title":"Wildcard URL Matching","titles":["Taps","Advanced Examples"],"text":"// Match all requests under /api/ const tap = mock. taps . inject ( { response : \"API is mocked\" , statusCode : 503 }, { url : \"/api/*\" } );","url":"/docs/taps/#wildcard-url-matching"},{"id":"/docs/taps/#multiple-injections","title":"Multiple Injections","titles":["Taps","Advanced Examples"],"text":"const tap1 = mock. taps . inject ( { response : \"Users data\" }, { url : \"/api/users\" } ); const tap2 = mock. taps . inject ( { response : \"Posts data\" }, { url : \"/api/posts\" } ); // View all active injections console . log (mock. taps . injections ); // Map of all active taps // Remove specific injections mock. taps . removeInjection (tap1); mock. taps . removeInjection (tap2);","url":"/docs/taps/#multiple-injections"},{"id":"/docs/taps/#match-by-http-method","title":"Match by HTTP Method","titles":["Taps","Advanced Examples"],"text":"// Only intercept POST requests const tap = mock. taps . inject ( { response : \"Created\" , statusCode : 201 }, { url : \"/api/users\" , method : \"POST\" } );","url":"/docs/taps/#match-by-http-method"},{"id":"/docs/taps/#match-by-headers","title":"Match by Headers","titles":["Taps","Advanced Examples"],"text":"const tap = mock. taps . inject ( { response : \"Authenticated response\" }, { url : \"/api/secure\" , headers : { \"authorization\" : \"Bearer token123\" } } );","url":"/docs/taps/#match-by-headers"},{"id":"/docs/taps/#catch-all-injection","title":"Catch-All Injection","titles":["Taps","Advanced Examples"],"text":"// Match ALL requests (no matcher specified) const tap = mock. taps . inject ({ response : \"Server is in maintenance mode\" , statusCode : 503 });","url":"/docs/taps/#catch-all-injection"},{"id":"/docs/taps/#dynamic-function-response","title":"Dynamic Function Response","titles":["Taps","Advanced Examples"],"text":"You can provide a function that dynamically generates the response based on the incoming request: // Function response with access to the request object const tap = mock. taps . inject ( ( request ) => { return { response : { message : `You requested ${request.url} ` , method : request. method , timestamp : new Date (). toISOString () }, statusCode : 200 , headers : { \"X-Request-Path\" : request. url } }; }, { url : \"/api/*\" } ); // Conditional responses based on request const tap = mock. taps . inject ( ( request ) => { // Return error for URLs containing 'error' if (request. url . includes ( 'error' )) { return { response : { error : \"Something went wrong\" }, statusCode : 500 }; } // Return success for everything else return { response : { status : \"success\" }, statusCode : 200 }; }); // Dynamic headers based on request const tap = mock. taps . inject ( ( request ) => ({ response : \"OK\" , statusCode : 200 , headers : { \"X-Original-Method\" : request. method , \"X-Original-URL\" : request. url , \"X-Original-Host\" : request. hostname } }), { url : \"/api/mirror\" } );","url":"/docs/taps/#dynamic-function-response"},{"id":"/docs/bins/","title":"Bins","titles":[],"text":"Bins are ephemeral URL endpoints that capture incoming HTTP requests so you can inspect them later. They're the inverse of Taps: instead of injecting a response, they record everything they receive. Useful for: Debugging webhooks — point Stripe / GitHub / Slack at a bin URL and see exactly what they send Exercising client SDKs — verify your SDK sends the request shape you expect Recording fixtures — capture real traffic to replay in tests later There are two URL prefixes: /bins — JSON management API: create, list, inspect, delete bins /b/:id — the capture URL. Any HTTP method, any sub-path, any body sent here is stored against bin :id","url":"/docs/bins/"},{"id":"/docs/bins/#quick-start","title":"Quick Start","titles":["Bins"],"text":"# 1. create a bin curl -s -X POST http://localhost:3000/bins # → { \"id\": \"abc123def456\", \"url\": \"http://localhost:3000/b/abc123def456\", # \"createdAt\": \"2026-05-18T12:00:00.000Z\", # \"expiresAt\": \"2026-05-19T12:00:00.000Z\", # \"requestCount\": 0 } # 2. send anything to the capture URL curl -X POST \"http://localhost:3000/b/abc123def456/webhook?source=stripe\" \\ -H 'content-type: application/json' \\ -d '{\"event\":\"payment.succeeded\"}' # → { \"ok\": true, \"binId\": \"abc123def456\", \"requestId\": \"f9c2e1a40b3d\" } # 3. list captured requests (newest first) curl http://localhost:3000/bins/abc123def456/requests","url":"/docs/bins/#quick-start"},{"id":"/docs/bins/#endpoints","title":"Endpoints","titles":["Bins"],"text":"Method Path Description POST /bins Create a new bin GET /bins List all active bins GET /bins/:id Get bin metadata GET /bins/:id/requests List captured requests (newest first) GET /bins/:id/requests/:reqId Get a single captured request DELETE /bins/:id/requests Clear all captured requests in a bin DELETE /bins/:id Delete a bin ANY /b/:id and /b/:id/* Capture requests sent to a bin","url":"/docs/bins/#endpoints"},{"id":"/docs/bins/#end-to-end-webhook-debugging-example","title":"End-to-End Webhook Debugging Example","titles":["Bins"],"text":"A complete walkthrough using curl: BASE=http://localhost:3000 # Create the bin and grab its id ID=$(curl -s -X POST $BASE /bins | jq -r . id ) echo \"Bin URL: $BASE /b/ $ID \" # Simulate a Stripe webhook curl -s -X POST \" $BASE /b/ $ID /stripe/events?secret=whsec_test\" \\ -H 'content-type: application/json' \\ -H 'stripe-signature: t=1700000000,v1=abc123' \\ -d '{\"id\":\"evt_1\",\"type\":\"payment_intent.succeeded\",\"data\":{\"object\":{\"amount\":2000}}}' # Simulate a GitHub webhook curl -s -X POST \" $BASE /b/ $ID /github\" \\ -H 'content-type: application/json' \\ -H 'x-github-event: pull_request' \\ -d '{\"action\":\"opened\",\"number\":42}' # Inspect everything that arrived curl -s \" $BASE /bins/ $ID /requests\" | jq # Drill into the most recent one RID=$(curl -s \" $BASE /bins/ $ID /requests\" | jq -r '.requests[0].id' ) curl -s \" $BASE /bins/ $ID /requests/ $RID \" | jq # { # \"id\": \"f9c2e1a40b3d\", # \"binId\": \"abc123def456\", # \"method\": \"POST\", # \"url\": \"/github\", # \"path\": \"/github\", # \"query\": {}, # \"headers\": { # \"host\": \"localhost:3000\", # \"content-type\": \"application/json\", # \"x-github-event\": \"pull_request\" # }, # \"remoteAddress\": \"127.0.0.1\", # \"contentType\": \"application/json\", # \"bodySize\": 32, # \"body\": \"{\\\"action\\\":\\\"opened\\\",\\\"number\\\":42}\", # \"bodyEncoding\": \"utf8\", # \"truncated\": false, # \"capturedAt\": \"2026-05-18T12:00:01.234Z\" # } # Clean up curl -s -X DELETE \" $BASE /bins/ $ID /requests\" # clear captures, keep the bin curl -s -X DELETE \" $BASE /bins/ $ID \" # delete the bin entirely","url":"/docs/bins/#end-to-end-webhook-debugging-example"},{"id":"/docs/bins/#captured-request-shape","title":"Captured Request Shape","titles":["Bins"],"text":"{ \"id\" : \"f9c2e1a40b3d\" , \"binId\" : \"abc123def456\" , \"method\" : \"POST\" , \"url\" : \"/webhook?source=stripe\" , \"path\" : \"/webhook\" , \"query\" : { \"source\" : \"stripe\" } , \"headers\" : { \"content-type\" : \"application/json\" , \"...\" : \"...\" } , \"remoteAddress\" : \"127.0.0.1\" , \"contentType\" : \"application/json\" , \"bodySize\" : 32 , \"body\" : \"{\\\"event\\\":\\\"payment.succeeded\\\"}\" , \"bodyEncoding\" : \"utf8\" , \"truncated\" : false , \"capturedAt\" : \"2026-05-18T12:00:00.000Z\" } url is the request URL relative to the bin (everything after /b/:id ). path is the sub-path only, without the query string. bodyEncoding is \"utf8\" for text content types (text/*, application/json, application/xml, application/x-www-form-urlencoded, application/javascript), \"base64\" for everything else (binary payloads), or \"none\" when no body was sent. truncated is true when the body exceeded maxBodySize and was cut off. bodySize reflects the original length.","url":"/docs/bins/#captured-request-shape"},{"id":"/docs/bins/#body-encoding-examples","title":"Body Encoding Examples","titles":["Bins"],"text":"","url":"/docs/bins/#body-encoding-examples"},{"id":"/docs/bins/#text-content-utf-8","title":"Text Content (UTF-8)","titles":["Bins","Body Encoding Examples"],"text":"JSON, XML, form-encoded, plain text, and JavaScript are stored as UTF-8 strings so you can read them directly: curl -X POST \"http://localhost:3000/b/ $ID \" \\ -H 'content-type: application/json' \\ -d '{\"hello\":\"world\"}' curl -s \"http://localhost:3000/bins/ $ID /requests\" | jq '.requests[0] | {bodyEncoding, body}' # { # \"bodyEncoding\": \"utf8\", # \"body\": \"{\\\"hello\\\":\\\"world\\\"}\" # }","url":"/docs/bins/#text-content-utf-8"},{"id":"/docs/bins/#binary-content-base64","title":"Binary Content (Base64)","titles":["Bins","Body Encoding Examples"],"text":"Any non-text content type is base64-encoded, preserving the bytes exactly: # Upload a PNG to the bin curl -X POST \"http://localhost:3000/b/ $ID /upload\" \\ -H 'content-type: image/png' \\ --data-binary @logo.png curl -s \"http://localhost:3000/bins/ $ID /requests\" | jq '.requests[0] | {bodyEncoding, bodySize}' # { # \"bodyEncoding\": \"base64\", # \"bodySize\": 14823 # } # Decode the body back to bytes curl -s \"http://localhost:3000/bins/ $ID /requests\" \\ | jq -r '.requests[0].body' | base64 -d > recovered.png","url":"/docs/bins/#binary-content-base64"},{"id":"/docs/bins/#truncation","title":"Truncation","titles":["Bins","Body Encoding Examples"],"text":"Bodies larger than maxBodySize (1 MiB by default) are cut off and flagged: // In test setup import { MockHttp , BinManager } from '@jaredwray/mockhttp' ; const mock = new MockHttp (); mock. bins = new BinManager ({ maxBodySize : 1024 }); // 1 KiB cap await mock. start (); # Send 5000 bytes to a bin with a 1 KiB cap head -c 5000 /dev/urandom | curl -X POST \"http://localhost:3000/b/ $ID \" \\ -H 'content-type: application/octet-stream' \\ --data-binary @- curl -s \"http://localhost:3000/bins/ $ID /requests\" | jq '.requests[0] | {bodySize, truncated, body_len: (.body | length)}' # { # \"bodySize\": 5000, ← original size # \"truncated\": true, # \"body_len\": 1368 ← base64 of the first 1024 bytes # }","url":"/docs/bins/#truncation"},{"id":"/docs/bins/#fifo-eviction-example","title":"FIFO Eviction Example","titles":["Bins"],"text":"Once a bin reaches maxRequestsPerBin captures (100 by default), the oldest ones are dropped: # Send 105 requests for i in $( seq 1 105); do curl -s -X POST \"http://localhost:3000/b/ $ID /event/ $i \" > /dev/null done # The bin holds the most recent 100; the first 5 are gone curl -s \"http://localhost:3000/bins/ $ID /requests\" | jq '.requests | length' # 100 # Newest is at the top curl -s \"http://localhost:3000/bins/ $ID /requests\" | jq '.requests[0].path' # \"/event/105\"","url":"/docs/bins/#fifo-eviction-example"},{"id":"/docs/bins/#programmatic-access","title":"Programmatic Access","titles":["Bins"],"text":"The bin manager is exposed on the MockHttp instance as mock.bins . This makes it easy to drive bins from a test suite without going through HTTP: import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp ({ logging : false }); await mock. start (); // Create a bin const bin = mock. bins . createBin (); console . log ( `Webhook target: http://localhost: ${mock.port} /b/ ${bin.id} ` ); // ... point your code-under-test at that URL ... // Read captured requests (newest first) const requests = mock. bins . getRequests (bin. id ); console . log ( `Captured ${requests.length} requests` ); for ( const req of requests) { console . log ( ` ${req.method} ${req.path} ( ${req.bodySize} bytes)` ); } // Clean up mock. bins . deleteBin (bin. id ); await mock. close (); // also stops the bin cleanup timer","url":"/docs/bins/#programmatic-access"},{"id":"/docs/bins/#using-bins-in-a-vitest-test","title":"Using Bins in a Vitest Test","titles":["Bins","Programmatic Access"],"text":"import { afterAll, beforeAll, expect, test } from 'vitest' ; import { MockHttp } from '@jaredwray/mockhttp' ; let mock : MockHttp ; beforeAll ( async () => { mock = new MockHttp ({ logging : false }); await mock. start (); }); afterAll ( async () => { await mock. close (); }); test ( 'my SDK sends the right webhook payload' , async () => { const bin = mock. bins . createBin (); const webhookUrl = `http://localhost: ${mock.port} /b/ ${bin.id} ` ; // Drive your SDK at the bin await mySdk. notify (webhookUrl, { event : 'user.created' , id : 42 }); // Assert on what actually arrived const [captured] = mock. bins . getRequests (bin. id ); expect (captured. method ). toBe ( 'POST' ); expect (captured. contentType ). toBe ( 'application/json' ); expect ( JSON . parse (captured. body !)). toEqual ({ event : 'user.created' , id : 42 , }); expect (captured. headers [ 'x-signature' ]). toBeDefined (); });","url":"/docs/bins/#using-bins-in-a-vitest-test"},{"id":"/docs/bins/#configuration","title":"Configuration","titles":["Bins"],"text":"Bins are enabled by default. To disable the routes entirely: const mock = new MockHttp ({ httpBin : { bins : false }, }); To tune limits, replace the default BinManager before starting: import { MockHttp , BinManager } from '@jaredwray/mockhttp' ; const mock = new MockHttp (); mock. bins = new BinManager ({ defaultTtlMs : 60 * 60 * 1000 , // 1 hour (default: 24h) maxRequestsPerBin : 500 , // (default: 100) maxBodySize : 5 * 1024 * 1024 , // 5 MiB (default: 1 MiB) idLength : 16 , // (default: 12) cleanupIntervalMs : 30 * 1000 , // sweep every 30s (default: 60s) }); await mock. start ();","url":"/docs/bins/#configuration"},{"id":"/docs/bins/#defaults","title":"Defaults","titles":["Bins","Configuration"],"text":"Option Default Description defaultTtlMs 86400000 (24h) Bin lifetime. Expired bins return 404 and are lazily removed. maxRequestsPerBin 100 When exceeded, oldest captures are dropped (FIFO). maxBodySize 1048576 (1 MiB) Larger bodies are truncated; truncated: true is set on the capture. idLength 12 Length of generated bin and request ids. cleanupIntervalMs 60000 (1 min) How often expired bins are swept. The timer is unref() 'd so it never keeps the process alive.","url":"/docs/bins/#defaults"},{"id":"/docs/bins/#pluggable-storage","title":"Pluggable Storage","titles":["Bins","Configuration"],"text":"BinManager accepts a store: BinStore so you can plug in alternative backends (Redis, SQLite, etc.) without changing the rest of the codebase. The default InMemoryBinStore keeps state in process memory. import { BinManager , InMemoryBinStore , type Bin , type BinStore , type CapturedRequest , } from '@jaredwray/mockhttp' ; class RedisBinStore implements BinStore { createBin ( bin : Bin ): void { /* SET bin:${bin.id} ... */ } getBin ( id : string ): Bin | undefined { /* GET ... */ } listBins (): Bin [] { /* SCAN ... */ } deleteBin ( id : string ): boolean { /* DEL ... */ } addRequest ( binId : string , req : CapturedRequest , max : number ): void { /* LPUSH bin:${binId}:requests + LTRIM to max */ } getRequests ( binId : string ): CapturedRequest [] { /* LRANGE ... */ } getRequest ( binId : string , reqId : string ): CapturedRequest | undefined { /* ... */ } clearRequests ( binId : string ): void { /* DEL bin:${binId}:requests */ } cleanupExpired ( now : number ): string [] { /* scan + delete */ return []; } } mock. bins = new BinManager ({ store : new RedisBinStore () });","url":"/docs/bins/#pluggable-storage"},{"id":"/docs/configuration/","title":"Configuration","titles":[],"text":"MockHttp supports rate limiting using @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.","url":"/docs/configuration/"},{"id":"/docs/configuration/#default-rate-limiting","title":"Default Rate Limiting","titles":["Configuration"],"text":"By default, MockHttp applies the following rate limit: 1000 requests per minute per IP address Localhost is excluded - requests from 127.0.0.1 and ::1 bypass rate limiting (ideal for local development and testing) import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp (); await mock. start (); // Rate limiting is active (1000 req/min) except for localhost","url":"/docs/configuration/#default-rate-limiting"},{"id":"/docs/configuration/#customizing-rate-limiting","title":"Customizing Rate Limiting","titles":["Configuration"],"text":"To customize rate limiting, pass a rateLimit configuration object when creating your MockHttp instance: import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp ({ rateLimit : { max : 100 , // Maximum 100 requests timeWindow : '1 minute' // Per 1 minute window } }); await mock. start ();","url":"/docs/configuration/#customizing-rate-limiting"},{"id":"/docs/configuration/#common-configuration-options","title":"Common Configuration Options","titles":["Configuration"],"text":"The rateLimit option accepts all @fastify/rate-limit options :","url":"/docs/configuration/#common-configuration-options"},{"id":"/docs/configuration/#basic-rate-limiting","title":"Basic Rate Limiting","titles":["Configuration","Common Configuration Options"],"text":"// Limit to 50 requests per minute const mock = new MockHttp ({ rateLimit : { max : 50 , timeWindow : '1 minute' } });","url":"/docs/configuration/#basic-rate-limiting"},{"id":"/docs/configuration/#stricter-limits-with-custom-error-response","title":"Stricter Limits with Custom Error Response","titles":["Configuration","Common Configuration Options"],"text":"const mock = new MockHttp ({ rateLimit : { max : 30 , timeWindow : 60000 , // 1 minute in milliseconds errorResponseBuilder : ( req, context ) => ({ statusCode : 429 , error : 'Too Many Requests' , message : `Rate limit exceeded. Try again in ${context.after} ` }) } });","url":"/docs/configuration/#stricter-limits-with-custom-error-response"},{"id":"/docs/configuration/#allow-list-exclude-specific-ips","title":"Allow List (Exclude Specific IPs)","titles":["Configuration","Common Configuration Options"],"text":"const mock = new MockHttp ({ rateLimit : { max : 100 , timeWindow : '1 minute' , allowList : [ '127.0.0.1' , '192.168.1.100' ] // These IPs bypass rate limiting } });","url":"/docs/configuration/#allow-list-exclude-specific-ips"},{"id":"/docs/configuration/#custom-key-generator-rate-limit-by-header","title":"Custom Key Generator (Rate Limit by Header)","titles":["Configuration","Common Configuration Options"],"text":"const mock = new MockHttp ({ rateLimit : { max : 100 , timeWindow : '1 minute' , keyGenerator : ( request ) => { // Rate limit by API key instead of IP return request. headers [ 'x-api-key' ] || request. ip ; } } });","url":"/docs/configuration/#custom-key-generator-rate-limit-by-header"},{"id":"/docs/configuration/#advanced-configuration","title":"Advanced Configuration","titles":["Configuration","Common Configuration Options"],"text":"const mock = new MockHttp ({ rateLimit : { global : true , // Apply to all routes max : 100 , // Max requests timeWindow : '1 minute' , // Time window cache : 10000 , // Cache size for tracking clients skipOnError : false , // Don't skip on storage errors ban : 10 , // Ban after 10 rate limit violations continueExceeding : false , // Don't reset window on each request enableDraftSpec : true , // Use IETF draft spec headers addHeaders : { // Customize rate limit headers 'x-ratelimit-limit' : true , 'x-ratelimit-remaining' : true , 'x-ratelimit-reset' : true } } });","url":"/docs/configuration/#advanced-configuration"},{"id":"/docs/configuration/#disabling-rate-limiting","title":"Disabling Rate Limiting","titles":["Configuration"],"text":"To disable rate limiting completely, set the rateLimit option to false : const mock = new MockHttp ({ rateLimit : false // Completely disable rate limiting }); await mock. start (); // No rate limiting is applied to any requests Note: To change rate limiting settings after the server has started, you must restart the server: const mock = new MockHttp (); await mock. start (); // Starts with default rate limiting // To change or disable rate limiting: await mock. close (); mock. rateLimit = undefined ; // or set new options await mock. start (); // Restarts with new settings","url":"/docs/configuration/#disabling-rate-limiting"},{"id":"/docs/configuration/#available-options","title":"Available Options","titles":["Configuration"],"text":"Option Type Default Description max number | function 1000 Maximum requests per time window timeWindow number | string 60000 Duration of rate limit window (milliseconds or string like '1 minute') cache number 5000 LRU cache size for tracking clients allowList array | function [] IPs or function to exclude from rate limiting keyGenerator function IP-based Function to generate unique client identifier errorResponseBuilder function Default 429 Custom error response function skipOnError boolean false Skip rate limiting if storage errors occur ban number -1 Ban client after N violations (disabled by default) continueExceeding boolean false Renew time window on each request while limited enableDraftSpec boolean false Use IETF draft specification headers For the complete list of options, see the @fastify/rate-limit documentation .","url":"/docs/configuration/#available-options"},{"id":"/docs/configuration/#logging","title":"Logging","titles":["Configuration"],"text":"MockHttp uses Pino for logging via Fastify's built-in logger. Logging is enabled by default but can be disabled when needed.","url":"/docs/configuration/#logging"},{"id":"/docs/configuration/#disabling-logging","title":"Disabling Logging","titles":["Configuration","Logging"],"text":"import { MockHttp } from '@jaredwray/mockhttp' ; const mock = new MockHttp ({ logging : false }); await mock. start (); // Server runs silently without any log output You can also disable logging via the LOGGING environment variable: LOGGING= false node your-app.js","url":"/docs/configuration/#disabling-logging"},{"id":"/docs/configuration/#flexible-url-matching","title":"Flexible URL Matching","titles":["Configuration"],"text":"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. For example, all of these are served by /status/:code : GET /status/429 GET /status/429/ GET /status/429/foo GET /status/429/foo/bar 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.","url":"/docs/configuration/#flexible-url-matching"},{"id":"/docs/library/","title":"Library API","titles":[],"text":"","url":"/docs/library/"},{"id":"/docs/library/#mockhttp-class","title":"MockHttp Class","titles":["Library API"],"text":"","url":"/docs/library/#mockhttp-class"},{"id":"/docs/library/#constructor","title":"Constructor","titles":["Library API","MockHttp Class"],"text":"new MockHttp (options?) Parameters: options? (MockHttpOptions): port? : number - The port to listen on (default: 3000) host? : string - The host to listen on (default: '0.0.0.0') autoDetectPort? : boolean - Auto-detect next available port if in use (default: true) helmet? : boolean - Use Helmet for security headers (default: true) apiDocs? : boolean - Serve the Docula documentation site and OpenAPI spec (default: true) siteDistPath? : string - Path to the built Docula site (default: the package site/dist directory) rateLimit? : RateLimitPluginOptions - Configure rate limiting (default: 1000 req/min, localhost excluded) logging? : boolean - Enable logging (default: true) staticFiles? : boolean - Serve files from the package public/ directory (default: true) pluginTimeout? : number - Fastify plugin boot timeout in milliseconds; 0 disables it (default: Fastify's timeout) startBins? : boolean - Start the request-bin cleanup timer during initialize() (default: true) httpBin? : HttpBinOptions - Configure which httpbin routes to enable httpMethods? : boolean - Enable HTTP method routes (default: true) redirects? : boolean - Enable redirect routes (default: true) requestInspection? : boolean - Enable request inspection routes (default: true) responseInspection? : boolean - Enable response inspection routes (default: true) statusCodes? : boolean - Enable status code routes (default: true) responseFormats? : boolean - Enable response format routes (default: true) cookies? : boolean - Enable cookie routes (default: true) anything? : boolean - Enable anything routes (default: true) auth? : boolean - Enable authentication routes (default: true) images? : boolean - Enable image routes (default: true) bins? : boolean - Enable request bin routes /bins and /b/:id (default: true) https? : boolean | HttpsOptions - Enable HTTPS with auto-generated or custom certificates (default: undefined/disabled) http2? : boolean - Enable HTTP/2 support (default: false) http1? : boolean - Allow HTTP/1.1 fallback when using HTTP/2 with HTTPS (default: true) hookOptions? : HookifiedOptions - Hookified options","url":"/docs/library/#constructor"},{"id":"/docs/library/#properties","title":"Properties","titles":["Library API","MockHttp Class"],"text":"port : number - Get/set the server port host : string - Get/set the server host autoDetectPort : boolean - Get/set auto-detect port behavior helmet : boolean - Get/set Helmet security headers apiDocs : boolean - Get/set whether the documentation site and OpenAPI spec are served siteDistPath : string - Get/set the path to the built Docula site logging : boolean - Get/set logging enabled state staticFiles : boolean - Get/set whether files from public/ are served pluginTimeout : number | undefined - Get/set Fastify plugin boot timeout startBins : boolean - Get/set whether bin cleanup starts during initialize() rateLimit : RateLimitPluginOptions | undefined - Get/set rate limiting options httpBin : HttpBinOptions - Get/set httpbin route options https : HttpsOptions | undefined - Get/set HTTPS configuration isHttps : boolean - Whether the server is running with HTTPS http2 : boolean - Get/set HTTP/2 support http1 : boolean - Get/set HTTP/1.1 fallback for HTTP/2 with HTTPS server : FastifyInstance - Get/set the Fastify server instance taps : TapManager - Get/set the TapManager instance bins : BinManager - Get/set the BinManager instance for request bins","url":"/docs/library/#properties"},{"id":"/docs/library/#methods","title":"Methods","titles":["Library API","MockHttp Class"],"text":"","url":"/docs/library/#methods"},{"id":"/docs/library/#async-initialize","title":"async initialize()","titles":["Library API","MockHttp Class","Methods"],"text":"Register plugins and routes without listening. Use server.inject() afterwards, or call start() to bind a port.","url":"/docs/library/#async-initialize"},{"id":"/docs/library/#async-start","title":"async start()","titles":["Library API","MockHttp Class","Methods"],"text":"Start the Fastify server. If already running, it will be closed and restarted.","url":"/docs/library/#async-start"},{"id":"/docs/library/#async-close","title":"async close()","titles":["Library API","MockHttp Class","Methods"],"text":"Stop the Fastify server.","url":"/docs/library/#async-close"},{"id":"/docs/library/#async-detectport","title":"async detectPort()","titles":["Library API","MockHttp Class","Methods"],"text":"Detect the next available port. Returns: number - The available port","url":"/docs/library/#async-detectport"},{"id":"/docs/library/#async-registerapidocsfastifyinstance","title":"async registerApiDocs(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register OpenAPI generation and the Docula documentation site.","url":"/docs/library/#async-registerapidocsfastifyinstance"},{"id":"/docs/library/#async-registerswaggerfastifyinstance","title":"async registerSwagger(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register @fastify/swagger and the live /openapi.json spec route.","url":"/docs/library/#async-registerswaggerfastifyinstance"},{"id":"/docs/library/#async-registersitefastifyinstance","title":"async registerSite(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Serve the built Docula site from siteDistPath when the directory exists.","url":"/docs/library/#async-registersitefastifyinstance"},{"id":"/docs/library/#async-registerhttpmethodsfastifyinstance","title":"async registerHttpMethods(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register HTTP method routes (GET, POST, PUT, PATCH, DELETE).","url":"/docs/library/#async-registerhttpmethodsfastifyinstance"},{"id":"/docs/library/#async-registerstatuscoderoutesfastifyinstance","title":"async registerStatusCodeRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register status code routes.","url":"/docs/library/#async-registerstatuscoderoutesfastifyinstance"},{"id":"/docs/library/#async-registerrequestinspectionroutesfastifyinstance","title":"async registerRequestInspectionRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register request inspection routes (headers, ip, user-agent).","url":"/docs/library/#async-registerrequestinspectionroutesfastifyinstance"},{"id":"/docs/library/#async-registerresponseinspectionroutesfastifyinstance","title":"async registerResponseInspectionRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register response inspection routes (cache, etag, response-headers).","url":"/docs/library/#async-registerresponseinspectionroutesfastifyinstance"},{"id":"/docs/library/#async-registerresponseformatroutesfastifyinstance","title":"async registerResponseFormatRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register response format routes (json, xml, html, etc.).","url":"/docs/library/#async-registerresponseformatroutesfastifyinstance"},{"id":"/docs/library/#async-registerredirectroutesfastifyinstance","title":"async registerRedirectRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register redirect routes (absolute, relative, redirect-to).","url":"/docs/library/#async-registerredirectroutesfastifyinstance"},{"id":"/docs/library/#async-registercookieroutesfastifyinstance","title":"async registerCookieRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register cookie routes (get, set, delete).","url":"/docs/library/#async-registercookieroutesfastifyinstance"},{"id":"/docs/library/#async-registeranythingroutesfastifyinstance","title":"async registerAnythingRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register \"anything\" catch-all routes.","url":"/docs/library/#async-registeranythingroutesfastifyinstance"},{"id":"/docs/library/#async-registerauthroutesfastifyinstance","title":"async registerAuthRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register authentication routes (basic, bearer, digest, hidden-basic).","url":"/docs/library/#async-registerauthroutesfastifyinstance"},{"id":"/docs/library/#async-registerimageroutesfastifyinstance","title":"async registerImageRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register image routes (jpeg, png, svg, webp) with content negotiation support.","url":"/docs/library/#async-registerimageroutesfastifyinstance"},{"id":"/docs/library/#async-registerbinroutesfastifyinstance","title":"async registerBinRoutes(fastifyInstance?)","titles":["Library API","MockHttp Class","Methods"],"text":"Register the request bin routes — management at /bins and capture at /b/:id .","url":"/docs/library/#async-registerbinroutesfastifyinstance"},{"id":"/docs/library/#bins-request-capture","title":"Bins (Request Capture)","titles":["Library API"],"text":"Access the BinManager via mockHttp.bins to manage request bins programmatically. See Request Bins for usage examples.","url":"/docs/library/#bins-request-capture"},{"id":"/docs/library/#binscreatebin","title":"bins.createBin()","titles":["Library API","Bins (Request Capture)"],"text":"Create a new bin with the configured TTL. Returns: Bin — { id, createdAt, expiresAt, requestCount }","url":"/docs/library/#binscreatebin"},{"id":"/docs/library/#binsgetbinid","title":"bins.getBin(id)","titles":["Library API","Bins (Request Capture)"],"text":"Look up a bin by id. Returns undefined if the bin does not exist or has expired (and lazily removes the expired entry). Returns: Bin | undefined","url":"/docs/library/#binsgetbinid"},{"id":"/docs/library/#binslistbins","title":"bins.listBins()","titles":["Library API","Bins (Request Capture)"],"text":"List all non-expired bins. Returns: Bin[]","url":"/docs/library/#binslistbins"},{"id":"/docs/library/#binsdeletebinid","title":"bins.deleteBin(id)","titles":["Library API","Bins (Request Capture)"],"text":"Delete a bin and all its captured requests. Returns: boolean — true if the bin existed","url":"/docs/library/#binsdeletebinid"},{"id":"/docs/library/#binsgetrequestsbinid","title":"bins.getRequests(binId)","titles":["Library API","Bins (Request Capture)"],"text":"List captured requests for a bin, newest first. Returns: CapturedRequest[]","url":"/docs/library/#binsgetrequestsbinid"},{"id":"/docs/library/#binsgetrequestbinid-reqid","title":"bins.getRequest(binId, reqId)","titles":["Library API","Bins (Request Capture)"],"text":"Look up a single captured request. Returns: CapturedRequest | undefined","url":"/docs/library/#binsgetrequestbinid-reqid"},{"id":"/docs/library/#binsclearrequestsbinid","title":"bins.clearRequests(binId)","titles":["Library API","Bins (Request Capture)"],"text":"Clear all captured requests in a bin (the bin itself is preserved).","url":"/docs/library/#binsclearrequestsbinid"},{"id":"/docs/library/#binsrecordrequestbinid-raw","title":"bins.recordRequest(binId, raw)","titles":["Library API","Bins (Request Capture)"],"text":"Manually record a captured request. Returns undefined if the bin does not exist or is expired. Normally invoked by the capture route, but available for programmatic use. Returns: CapturedRequest | undefined","url":"/docs/library/#binsrecordrequestbinid-raw"},{"id":"/docs/library/#binsstart--binsstop","title":"bins.start() / bins.stop()","titles":["Library API","Bins (Request Capture)"],"text":"Start or stop the periodic cleanup of expired bins. MockHttp.start() and MockHttp.close() call these automatically. The interval is unref() 'd so it never keeps the Node process alive.","url":"/docs/library/#binsstart--binsstop"},{"id":"/docs/library/#binsmaxbodysize--binsmaxrequestsperbin--binsdefaultttlms","title":"bins.maxBodySize / bins.maxRequestsPerBin / bins.defaultTtlMs","titles":["Library API","Bins (Request Capture)"],"text":"Read-only getters for the currently-configured limits.","url":"/docs/library/#binsmaxbodysize--binsmaxrequestsperbin--binsdefaultttlms"},{"id":"/docs/library/#taps-response-injection","title":"Taps (Response Injection)","titles":["Library API"],"text":"Access the TapManager via mockHttp.taps to inject custom responses.","url":"/docs/library/#taps-response-injection"},{"id":"/docs/library/#tapsinjectresponse-matcher","title":"taps.inject(response, matcher?)","titles":["Library API","Taps (Response Injection)"],"text":"Injects a custom response for requests matching the criteria. Parameters: response (InjectionResponse | InjectionResponseFunction): Static Response (InjectionResponse): response : string | object | Buffer - The response body statusCode? : number - HTTP status code (default: 200) headers? : object - Response headers Function Response (InjectionResponseFunction): A function that receives the Fastify request object and returns an InjectionResponse (request: FastifyRequest) => InjectionResponse Allows dynamic response generation based on request properties (url, method, headers, etc.) matcher? (InjectionMatcher) - Optional matching criteria: url? : string - URL path (supports wildcards with * ) method? : string - HTTP method (GET, POST, etc.) hostname? : string - Hostname to match headers? : object - Headers that must be present Returns: InjectionTap - A tap object with a unique id that can be used to remove the injection","url":"/docs/library/#tapsinjectresponse-matcher"},{"id":"/docs/library/#tapsremoveinjectiontaporid","title":"taps.removeInjection(tapOrId)","titles":["Library API"],"text":"Removes an injection. Parameters: tapOrId : InjectionTap | string - The tap object or tap ID to remove Returns: boolean - true if removed, false if not found","url":"/docs/library/#tapsremoveinjectiontaporid"},{"id":"/docs/library/#tapsinjections","title":"taps.injections","titles":["Library API","taps.removeInjection(tapOrId)"],"text":"A getter that returns a Map of all active injection taps. Returns: Map<string, InjectionTap> - Map of all active injections with tap IDs as keys","url":"/docs/library/#tapsinjections"},{"id":"/docs/library/#tapsclear","title":"taps.clear()","titles":["Library API"],"text":"Removes all injections.","url":"/docs/library/#tapsclear"},{"id":"/docs/library/#tapshasinjections","title":"taps.hasInjections","titles":["Library API"],"text":"A getter that returns whether there are any active injections. Returns: boolean - true if there are active injections, false otherwise","url":"/docs/library/#tapshasinjections"},{"id":"/docs/hosted/","title":"MockHttp.org Live","titles":[],"text":"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. All mockhttp.org traffic stays on Cloudflare. A separate test app runs the Node server on Wasmer Edge at mockhttp.wasmer.app . Getting Started is served at / and /docs , other guides at /docs/... , and the interactive HTTP API reference at /api . Mock endpoints such as /get and /post are unchanged.","url":"/docs/hosted/"},{"id":"/docs/how-to-deploy/cloudflare/","title":"Cloudflare","titles":[],"text":"MockHTTP runs on Cloudflare as a Worker, not a container. mockhttp.org is this deployment: Workers Assets serve the documentation site, and the Worker handles mock APIs such as /get and /post . The Worker entry is worker/index.ts . It listens with the Node.js compatibility layer and forwards each request into the Fastify app. Configuration lives in wrangler.jsonc .","url":"/docs/how-to-deploy/cloudflare/"},{"id":"/docs/how-to-deploy/cloudflare/#what-the-worker-does-differently","title":"What the Worker does differently","titles":["Cloudflare"],"text":"The Worker starts the same MockHTTP app as Node.js, with a few options set for the Workers runtime: Option Worker value Why rateLimit false @fastify/rate-limit is off. A Cloudflare rate limiting binding allows 1000 requests per 60 seconds per IP. siteDistPath unused path Fastify does not serve the docs. Workers Assets serve site/dist . staticFiles false Logos and other public/ files are copied into site/dist and read through the ASSETS binding. startBins false The bin cleanup timer uses setInterval , which can hang a Worker isolate during startup. Bin routes still register. Expired bins are removed when that bin is read, not by a sweep of every bin. pluginTimeout 0 Disables Fastify's plugin boot timeout. Those timers are unreliable on Workers. logging false Request logging is off. autoDetectPort false The app always listens on port 3000 inside the isolate. The rate limiter key is the cf-connecting-ip header, then the first address in x-forwarded-for , then unknown . A limited request returns 429 with retry-after: 60 . That limiter is shared across isolates. Bins are not. The default store is in memory inside the isolate that handled the request, so a bin created on one request can be missing when another isolate or location handles the next one. Taps are a library API ( mock.taps.inject ). They have no HTTP routes, so a deployed Worker has no way to inject one. Assets are checked before the Worker. A file under site/dist (the docs site, favicon, logos) is served as a static asset. A path that is not a file, such as /get or /post , is handled by the Worker.","url":"/docs/how-to-deploy/cloudflare/#what-the-worker-does-differently"},{"id":"/docs/how-to-deploy/cloudflare/#deploy-your-own-worker","title":"Deploy your own Worker","titles":["Cloudflare"],"text":"You need a Cloudflare account and permission to deploy Workers. This repository pins Wrangler to 4.127.0 . Change name and routes in wrangler.jsonc before you deploy a fork. The route in this repo attaches the custom domain mockhttp.org . workers_dev is enabled, so a *.workers.dev hostname is available as well. Adjust the RATE_LIMITER binding if you want a different limit than 1000 requests per 60 seconds. Also change siteUrl in site/docula.config.ts . The sitemap is a static file, and this repo sets it to https://mockhttp.org . The migrations block records a container class that this Worker no longer uses. A brand-new Worker can omit that block. Wrangler bundles worker/index.ts from source, so you do not need pnpm build for this deploy. pnpm website:build produces site/dist . pnpm install pnpm website:build pnpm prepare:worker-assets npx wrangler@4.127.0 deploy pnpm prepare:worker-assets copies public/ into site/dist so favicon and logo files ship with the docs site. Wrangler reads CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID from the environment when you are not logged in locally. After deploy, open the workers.dev hostname or your custom domain and request /get . The docs are at /docs , and the OpenAPI reference is at /api .","url":"/docs/how-to-deploy/cloudflare/#deploy-your-own-worker"},{"id":"/docs/how-to-deploy/cloudflare/#deploy-from-github-actions","title":"Deploy from GitHub Actions","titles":["Cloudflare"],"text":".github/workflows/deploy-site.yaml deploys this Worker on the released event (a published release, not a prerelease) and when the workflow is started by hand. The production environment provides CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID . The deploy job installs production dependencies, downloads the built site, copies public/ into site/dist , installs Wrangler 4.127.0 , and runs wrangler deploy . That workflow does not deploy the Wasmer app. Docker image publishing is a separate workflow, documented in Docker .","url":"/docs/how-to-deploy/cloudflare/#deploy-from-github-actions"},{"id":"/docs/how-to-deploy/docker/","title":"Docker","titles":[],"text":"The published image is jaredwray/mockhttp on Docker Hub. It runs the Node.js server and the documentation site in one container. The latest tag is linux/amd64 only. Apple Silicon runs it under emulation. On arm64 Linux, build the image from this repository instead.","url":"/docs/how-to-deploy/docker/"},{"id":"/docs/how-to-deploy/docker/#run-the-image","title":"Run the image","titles":["Docker"],"text":"docker run -d -p 3000:3000 jaredwray/mockhttp The server listens on port 3000. Open http://localhost:3000/get for a mock response, http://localhost:3000/docs for these guides, and http://localhost:3000/api for the OpenAPI reference. pnpm docker:run is docker run -p 3000:3000 jaredwray/mockhttp . It stays in the foreground. Docker pulls the Hub image when it is not already local. Rate limiting is on: 1000 requests per minute. The allow list is only 127.0.0.1 and ::1 . A published port delivers traffic from the Docker bridge address, not from loopback inside the container, so those requests count against the limit. None of the environment variables below turn it off. Change or disable it with the library rateLimit option . A test suite that sends more than 1000 requests a minute to the published port will get 429 responses.","url":"/docs/how-to-deploy/docker/#run-the-image"},{"id":"/docs/how-to-deploy/docker/#docker-compose","title":"Docker Compose","titles":["Docker"],"text":"services: mockhttp: image: jaredwray/mockhttp:latest ports: - \"3000:3000\" The Compose file in this repository publishes port 3001 and sets PORT so the process listens on that same port: services: mockhttp: image: jaredwray/mockhttp:latest ports: - \"3001:3001\" environment: - PORT=3001 pnpm docker:compose:up and pnpm docker:compose:down call the docker-compose binary. Current Docker installs often provide docker compose instead, which you can run against the same file.","url":"/docs/how-to-deploy/docker/#docker-compose"},{"id":"/docs/how-to-deploy/docker/#environment-variables","title":"Environment variables","titles":["Docker"],"text":"The container starts node dist/index.mjs . That process reads these variables: Variable Default Effect PORT 3000 Port the server listens on. Match it to the published container port. HOST 0.0.0.0 Bind address. LOGGING enabled Set to false to turn logging off. HTTP2 off Set to true to enable HTTP/2 cleartext (h2c). The image does not load a TLS certificate. AUTO_DETECT_PORT true Set to false to keep PORT even when that port is already in use. HTTPS certificates are configured in the library , not through container environment variables. Put a TLS proxy in front of the container when you need HTTPS.","url":"/docs/how-to-deploy/docker/#environment-variables"},{"id":"/docs/how-to-deploy/docker/#build-the-image","title":"Build the image","titles":["Docker"],"text":"The Dockerfile copies node_modules , package.json , public/ , dist/ , and site/dist/ from the build context. Build the package and the docs site before docker build . pnpm install pnpm build pnpm website:build docker build -t jaredwray/mockhttp . docker run -d -p 3000:3000 jaredwray/mockhttp pnpm docker:build is the docker build step. The image is based on Node.js 24 Alpine, runs as the node user, exposes port 3000, and starts node dist/index.mjs .","url":"/docs/how-to-deploy/docker/#build-the-image"},{"id":"/docs/how-to-deploy/docker/#publish-to-docker-hub","title":"Publish to Docker Hub","titles":["Docker"],"text":".github/workflows/docker-publish.yaml runs on the released event (a published release, not a prerelease) and when the workflow is started by hand. It builds jaredwray/mockhttp:<version> and jaredwray/mockhttp:latest with docker build on ubuntu-latest , pushes both tags, and updates the Docker Hub description from DOCKER.md . That build is linux/amd64 . The same Node server can run on Wasmer Edge . The public site at mockhttp.org is the Cloudflare Worker , not this image.","url":"/docs/how-to-deploy/docker/#publish-to-docker-hub"},{"id":"/docs/how-to-deploy/wasmer/","title":"Wasmer","titles":[],"text":"Wasmer Edge runs the same Node.js server as Docker . The test app for this repository is mockhttp.wasmer.app . This deploy does not publish the Cloudflare Worker . mockhttp.org stays on Cloudflare.","url":"/docs/how-to-deploy/wasmer/"},{"id":"/docs/how-to-deploy/wasmer/#app-configuration","title":"App configuration","titles":["Wasmer"],"text":"app.yaml describes the Edge app: kind: wasmer.io/App.v0 name: mockhttp owner: jaredwray package: . env: HOST: \"0.0.0.0\" LOGGING: \"false\" AUTO_DETECT_PORT: \"false\" package: . deploys the repository directory. HOST binds the server on all interfaces. Logging is off. Wasmer injects PORT . AUTO_DETECT_PORT=false keeps that port instead of scanning for another one. Change name and owner before you deploy your own app. The environment variables are the same ones the Docker image reads ( PORT , HOST , LOGGING , HTTP2 , and AUTO_DETECT_PORT ). See Docker for what each one does.","url":"/docs/how-to-deploy/wasmer/#app-configuration"},{"id":"/docs/how-to-deploy/wasmer/#build-with-anybuild","title":"Build with Anybuild","titles":["Wasmer"],"text":"Anybuild tells Wasmer how to build the package on a remote builder: Node.js 24 and pnpm 12.4.1 Build command: pnpm run build && pnpm website:build Start command: node dist/index.mjs The build command produces dist/ and site/dist/ while Docula is still installed. Wasmer then prunes dev dependencies. The docs site has to exist before that prune, because Docula is a dev dependency.","url":"/docs/how-to-deploy/wasmer/#build-with-anybuild"},{"id":"/docs/how-to-deploy/wasmer/#deploy-from-the-cli","title":"Deploy from the CLI","titles":["Wasmer"],"text":"Install the Wasmer CLI and log in, then from the repository root: wasmer deploy --build-remote --build-remote uploads the source and runs the Anybuild file on Wasmer's builders. When the deploy finishes, the CLI prints the app URL.","url":"/docs/how-to-deploy/wasmer/#deploy-from-the-cli"},{"id":"/docs/how-to-deploy/wasmer/#deploy-from-github-actions","title":"Deploy from GitHub Actions","titles":["Wasmer"],"text":".github/workflows/deploy-wasmer.yaml runs on the released event (a published release, not a prerelease) and when the workflow is started by hand. The wasmer environment provides WASMER_TOKEN . The deploy step runs: wasmer deploy --non-interactive --build-remote","url":"/docs/how-to-deploy/wasmer/#deploy-from-github-actions"},{"id":"/docs/how-to-deploy/wasmer/#runtime-behavior","title":"Runtime behavior","titles":["Wasmer"],"text":"Bins use the default in-memory store, so a bin exists only on the instance that created it. Taps are a library API ( mock.taps.inject ) and have no HTTP routes, so a deployed app cannot inject one. @fastify/rate-limit is on at 1000 requests per minute. It keys on the address that connects to the process. The server does not trust proxy headers, and the allow list is only 127.0.0.1 and ::1 . On the test app, /ip reports 127.0.0.100 , which is the edge proxy rather than the caller, and the response includes x-ratelimit-limit: 1000 . Clients that share that proxy address share one limit on that instance. This is not the Cloudflare limiter used by mockhttp.org . The process listens with HTTP. Wasmer terminates TLS for the *.wasmer.app hostname.","url":"/docs/how-to-deploy/wasmer/#runtime-behavior"},{"id":"/changelog/v2-1-0/","title":"v2.1.0","titles":[],"text":"","url":"/changelog/v2-1-0/"},{"id":"/changelog/v2-1-0/#jaredwraymockhttp210--2026-10-03","title":"@jaredwray/mockhttp@2.1.0 — 2026-10-03","titles":["v2.1.0"],"text":"Add AUTO_DETECT_PORT=false so the process keeps PORT, and include the docs site in the npm package.","url":"/changelog/v2-1-0/#jaredwraymockhttp210--2026-10-03"},{"id":"/changelog/v2-1-0/#features","title":"Features","titles":["v2.1.0","@jaredwray/mockhttp@2.1.0 — 2026-10-03"],"text":"Deploy the Node server to Wasmer Edge (#225) PORT=3000 AUTO_DETECT_PORT= false node dist/index.mjs","url":"/changelog/v2-1-0/#features"},{"id":"/changelog/v2-1-0/#bug-fixes","title":"Bug Fixes","titles":["v2.1.0","@jaredwray/mockhttp@2.1.0 — 2026-10-03"],"text":"include Docula site in the npm tarball (#222) deploy Wasmer with a remote build (#226) deploy Wasmer through the Anybuild file (#228)","url":"/changelog/v2-1-0/#bug-fixes"},{"id":"/changelog/v2-1-0/#documentation","title":"Documentation","titles":["v2.1.0","@jaredwray/mockhttp@2.1.0 — 2026-10-03"],"text":"add Drydock review badge to README (#224) rename Hosted Service page to MockHttp.org Live (#230) add How to Deploy guides for Cloudflare, Docker, and Wasmer (#229)","url":"/changelog/v2-1-0/#documentation"},{"id":"/changelog/v2-1-0/#internal","title":"Internal","titles":["v2.1.0","@jaredwray/mockhttp@2.1.0 — 2026-10-03"],"text":"root - defense - close catalog gaps from current skill (#221) Publish the GitHub Actions build to Wasmer (#227)","url":"/changelog/v2-1-0/#internal"},{"id":"/changelog/v2-1-0/#contributors","title":"Contributors","titles":["v2.1.0","@jaredwray/mockhttp@2.1.0 — 2026-10-03"],"text":"@jaredwray (owner)","url":"/changelog/v2-1-0/#contributors"},{"id":"/changelog/v2-1-0/#full-list-of-changes","title":"Full List of Changes","titles":["v2.1.0","@jaredwray/mockhttp@2.1.0 — 2026-10-03"],"text":"root - chore: defense - close catalog gaps from current skill by @jaredwray in #221 fix: include Docula site in the npm tarball by @jaredwray in #222 docs: add Drydock review badge to README by @jaredwray in #224 Deploy the Node server to Wasmer Edge by @jaredwray in #225 Fix the Wasmer deploy by using a remote build by @jaredwray in #226 Publish the GitHub Actions build to Wasmer by @jaredwray in #227 Deploy Wasmer with the Anybuild file by @jaredwray in #228 docs: rename Hosted Service to MockHttp.org Live by @jaredwray in #230 docs: add How to Deploy guides for Cloudflare, Docker, and Wasmer by @jaredwray in #229 Full diff: https://github.com/jaredwray/mockhttp/compare/v2.0.0...v2.1.0","url":"/changelog/v2-1-0/#full-list-of-changes"},{"id":"/changelog/v2-0-0/","title":"v2.0.0","titles":[],"text":"","url":"/changelog/v2-0-0/"},{"id":"/changelog/v2-0-0/#jaredwraymockhttp200--2026-09-18","title":"@jaredwray/mockhttp@2.0.0 — 2026-09-18","titles":["v2.0.0"],"text":"Replace Scalar with a Docula site, run mockhttp.org on a Worker, and add initialize().","url":"/changelog/v2-0-0/#jaredwraymockhttp200--2026-09-18"},{"id":"/changelog/v2-0-0/#features","title":"Features","titles":["v2.0.0","@jaredwray/mockhttp@2.0.0 — 2026-09-18"],"text":"replace Scalar with a Docula documentation site (#209) # Before 1.10.0 After 1.10.0 GET / → Scalar UI Docula Getting Started GET /docs → Swagger UI Docula docs GET /docs/json → OpenAPI JSON 404 GET /api/ → (none) Interactive OpenAPI GET /openapi.json → (none) Live OpenAPI spec GET /get → unchanged unchanged migrate production deploy from GCP Cloud Run to Cloudflare Containers (#207) run mockhttp.org on a Cloudflare Worker only (#218) const mock = new MockHttp ({ logging : false , autoDetectPort : false , staticFiles : false , pluginTimeout : 0 , startBins : false , }); await mock. initialize (); // register routes without listen() const response = await mock. server . inject ({ method : \"GET\" , url : \"/get\" }); use the Docula docs index as the homepage (#219)","url":"/changelog/v2-0-0/#features"},{"id":"/changelog/v2-0-0/#internal","title":"Internal","titles":["v2.0.0","@jaredwray/mockhttp@2.0.0 — 2026-09-18"],"text":"lower Cloudflare Containers max instances to 3 (#208) upgrade @biomejs/biome 2.5.8 → 2.5.13, vitest 4.1.10 → 5.0.0 (#210) upgrade @swc/core 1.15.47 → 1.16.2, tsdown 0.22.14 → 0.23.0, tsx 4.23.12 → 4.23.13 (#211) upgrade package manager pnpm 11.21.0 → 12.4.1 (#212) upgrade GitHub Actions (codecov, CodeQL, zizmor, Socket Firewall) (#213) pin Dev Container image to javascript-node 5.2.1-24-trixie (#214) upgrade fastify 5.11.3 → 5.12.4, @fastify/helmet 13.1.0 → 13.1.1 (#215) upgrade hookified 3.0.2 → 3.0.3 (#216) pin Docker Node.js runtime image to node:24.20.0-alpine3.24 (#217)","url":"/changelog/v2-0-0/#internal"},{"id":"/changelog/v2-0-0/#contributors","title":"Contributors","titles":["v2.0.0","@jaredwray/mockhttp@2.0.0 — 2026-09-18"],"text":"@jaredwray (13)","url":"/changelog/v2-0-0/#contributors"},{"id":"/changelog/v2-0-0/#full-list-of-changes","title":"Full List of Changes","titles":["v2.0.0","@jaredwray/mockhttp@2.0.0 — 2026-09-18"],"text":"Migrate production deploy from GCP Cloud Run to Cloudflare Containers by @jaredwray in #207 Lower Cloudflare Containers max instances to 3 by @jaredwray in #208 Replace Scalar with a Docula documentation site by @jaredwray in #209 root - chore: upgrade code quality dependencies by @jaredwray in #210 root - chore: upgrade TypeScript and build tooling by @jaredwray in #211 root - chore: upgrade package manager by @jaredwray in #212 root - chore: upgrade GitHub Actions by @jaredwray in #213 root - chore: pin Dev Container images by @jaredwray in #214 root - chore: upgrade fastify dependencies by @jaredwray in #215 root - chore: upgrade hookified by @jaredwray in #216 root - chore: upgrade Docker Node.js runtime image by @jaredwray in #217 Run mockhttp.org on a Cloudflare Worker only by @jaredwray in #218 Use the Docula docs index as the homepage by @jaredwray in #219 Full diff: https://github.com/jaredwray/mockhttp/compare/v1.9.0...v1.10.0","url":"/changelog/v2-0-0/#full-list-of-changes"},{"id":"/changelog/v1-9-0/","title":"v1.9.0","titles":[],"text":"","url":"/changelog/v1-9-0/"},{"id":"/changelog/v1-9-0/#jaredwraymockhttp190--2026-08-19","title":"@jaredwray/mockhttp@1.9.0 — 2026-08-19","titles":["v1.9.0"],"text":"Stable indexed response-format templates, plus security hardening and dependency refreshes.","url":"/changelog/v1-9-0/#jaredwraymockhttp190--2026-08-19"},{"id":"/changelog/v1-9-0/#features","title":"Features","titles":["v1.9.0","@jaredwray/mockhttp@1.9.0 — 2026-08-19"],"text":"add stable response format output via optional template index (#181) # Same index → byte-identical JSON. Omit the index for the previous random pick. curl http://localhost:3000/json/1 curl http://localhost:3000/html/1 curl http://localhost:3000/json/99 # → 404 {\"error\":\"Template index must be between 1 and 5\"}","url":"/changelog/v1-9-0/#features"},{"id":"/changelog/v1-9-0/#bug-fixes","title":"Bug Fixes","titles":["v1.9.0","@jaredwray/mockhttp@1.9.0 — 2026-08-19"],"text":"clone JSON template per request to protect stable output (#181)","url":"/changelog/v1-9-0/#bug-fixes"},{"id":"/changelog/v1-9-0/#internal","title":"Internal","titles":["v1.9.0","@jaredwray/mockhttp@1.9.0 — 2026-08-19"],"text":"assert trailing-slash index requests fail loudly with 404 (#181) land security docs through zizmor (#182) stage npm publishes instead of publishing live (#190) gate staged publishes on Aikido scan-release (#191) prefer tilde ranges for runtime deps (#192) record repository lockdown (#193) remove set-cookie-parser override (#194) remove @ungap/structured-clone override (#195) remove glob override (#196) upgrade @biomejs/biome 2.5.3 → 2.5.8 (#197) upgrade TypeScript 6.0.3 → 7.0.2, tsdown 0.22.2 → 0.22.14, tsx 4.23.0 → 4.23.12, @swc/core 1.15.43 → 1.15.47 (#198) upgrade package manager pnpm 11.20.0 → 11.21.0 (#200) upgrade fastify 5.10.0 → 5.11.3, @fastify/cookie, @fastify/rate-limit, @fastify/static, @fastify/swagger, @fastify/swagger-ui (#201) upgrade @scalar/api-reference 1.62.5 → 1.64.1 (#202) upgrade hookified 3.0.1 → 3.0.2 (#203) prefer caret ranges over tilde (#204) pin Docker Node.js runtime image to node:24.19.0-alpine3.24 (#205)","url":"/changelog/v1-9-0/#internal"},{"id":"/changelog/v1-9-0/#contributors","title":"Contributors","titles":["v1.9.0","@jaredwray/mockhttp@1.9.0 — 2026-08-19"],"text":"@jaredwray (15)","url":"/changelog/v1-9-0/#contributors"},{"id":"/changelog/v1-9-0/#full-list-of-changes","title":"Full List of Changes","titles":["v1.9.0","@jaredwray/mockhttp@1.9.0 — 2026-08-19"],"text":"feat: add stable response format output via optional template index by @jaredwray in #181 mockhttp - chore: defense - land security docs through zizmor by @jaredwray in #182 mockhttp - chore: defense - stage npm publishes instead of publishing live by @jaredwray in #190 mockhttp - chore: defense - gate staged publishes on Aikido scan-release by @jaredwray in #191 mockhttp - chore: defense - prefer tilde ranges for runtime deps by @jaredwray in #192 mockhttp - chore: defense - record repository lockdown by @jaredwray in #193 root - chore: remove set-cookie-parser override by @jaredwray in #194 root - chore: remove @ungap/structured-clone override by @jaredwray in #195 root - chore: remove glob override by @jaredwray in #196 root - chore: upgrade code quality dependencies by @jaredwray in #197 root - chore: upgrade TypeScript and build tooling by @jaredwray in #198 root - chore: upgrade package manager by @jaredwray in #200 root - chore: upgrade fastify dependencies by @jaredwray in #201 root - chore: upgrade @scalar/api-reference by @jaredwray in #202 root - chore: upgrade hookified by @jaredwray in #203 root - chore: defense - prefer caret ranges over tilde by @jaredwray in #204 root - chore: upgrade Docker Node.js runtime image by @jaredwray in #205 Full diff: https://github.com/jaredwray/mockhttp/compare/v1.8.1...v1.9.0","url":"/changelog/v1-9-0/#full-list-of-changes"},{"id":"/changelog/v1-8-1/","title":"v1.8.1","titles":[],"text":"","url":"/changelog/v1-8-1/"},{"id":"/changelog/v1-8-1/#jaredwraymockhttp181--2026-07-18","title":"@jaredwray/mockhttp@1.8.1 — 2026-07-18","titles":["v1.8.1"],"text":"Dependency maintenance: refresh runtime and build dependencies (incl. @fastify/static v10).","url":"/changelog/v1-8-1/#jaredwraymockhttp181--2026-07-18"},{"id":"/changelog/v1-8-1/#internal","title":"Internal","titles":["v1.8.1","@jaredwray/mockhttp@1.8.1 — 2026-07-18"],"text":"update fastify, @fastify/cookie, @fastify/helmet, @fastify/rate-limit, @fastify/swagger, @fastify/swagger-ui to latest ( 62d073a , #174) update @fastify/static to 10 (major) ( 71501e3 , #178) update @scalar/api-reference to latest ( 7efd744 , #176) update hookified to latest ( f46b91a , #177) update @biomejs/biome, @swc/core, tsx to latest ( 68584a6 , #175) update test tooling — vitest, @vitest/coverage-v8 ( c3461d3 , #166)","url":"/changelog/v1-8-1/#internal"},{"id":"/changelog/v1-8-1/#contributors","title":"Contributors","titles":["v1.8.1","@jaredwray/mockhttp@1.8.1 — 2026-07-18"],"text":"@jaredwray (6)","url":"/changelog/v1-8-1/#contributors"},{"id":"/changelog/v1-8-1/#full-list-of-changes","title":"Full List of Changes","titles":["v1.8.1","@jaredwray/mockhttp@1.8.1 — 2026-07-18"],"text":"chore: update test tooling (vitest, @vitest/coverage-v8) by @jaredwray in #166 chore: update fastify, @fastify/cookie, @fastify/helmet, @fastify/rate-limit, @fastify/swagger, @fastify/swagger-ui to latest by @jaredwray in #174 chore: update @biomejs/biome, @swc/core, tsx to latest by @jaredwray in #175 chore: update @scalar/api-reference to latest by @jaredwray in #176 chore: update hookified to latest by @jaredwray in #177 chore: update @fastify/static to 10 (major) by @jaredwray in #178 Full diff: https://github.com/jaredwray/mockhttp/compare/v1.8.0...v1.8.1","url":"/changelog/v1-8-1/#full-list-of-changes"},{"id":"/changelog/v1-8-0/","title":"v1.8.0","titles":[],"text":"","url":"/changelog/v1-8-0/"},{"id":"/changelog/v1-8-0/#jaredwraymockhttp180--2026-06-18","title":"@jaredwray/mockhttp@1.8.0 — 2026-06-18","titles":["v1.8.0"],"text":"Add request bins for capturing and inspecting HTTP requests; refresh runtime and build dependencies.","url":"/changelog/v1-8-0/#jaredwraymockhttp180--2026-06-18"},{"id":"/changelog/v1-8-0/#features","title":"Features","titles":["v1.8.0","@jaredwray/mockhttp@1.8.0 — 2026-06-18"],"text":"add request bins for inspecting captured HTTP requests ( 41e3d20 , #150) Mint an ephemeral URL, send arbitrary requests to it, and read back what was captured — useful for webhook debugging. # Create a bin, send a request to it, then inspect what was captured ID=$(curl -s -X POST http://localhost:3000/bins | jq -r . id ) curl -X POST \"http://localhost:3000/b/ $ID /webhook?source=stripe\" \\ -H 'content-type: application/json' \\ -d '{\"event\":\"payment.succeeded\"}' curl \"http://localhost:3000/bins/ $ID /requests\" | jq","url":"/changelog/v1-8-0/#features"},{"id":"/changelog/v1-8-0/#documentation","title":"Documentation","titles":["v1.8.0","@jaredwray/mockhttp@1.8.0 — 2026-06-18"],"text":"expand Request Bins section with end-to-end examples and API reference ( c860005 , #150)","url":"/changelog/v1-8-0/#documentation"},{"id":"/changelog/v1-8-0/#internal","title":"Internal","titles":["v1.8.0","@jaredwray/mockhttp@1.8.0 — 2026-06-18"],"text":"cover MockHttp bin integration; harden against negative maxRequestsPerBin ( d6356c1 , #150) run deploy-site test and build in parallel, gate deploy on both ( 133115d , #149) upgrade hookified 2.2.0 → 3.0.0 ( 58e0717 , #157) upgrade @scalar/api-reference 1.55.3 → 1.59.3 ( 1209de0 , #156) upgrade @fastify/swagger-ui 5.2.6 → 6.0.0 ( b37285c , #155) upgrade @fastify/rate-limit 10.3.0 → 11.0.0 ( 3c7e14a , #154) upgrade GitHub Actions — checkout v7, codecov-action v7 ( 318c34a , #153) upgrade TypeScript and build tooling — @swc/core, tsx, tsdown ( c474f8d , #152) upgrade code quality dependencies — biome, vitest ( b06c1e6 , #151)","url":"/changelog/v1-8-0/#internal"},{"id":"/changelog/v1-8-0/#contributors","title":"Contributors","titles":["v1.8.0","@jaredwray/mockhttp@1.8.0 — 2026-06-18"],"text":"@jaredwray (11)","url":"/changelog/v1-8-0/#contributors"},{"id":"/changelog/v1-8-0/#full-list-of-changes","title":"Full List of Changes","titles":["v1.8.0","@jaredwray/mockhttp@1.8.0 — 2026-06-18"],"text":"ci(deploy-site): run test and build in parallel by @jaredwray in #149 feat: add request bins for inspecting captured HTTP requests by @jaredwray in #150 root - chore: upgrade code quality dependencies by @jaredwray in #151 root - chore: upgrade TypeScript and build tooling by @jaredwray in #152 root - chore: upgrade GitHub Actions (breaking) by @jaredwray in #153 root - chore: upgrade @fastify/rate-limit (breaking) by @jaredwray in #154 root - chore: upgrade @fastify/swagger-ui (breaking) by @jaredwray in #155 root - chore: upgrade @scalar/api-reference by @jaredwray in #156 root - chore: upgrade hookified (breaking) by @jaredwray in #157 Full diff: https://github.com/jaredwray/mockhttp/compare/v1.6.1...v1.7.0","url":"/changelog/v1-8-0/#full-list-of-changes"},{"id":"/changelog/v1-7-0/","title":"v1.7.0","titles":[],"text":"","url":"/changelog/v1-7-0/"},{"id":"/changelog/v1-7-0/#jaredwraymockhttp161--2026-05-18","title":"@jaredwray/mockhttp@1.6.1 — 2026-05-18","titles":["v1.7.0"],"text":"Routine maintenance: dependency refresh (fastify, @scalar/api-reference, hookified), pnpm 11 supply-chain baseline, and GitHub Actions major upgrades.","url":"/changelog/v1-7-0/#jaredwraymockhttp161--2026-05-18"},{"id":"/changelog/v1-7-0/#internal","title":"Internal","titles":["v1.7.0","@jaredwray/mockhttp@1.6.1 — 2026-05-18"],"text":"upgrade hookified 2.1.1 → 2.2.0 ( e431858 , #147) upgrade @scalar/api-reference 1.52.1 → 1.55.3 ( e07afea , #146) upgrade @fastify/static 9.1.0→9.1.3, @fastify/swagger-ui 5.2.5→5.2.6, fastify 5.8.4→5.8.5 ( bcfddf6 , #145) upgrade GitHub Actions to latest majors (checkout v6, setup-node v6, upload-artifact v7, download-artifact v8, codeql v4, etc.) ( a47cf91 , #144) bump engines.node to >=22.18.0 for tsdown 0.22.0 ( 5ab1512 , #143) upgrade TypeScript 6.0.2 → 6.0.3, tsdown 0.21.7 → 0.22.0, @swc/core 1.15.24 → 1.15.33 ( 5cef6c7 , #143) upgrade Biome 2.4.11 → 2.4.15 and Vitest 4.1.4 → 4.1.6 ( edfdf90 , #142) disable setup-node v5 package-manager-cache to fix corepack ordering ( 8bf7cd1 , #141) address review feedback on pnpm 11 upgrade ( ca65ce5 , #141) upgrade to pnpm 11 via corepack with defense-in-depth workspace baseline ( 1d93b64 , #141)","url":"/changelog/v1-7-0/#internal"},{"id":"/changelog/v1-7-0/#contributors","title":"Contributors","titles":["v1.7.0","@jaredwray/mockhttp@1.6.1 — 2026-05-18"],"text":"@jaredwray (10)","url":"/changelog/v1-7-0/#contributors"},{"id":"/changelog/v1-7-0/#full-list-of-changes","title":"Full List of Changes","titles":["v1.7.0","@jaredwray/mockhttp@1.6.1 — 2026-05-18"],"text":"chore: upgrade to pnpm 11 via corepack with defense-in-depth workspace by @jaredwray in #141 root - chore: upgrade code quality dependencies by @jaredwray in #142 root - chore: upgrade TypeScript and build tooling by @jaredwray in #143 root - chore: upgrade GitHub Actions (breaking) by @jaredwray in #144 root - chore: upgrade fastify dependencies by @jaredwray in #145 root - chore: upgrade @scalar/api-reference by @jaredwray in #146 root - chore: upgrade hookified by @jaredwray in #147 Full diff: https://github.com/jaredwray/mockhttp/compare/v1.6.0...v1.6.1","url":"/changelog/v1-7-0/#full-list-of-changes"},{"id":"/changelog/v1-6-0/","title":"v1.6.0","titles":[],"text":"","url":"/changelog/v1-6-0/"},{"id":"/changelog/v1-6-0/#jaredwraymockhttp160--2026-05-16","title":"@jaredwray/mockhttp@1.6.0 — 2026-05-16","titles":["v1.6.0"],"text":"Flexible URL matching: trailing path segments fall back to the parsable route prefix (fixes #137).","url":"/changelog/v1-6-0/#jaredwraymockhttp160--2026-05-16"},{"id":"/changelog/v1-6-0/#features","title":"Features","titles":["v1.6.0","@jaredwray/mockhttp@1.6.0 — 2026-05-16"],"text":"ignore trailing path segments after the parsable portion ( 6f82897 , #139) A Fastify rewriteUrl hook progressively strips trailing segments when only the static catch-all wildcard or nothing matches. Query strings are preserved and the first path segment is never stripped, so genuinely unknown URLs still 404. # Before — only an exact match worked: GET /status/429 → 429 GET /status/429/foo → 404 # After — trailing segments fall back to the parsable prefix: GET /status/429 → 429 GET /status/429/foo → 429 (served by /status/:code) GET /status/429/foo/bar/ → 429 GET /status/429?x=1 → 429 (query preserved) GET /totally/unknown → 404 (first segment never stripped)","url":"/changelog/v1-6-0/#features"},{"id":"/changelog/v1-6-0/#documentation","title":"Documentation","titles":["v1.6.0","@jaredwray/mockhttp@1.6.0 — 2026-05-16"],"text":"document flexible URL matching behavior in the README ( 148ed17 , #139)","url":"/changelog/v1-6-0/#documentation"},{"id":"/changelog/v1-6-0/#internal","title":"Internal","titles":["v1.6.0","@jaredwray/mockhttp@1.6.0 — 2026-05-16"],"text":"extract query string before initial route check; add trailing-slash path coverage ( 5f298ea , #139) fix typos in README and src/swagger.ts ( be2b014 , #138)","url":"/changelog/v1-6-0/#internal"},{"id":"/changelog/v1-6-0/#contributors","title":"Contributors","titles":["v1.6.0","@jaredwray/mockhttp@1.6.0 — 2026-05-16"],"text":"@jaredwray — #139 @mrazauskas — #138 (first contribution 🎉) Full diff: https://github.com/jaredwray/mockhttp/compare/v1.5.1...v1.6.0","url":"/changelog/v1-6-0/#contributors"},{"id":"/changelog/v1-5-1/","title":"v1.5.1","titles":[],"text":"","url":"/changelog/v1-5-1/"},{"id":"/changelog/v1-5-1/#whats-changed","title":"What's Changed","titles":["v1.5.1"],"text":"chore: upgrading biome, vitest, swc to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/130 chore: upgrading fastify to 5.8.4 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/131 chore: upgrading hookified to 2.1.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/132 chore: upgrading @scalar/api-reference to 1.52.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/133 chore: migrating from tsup to tsdown by @jaredwray in https://github.com/jaredwray/mockhttp/pull/134 chore: updating all github actions by @jaredwray in https://github.com/jaredwray/mockhttp/pull/135 fix: docker publish and updating tsdown by @jaredwray in https://github.com/jaredwray/mockhttp/pull/136 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.5.0...v1.5.1","url":"/changelog/v1-5-1/#whats-changed"},{"id":"/changelog/v1-5-0/","title":"v1.5.0","titles":[],"text":"","url":"/changelog/v1-5-0/"},{"id":"/changelog/v1-5-0/#whats-changed","title":"What's Changed","titles":["v1.5.0"],"text":"chore: upgrading swc, biome, vitest, and rimraf by @jaredwray in https://github.com/jaredwray/mockhttp/pull/127 chore: upgrading fastify and scalar by @jaredwray in https://github.com/jaredwray/mockhttp/pull/128 feat: adding in http2 support by @jaredwray in https://github.com/jaredwray/mockhttp/pull/129 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.4.0...v1.5.0","url":"/changelog/v1-5-0/#whats-changed"},{"id":"/changelog/v1-4-0/","title":"v1.4.0","titles":[],"text":"","url":"/changelog/v1-4-0/"},{"id":"/changelog/v1-4-0/#whats-changed","title":"What's Changed","titles":["v1.4.0"],"text":"chore: removing route export files from code coverage by @jaredwray in https://github.com/jaredwray/mockhttp/pull/117 chore: upgrading vitest and support modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/118 chore: upgrading fastify and supporting modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/119 chore: upgrading pino to 10.3.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/120 chore: upgrading hookified to 1.15.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/121 feat: adding mock certificate support for ssl testing by @jaredwray in https://github.com/jaredwray/mockhttp/pull/123 feat: adding mock certificate support for ssl testing by @jaredwray in https://github.com/jaredwray/mockhttp/pull/122 chore: getting test coverage back to normal levels by @jaredwray in https://github.com/jaredwray/mockhttp/pull/124 feat: adding in https support in docs by @jaredwray in https://github.com/jaredwray/mockhttp/pull/125 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.3.0...v1.4.0","url":"/changelog/v1-4-0/#whats-changed"},{"id":"/changelog/v1-3-0/","title":"v1.3.0","titles":[],"text":"","url":"/changelog/v1-3-0/"},{"id":"/changelog/v1-3-0/#whats-changed","title":"What's Changed","titles":["v1.3.0"],"text":"fix: [Aikido] Fix security issue in glob via minor version upgrade from 11.0.3 to 11.1.0 by @aikido-autofix[bot] in https://github.com/jaredwray/mockhttp/pull/107 chore: upgrading vitest to 4.0.16 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/109 chore: upgrading hookified to 1.15.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/110 chore: upgrading pino to 10.1.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/111 chore: upgrading fastify modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/112 feat: adding in meta descriptions by @jaredwray in https://github.com/jaredwray/mockhttp/pull/113 chore: pin set-cookie-parser to 2.7.2 to mitigate prototype pollution by @jaredwray in https://github.com/jaredwray/mockhttp/pull/114 feat: implement httpbin Dynamic Data endpoints by @jaredwray in https://github.com/jaredwray/mockhttp/pull/115","url":"/changelog/v1-3-0/#whats-changed"},{"id":"/changelog/v1-3-0/#new-contributors","title":"New Contributors","titles":["v1.3.0"],"text":"@aikido-autofix[bot] made their first contribution in https://github.com/jaredwray/mockhttp/pull/107 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.2.0...v1.3.0","url":"/changelog/v1-3-0/#new-contributors"},{"id":"/changelog/v1-2-0/","title":"v1.2.0","titles":[],"text":"","url":"/changelog/v1-2-0/"},{"id":"/changelog/v1-2-0/#whats-changed","title":"What's Changed","titles":["v1.2.0"],"text":"chore: moving to nodejs 24 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/100 chore: upgradint tsup to 8.5.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/101 chore: upgrading hookified to 1.14.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/102 chore: upgrading vitest to 4.0.15 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/103 chore: upgrading @scalar/api-reference to 1.40.4 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/104 chore: upgrading @biomejs/biome to 2.3.8 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/105 feat: ability to disable logging by @jaredwray in https://github.com/jaredwray/mockhttp/pull/106 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.1.0...v1.2.0","url":"/changelog/v1-2-0/#whats-changed"},{"id":"/changelog/v1-1-0/","title":"v1.1.0","titles":[],"text":"","url":"/changelog/v1-1-0/"},{"id":"/changelog/v1-1-0/#whats-changed","title":"What's Changed","titles":["v1.1.0"],"text":"chore: removing minify as it causes debugging issues by @jaredwray in https://github.com/jaredwray/mockhttp/pull/91 fix: updating readme with correct spelling by @jaredwray in https://github.com/jaredwray/mockhttp/pull/92 chore: upgrading vitest to 4.0.8 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/93 chore: upgrading pino to 10.1.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/94 chore: upgrading hookified to 1.13.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/95 chore: upgrading fastify to 5.6.2 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/96 feat: adding in image routes by @jaredwray in https://github.com/jaredwray/mockhttp/pull/97 feat: adding in rate limit options by @jaredwray in https://github.com/jaredwray/mockhttp/pull/98 feat: making rate limiting enabled by default by @jaredwray in https://github.com/jaredwray/mockhttp/pull/99 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.0.1...v1.1.0","url":"/changelog/v1-1-0/#whats-changed"},{"id":"/changelog/v1-0-1/","title":"v1.0.1","titles":[],"text":"","url":"/changelog/v1-0-1/"},{"id":"/changelog/v1-0-1/#whats-changed","title":"What's Changed","titles":["v1.0.1"],"text":"fix: delete endpoing allows string, JSON, or any by @jaredwray in https://github.com/jaredwray/mockhttp/pull/90 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v1.0.0...v1.0.1","url":"/changelog/v1-0-1/#whats-changed"},{"id":"/changelog/v1-0-0/","title":"v1.0.0","titles":[],"text":"","url":"/changelog/v1-0-0/"},{"id":"/changelog/v1-0-0/#whats-changed","title":"What's Changed","titles":["v1.0.0"],"text":"fix: docker no longer runs as default user by @jaredwray in https://github.com/jaredwray/mockhttp/pull/80 chore: upgrading @biomejs/biome to 2.2.5 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/81 chore: upgrading pino to 10.0.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/82 chore: upgrading hookified to 1.12.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/83 chore: upgrading fastify to 5.6.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/84 feat: adding in injection taps by @jaredwray in https://github.com/jaredwray/mockhttp/pull/85 fix: delete should allow strings or json to be passed by @jaredwray in https://github.com/jaredwray/mockhttp/pull/86 feat: adding minification to build by @jaredwray in https://github.com/jaredwray/mockhttp/pull/87 feat: adding function for tap injections by @jaredwray in https://github.com/jaredwray/mockhttp/pull/88 feat: updating documentation for taps by @jaredwray in https://github.com/jaredwray/mockhttp/pull/89 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.9.0...v1.0.0","url":"/changelog/v1-0-0/#whats-changed"},{"id":"/changelog/v0-9-0/","title":"v0.9.0","titles":[],"text":"","url":"/changelog/v0-9-0/"},{"id":"/changelog/v0-9-0/#whats-changed","title":"What's Changed","titles":["v0.9.0"],"text":"feat: adding in multiple http methods for plain, html, and text by @jaredwray in https://github.com/jaredwray/mockhttp/pull/78 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.8.0...v0.9.0","url":"/changelog/v0-9-0/#whats-changed"},{"id":"/changelog/v0-8-0/","title":"v0.8.0","titles":[],"text":"","url":"/changelog/v0-8-0/"},{"id":"/changelog/v0-8-0/#whats-changed","title":"What's Changed","titles":["v0.8.0"],"text":"feat: adding in plain endpoint by @jaredwray in https://github.com/jaredwray/mockhttp/pull/74 feat: adding in text endpoint by @jaredwray in https://github.com/jaredwray/mockhttp/pull/75 feat: adding in html endpoint by @jaredwray in https://github.com/jaredwray/mockhttp/pull/76 fix: removing eslint by @jaredwray in https://github.com/jaredwray/mockhttp/pull/77 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.7.0...v0.8.0","url":"/changelog/v0-8-0/#whats-changed"},{"id":"/changelog/v0-7-0/","title":"v0.7.0","titles":[],"text":"","url":"/changelog/v0-7-0/"},{"id":"/changelog/v0-7-0/#whats-changed","title":"What's Changed","titles":["v0.7.0"],"text":"feat: adding in custom traffic badge by @jaredwray in https://github.com/jaredwray/mockhttp/pull/65 feat: adding in auth with basic, bearer, digest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/66 chore: upgrading typescript to 5.9.2 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/67 chore: upgrading codecov to v5 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/68 chore: upgrading pino to 9.9.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/69 chore: upgrading hookified to 1.12.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/70 chore: upgrading fastify to 5.5.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/71 chore: migrating from xo to biome by @jaredwray in https://github.com/jaredwray/mockhttp/pull/72 fix: adding error on warnings for biome check by @jaredwray in https://github.com/jaredwray/mockhttp/pull/73 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.6.1...v0.6.2","url":"/changelog/v0-7-0/#whats-changed"},{"id":"/changelog/v0-6-1/","title":"v0.6.1","titles":[],"text":"","url":"/changelog/v0-6-1/"},{"id":"/changelog/v0-6-1/#whats-changed","title":"What's Changed","titles":["v0.6.1"],"text":"chore: adding in min for cloud run by @jaredwray in https://github.com/jaredwray/mockhttp/pull/60 chore: upgrading xo to 1.2.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/61 chore: upgrading vitest to 3.2.4 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/62 chore: upgrading @scalar/api-reference to 1.32.9 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/63 chore: upgrading hookified to 1.10.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/64 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.6.0...v0.6.1","url":"/changelog/v0-6-1/#whats-changed"},{"id":"/changelog/v0-6-0/","title":"v0.6.0","titles":[],"text":"","url":"/changelog/v0-6-0/"},{"id":"/changelog/v0-6-0/#whats-changed","title":"What's Changed","titles":["v0.6.0"],"text":"fix: adding in application/json for return time on cookies by @jaredwray in https://github.com/jaredwray/mockhttp/pull/52 chore: upgrading vitest to 3.2.3 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/53 chore: upgrading tsup to 8.5.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/54 chore: upgrading pino to 9.7.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/55 chore: upgrading hookified to 1.9.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/56 chore: upgrading xo to 1.1.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/57 chore: upgrading fastify to 5.4.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/58 feat: adding in the anything route from httpbin by @jaredwray in https://github.com/jaredwray/mockhttp/pull/59 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.5.0...v0.6.0","url":"/changelog/v0-6-0/#whats-changed"},{"id":"/changelog/v0-5-0/","title":"v0.5.0","titles":[],"text":"","url":"/changelog/v0-5-0/"},{"id":"/changelog/v0-5-0/#whats-changed","title":"What's Changed","titles":["v0.5.0"],"text":"chore: updating github actions and scripts by @jaredwray in https://github.com/jaredwray/mockhttp/pull/45 chore: upgrading @swc/core and tsx to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/46 chore: upgrading vitest to 3.1.3 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/47 chore: upgrading hookified to 1.9.0 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/48 chore: upgrading fastify to 5.3.2 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/49 feat: moving docker to get external packaging by @jaredwray in https://github.com/jaredwray/mockhttp/pull/50 feat: adding in cookies from httpbin by @jaredwray in https://github.com/jaredwray/mockhttp/pull/51 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.4.3...v0.5.0","url":"/changelog/v0-5-0/#whats-changed"},{"id":"/changelog/v0-4-3/","title":"v0.4.3","titles":[],"text":"","url":"/changelog/v0-4-3/"},{"id":"/changelog/v0-4-3/#whats-changed","title":"What's Changed","titles":["v0.4.3"],"text":"fix: fixing workflows to use npm for docker by @jaredwray in https://github.com/jaredwray/mockhttp/pull/44 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.4.2...v0.4.3","url":"/changelog/v0-4-3/#whats-changed"},{"id":"/changelog/v0-4-2/","title":"v0.4.2","titles":[],"text":"","url":"/changelog/v0-4-2/"},{"id":"/changelog/v0-4-2/#whats-changed","title":"What's Changed","titles":["v0.4.2"],"text":"fix: updating the description in swagger definition by @jaredwray in https://github.com/jaredwray/mockhttp/pull/34 feat: adding in auto port detection by @jaredwray in https://github.com/jaredwray/mockhttp/pull/35 chore: migrating to pnpm for workflows by @jaredwray in https://github.com/jaredwray/mockhttp/pull/36 chore: upgrading vitest to 3.1.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/37 chore: upgrading typescript to 5.8.3 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/38 chore: upgrading hookified to 1.8.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/39 chore: upgrading fastify to 5.2.2 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/40 chore: upgrading @swc/core to 1.11.16 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/41 chore: upgrading @scalar/api-reference to 1.28.12 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/42 feat: adding in docker compose example by @jaredwray in https://github.com/jaredwray/mockhttp/pull/43 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.4.1...v0.4.2","url":"/changelog/v0-4-2/#whats-changed"},{"id":"/changelog/v0-4-1/","title":"v0.4.1","titles":[],"text":"","url":"/changelog/v0-4-1/"},{"id":"/changelog/v0-4-1/#whats-changed","title":"What's Changed","titles":["v0.4.1"],"text":"chore: upgrading tsup, tsx, and typescript to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/29 chore: upgrading vitest to 3.0.7 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/30 chore: upgrading hookified to 1.7.1 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/31 chore: upgrading swc to 1.11.5 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/32 chore: upgrading fastify and scalar modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/33 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.4.0...v0.4.1","url":"/changelog/v0-4-1/#whats-changed"},{"id":"/changelog/v0-4-0/","title":"v0.4.0","titles":[],"text":"","url":"/changelog/v0-4-0/"},{"id":"/changelog/v0-4-0/#whats-changed","title":"What's Changed","titles":["v0.4.0"],"text":"feat: adding in the start of mockhttp class by @jaredwray in https://github.com/jaredwray/mockhttp/pull/28 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.3.0...v0.4.0","url":"/changelog/v0-4-0/#whats-changed"},{"id":"/changelog/v0-3-0/","title":"v0.3.0","titles":[],"text":"","url":"/changelog/v0-3-0/"},{"id":"/changelog/v0-3-0/#whats-changed","title":"What's Changed","titles":["v0.3.0"],"text":"chore: upgrading vitest to 3.0.4 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/21 chore: upgrading typescript to 5.7.3 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/22 chore: upgrading tsup and scalar to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/23 chore: upgrading fastify to 5.2.1 and modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/24 feat: moving concurrency on cloud run to 500 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/25 feat: adding in description on main page by @jaredwray in https://github.com/jaredwray/mockhttp/pull/26 feat: adding in redirects by @jaredwray in https://github.com/jaredwray/mockhttp/pull/27 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.2.3...v0.3.0","url":"/changelog/v0-3-0/#whats-changed"},{"id":"/changelog/v0-2-3/","title":"v0.2.3","titles":[],"text":"","url":"/changelog/v0-2-3/"},{"id":"/changelog/v0-2-3/#whats-changed","title":"What's Changed","titles":["v0.2.3"],"text":"removing CORS as its is not needed by @jaredwray in https://github.com/jaredwray/mockhttp/pull/17 feat: adding in robots.txt file by @jaredwray in https://github.com/jaredwray/mockhttp/pull/18 feat: adding in sitemap.xml by @jaredwray in https://github.com/jaredwray/mockhttp/pull/19 chore: upgrading modules to latest by @jaredwray in https://github.com/jaredwray/mockhttp/pull/20 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.2.2...v0.2.3","url":"/changelog/v0-2-3/#whats-changed"},{"id":"/changelog/v0-2-2/","title":"v0.2.2","titles":[],"text":"","url":"/changelog/v0-2-2/"},{"id":"/changelog/v0-2-2/#whats-changed","title":"What's Changed","titles":["v0.2.2"],"text":"Adding in docker description and CORS for allowing logo.svg access","url":"/changelog/v0-2-2/#whats-changed"},{"id":"/changelog/v0-2-1/","title":"v0.2.1","titles":[],"text":"","url":"/changelog/v0-2-1/"},{"id":"/changelog/v0-2-1/#whats-changed","title":"What's Changed","titles":["v0.2.1"],"text":"moving to logging on a single line by @jaredwray in https://github.com/jaredwray/mockhttp/pull/15 upgrading scalar to 1.25.82 by @jaredwray in https://github.com/jaredwray/mockhttp/pull/16 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.2.0...v0.2.1","url":"/changelog/v0-2-1/#whats-changed"},{"id":"/changelog/v0-2-0/","title":"v0.2.0","titles":[],"text":"","url":"/changelog/v0-2-0/"},{"id":"/changelog/v0-2-0/#whats-changed","title":"What's Changed","titles":["v0.2.0"],"text":"response inspection by @jaredwray in https://github.com/jaredwray/mockhttp/pull/14 Full Changelog : https://github.com/jaredwray/mockhttp/compare/v0.1.0...v0.2.0","url":"/changelog/v0-2-0/#whats-changed"}]}
|