@jaredwray/mockhttp 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +6 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var De=Object.defineProperty;var r=(s,e)=>De(s,"name",{value:e,configurable:!0});import I from"process";import qe from"path";import pt from"@fastify/cookie";import ht from"@fastify/helmet";import _e from"@fastify/static";import{fastifySwagger as mt}from"@fastify/swagger";import{detect as ut}from"detect-port";import He from"fastify";import{Hookified as lt}from"hookified";var ce={logger:{transport:{target:"pino-pretty",options:{colorize:!0,translateTime:!0,ignore:"pid,hostname",singleLine:!0}}}};var $e={description:"Will return anything that you send it",tags:["Anything"],response:{200:{type:"object",properties:{args:{type:"object",description:"Route parameters",additionalProperties:!0},data:{type:"object",description:"Request body data",additionalProperties:!0},files:{type:"object",description:"Uploaded files",additionalProperties:!0},form:{type:"object",description:"Form data",additionalProperties:!0},headers:{type:"object",description:"Request headers",additionalProperties:!0},json:{type:"object",description:"Parsed JSON body",additionalProperties:!0},method:{type:"string",description:"HTTP method used"},origin:{type:"string",description:"Origin of the request"},url:{type:"string",description:"Request URL"}},additionalProperties:!1}}},de=r(s=>{let e=r(async(o,a)=>{let i={args:o.query,data:o.body??{},files:o.raw?.files??{},form:o.body??{},headers:o.headers,json:o.body??{},method:o.method,origin:o.headers.origin??o.headers.host??"",url:o.url};await a.send(i)},"handler"),t={schema:$e,validatorCompiler:r(()=>()=>!0,"validatorCompiler")};s.get("/anything",t,e),s.post("/anything",t,e),s.put("/anything",t,e),s.patch("/anything",t,e),s.delete("/anything",t,e)},"anythingRoute");import{Buffer as z}from"buffer";import{timingSafeEqual as Me}from"crypto";var Ae=r(s=>{if(!s||typeof s!="string")return;let e=s.indexOf(" ");if(e===-1)return;let t=s.slice(0,e),o=s.slice(e+1);if(!(t.toLowerCase()!=="basic"||!o))try{let a=z.from(o,"base64").toString("utf8"),i=a.indexOf(":");if(i===-1)return;let n=a.slice(0,i),d=a.slice(i+1);return n===""?void 0:{username:n,password:d}}catch{return}},"parseBasic"),pe=r((s,e)=>{if(s.length!==e.length)return!1;try{return Me(z.from(s,"utf8"),z.from(e,"utf8"))}catch{return!1}},"safeCompare"),Ie={description:"HTTP Basic authentication. Succeeds only if the user/pass provided in the path matches the Basic Authorization header.",tags:["Auth"],params:{type:"object",properties:{user:{type:"string"},passwd:{type:"string"}},required:["user","passwd"]},response:{200:{type:"object",properties:{authenticated:{type:"boolean"},user:{type:"string"}},required:["authenticated","user"]},401:{type:"object",properties:{message:{type:"string"}},required:["message"]}}},U=r(s=>{s.get("/basic-auth/:user/:passwd",{schema:Ie},async(e,t)=>{let{user:o,passwd:a}=e.params;if(!o||typeof o!="string"||typeof a!="string")return t.header("WWW-Authenticate",'Basic realm="mockhttp"'),t.status(401).send({message:"Unauthorized"});let i=Ae(e.headers.authorization);return!i||!pe(i.username,o)||!pe(i.password,a)?(t.header("WWW-Authenticate",'Basic realm="mockhttp"'),t.status(401).send({message:"Unauthorized"})):t.send({authenticated:!0,user:o})})},"basicAuthRoute");var Ee=r(s=>{if(!s)return;let[e,t]=s.split(" ");if(!(!e||e.toLowerCase()!=="bearer"||!t))return t},"parseBearer"),Le={description:"HTTP Bearer authentication. Succeeds if any Bearer token is present unless ?required=true is provided.",tags:["Auth"],querystring:{type:"object",properties:{required:{type:"boolean",default:!0}}},response:{200:{type:"object",properties:{authenticated:{type:"boolean"},token:{type:"string"}},required:["authenticated","token"]},401:{type:"object",properties:{message:{type:"string"}},required:["message"]}}},O=r(s=>{s.get("/bearer",{schema:Le},async(e,t)=>{let o=Ee(e.headers.authorization),i=e.query?.required??!0;return!o&&i?(t.header("WWW-Authenticate","Bearer"),t.status(401).send({message:"Unauthorized"})):o?t.send({authenticated:!0,token:o}):t.send({authenticated:!1,token:""})})},"bearerAuthRoute");import le from"crypto";var w=r(()=>le.randomBytes(16).toString("hex"),"makeNonce"),ze=new Set(["MD5","md5","SHA-256","sha-256","SHA-512","sha-512"]),he=r(s=>{if(!s)return"md5";let e=s.toLowerCase();return e==="md5"?"md5":e==="sha-256"?"sha256":e==="sha-512"?"sha512":"md5"},"hashAlg"),x=r((s,e)=>le.createHash(s).update(e).digest("hex"),"h"),me=r(s=>{if(!s)return;let e=s.indexOf(" ");if(e===-1)return;let t=s.slice(0,e),o=s.slice(e+1);if(!t||t.toLowerCase()!=="digest"||!o)return;let a={},i=[],n="",d=!1;for(let g of o)g==='"'?(d=!d,n+=g):g===","&&!d?(n.trim()&&i.push(n.trim()),n=""):n+=g;if(n.trim()&&i.push(n.trim()),i.length===0)return a;for(let g of i){let h=g.indexOf("=");if(h===-1)continue;let l=g.slice(0,h).trim(),p=g.slice(h+1).trim();p.startsWith('"')&&p.endsWith('"')&&(p=p.slice(1,-1)),a[l]=p}return a},"parseDigest"),ue={description:"HTTP Digest authentication. Mirrors httpbin behavior for testing clients.",tags:["Auth"],params:{type:"object",properties:{qop:{type:"string"},user:{type:"string"},passwd:{type:"string"},algorithm:{type:"string"},stale_after:{type:"string"}},required:["qop","user","passwd"]}},B=r(s=>{s.get("/digest-auth/:qop/:user/:passwd",{schema:ue},async(e,t)=>{let{user:o,passwd:a}=e.params,i="mockhttp",n=w(),d=me(e.headers.authorization);if(!d)return t.header("WWW-Authenticate",`Digest realm="${i}", qop="auth,auth-int", nonce="${n}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"});if(d.username!==o)return t.header("WWW-Authenticate",`Digest realm="${i}", qop="auth,auth-int", nonce="${n}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"});let g="GET",h=d.uri??e.url.replace(/^https?:\/\/[^/]+/,""),l=he(d.algorithm),c=x(l,`${o}:${i}:${a}`),p=x(l,`${g}:${h}`),u="";return u=d.qop?x(l,`${c}:${d.nonce}:${d.nc}:${d.cnonce}:${d.qop}:${p}`):x(l,`${c}:${d.nonce}:${p}`),!d.response||d.response!==u?(t.header("WWW-Authenticate",`Digest realm="${i}", qop="auth,auth-int", nonce="${n}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"})):t.send({authenticated:!0,user:o})}),s.get("/digest-auth/:qop/:user/:passwd/:algorithm",{schema:ue},async(e,t)=>{let{user:o,passwd:a,algorithm:i}=e.params,n="mockhttp",d=ze.has(String(i))?String(i):"MD5",g=w(),h=me(e.headers.authorization);if(!h)return t.header("WWW-Authenticate",`Digest realm="${n}", qop="auth,auth-int", algorithm=${d}, nonce="${g}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"});if(h.username!==o)return t.header("WWW-Authenticate",`Digest realm="${n}", qop="auth,auth-int", algorithm=${d}, nonce="${g}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"});let l="GET",c=h.uri??e.url.replace(/^https?:\/\/[^/]+/,""),p=he(h.algorithm??d),u=x(p,`${o}:${n}:${a}`),m=x(p,`${l}:${c}`),y=h.qop?x(p,`${u}:${h.nonce}:${h.nc}:${h.cnonce}:${h.qop}:${m}`):x(p,`${u}:${h.nonce}:${m}`);return!h.response||h.response!==y?(t.header("WWW-Authenticate",`Digest realm="${n}", qop="auth,auth-int", algorithm=${d}, nonce="${g}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"})):t.send({authenticated:!0,user:o})})},"digestAuthRoute");import{Buffer as Ue}from"buffer";var Oe=r(s=>{if(!s)return;let[e,t]=s.split(" ");if(!(!e||e.toLowerCase()!=="basic"||!t))try{let o=Ue.from(t,"base64").toString("utf8"),a=o.indexOf(":");return a===-1?void 0:{username:o.slice(0,a),password:o.slice(a+1)}}catch{return}},"parseBasic"),Be={description:"HTTP Basic authentication with docs hidden. Mirrors /basic-auth but hides from schema.",tags:["Auth"],hide:!0,params:{type:"object",properties:{user:{type:"string"},passwd:{type:"string"}},required:["user","passwd"]}},F=r(s=>{s.get("/hidden-basic-auth/:user/:passwd",{schema:Be},async(e,t)=>{let{user:o,passwd:a}=e.params,i=Oe(e.headers.authorization);return!i||i.username!==o||i.password!==a?(t.header("WWW-Authenticate",'Basic realm="mockhttp"'),t.status(401).send({message:"Unauthorized"})):t.send({authenticated:!0,user:o})})},"hiddenBasicAuthRoute");var Fe={description:"Delete a cookie",tags:["Cookies"],querystring:{type:"object",properties:{name:{type:"string"}},required:["name"],additionalProperties:!1},response:{204:{type:"null"}}},W=r(s=>{s.delete("/cookies",{schema:Fe},async(e,t)=>{let{name:o}=e.query;return t.clearCookie(o,{path:"/"}),t.status(204).send()})},"deleteCookieRoute");var We={description:"Return cookies from the request",tags:["Cookies"],response:{200:{type:"object",properties:{cookies:{type:"object",additionalProperties:{type:"string"}}},required:["cookies"]}}},N=r(s=>{s.get("/cookies",{schema:We},async(e,t)=>{t.type("application/json"),await t.send({cookies:e.cookies})})},"getCookiesRoute");var Ne={description:"Set a cookie",tags:["Cookies"],body:{type:"object",properties:{name:{type:"string"},value:{type:"string"},expires:{type:"string",format:"date-time"}},required:["name","value"],additionalProperties:!1},response:{200:{type:"object",properties:{cookies:{type:"object",additionalProperties:{type:"string"}}},required:["cookies"]}}},J=r(s=>{s.post("/cookies",{schema:Ne},async(e,t)=>{let{name:o,value:a,expires:i}=e.body;if(i){let n=new Date(i);t.setCookie(o,a,{path:"/",expires:n})}else t.setCookie(o,a,{path:"/"});return t.status(200).send()})},"postCookieRoute");var Je={description:"Handles a DELETE request and returns request information",tags:["HTTP Methods"],body:{oneOf:[{type:"object",additionalProperties:!0,description:"JSON body of the DELETE request"},{type:"string",description:"String body of the DELETE request"}]},response:{200:{type:"object",properties:{method:{type:"string"},headers:{type:"object",additionalProperties:{type:"string"}},body:{oneOf:[{type:"object",additionalProperties:!0},{type:"string"}]}},required:["method","headers","body"]}}},G=r(s=>{s.delete("/delete",{schema:Je},async e=>({method:"DELETE",headers:e.headers,body:e.body}))},"deleteRoute");var Ge={description:"Returns request information for GET requests",tags:["HTTP Methods"],querystring:{type:"object",additionalProperties:!0,properties:{},description:"Query parameters sent in the request"},headers:{type:"object",additionalProperties:!0,properties:{},description:"Headers sent in the request"},response:{200:{type:"object",properties:{method:{type:"string"},headers:{type:"object",additionalProperties:{type:"string"}},queryParams:{type:"object",additionalProperties:{type:"string"}}},required:["method","headers","queryParams"]}}},Y=r(s=>{s.get("/get",{schema:Ge},async(e,t)=>({method:"GET",headers:e.headers,queryParams:e.query}))},"getRoute");var Ye={description:"Handles a PATCH request and returns request information",tags:["HTTP Methods"],body:{type:"object",additionalProperties:!0,description:"The body of the PATCH request"},response:{200:{type:"object",properties:{method:{type:"string"},headers:{type:"object",additionalProperties:{type:"string"}},body:{type:"object",additionalProperties:!0}},required:["method","headers","body"]}}},Z=r(s=>{s.patch("/patch",{schema:Ye},async e=>({method:"PATCH",headers:e.headers,body:e.body}))},"patchRoute");var Ze={description:"Handles a POST request and returns request information",tags:["HTTP Methods"],body:{type:"object",additionalProperties:!0,description:"The body of the POST request"},response:{200:{type:"object",properties:{method:{type:"string"},headers:{type:"object",additionalProperties:{type:"string"}},body:{type:"object",additionalProperties:!0}},required:["method","headers","body"]}}},V=r(s=>{s.post("/post",{schema:Ze},async e=>({method:"POST",headers:e.headers,body:e.body}))},"postRoute");var Ve={description:"Handles a PUT request and returns request information",tags:["HTTP Methods"],body:{type:"object",additionalProperties:!0,description:"The body of the PUT request"},response:{200:{type:"object",properties:{method:{type:"string"},headers:{type:"object",additionalProperties:{type:"string"}},body:{type:"object",additionalProperties:!0}},required:["method","headers","body"]}}},X=r(s=>{s.put("/put",{schema:Ve},async e=>({method:"PUT",headers:e.headers,body:e.body}))},"putRoute");var ge=r(s=>{s.get("/",{schema:{hide:!0}},async(e,t)=>{await t.type("text/html").send(`
|
|
1
|
+
var $e=Object.defineProperty;var r=(s,e)=>$e(s,"name",{value:e,configurable:!0});import I from"process";import qe from"path";import pt from"@fastify/cookie";import ht from"@fastify/helmet";import _e from"@fastify/static";import{fastifySwagger as mt}from"@fastify/swagger";import{detect as ut}from"detect-port";import He from"fastify";import{Hookified as lt}from"hookified";var ce={logger:{transport:{target:"pino-pretty",options:{colorize:!0,translateTime:!0,ignore:"pid,hostname",singleLine:!0}}}};var De={description:"Will return anything that you send it",tags:["Anything"],response:{200:{type:"object",properties:{args:{type:"object",description:"Route parameters",additionalProperties:!0},data:{type:"object",description:"Request body data",additionalProperties:!0},files:{type:"object",description:"Uploaded files",additionalProperties:!0},form:{type:"object",description:"Form data",additionalProperties:!0},headers:{type:"object",description:"Request headers",additionalProperties:!0},json:{type:"object",description:"Parsed JSON body",additionalProperties:!0},method:{type:"string",description:"HTTP method used"},origin:{type:"string",description:"Origin of the request"},url:{type:"string",description:"Request URL"}},additionalProperties:!1}}},de=r(s=>{let e=r(async(o,a)=>{let i={args:o.query,data:o.body??{},files:o.raw?.files??{},form:o.body??{},headers:o.headers,json:o.body??{},method:o.method,origin:o.headers.origin??o.headers.host??"",url:o.url};await a.send(i)},"handler"),t={schema:De,validatorCompiler:r(()=>()=>!0,"validatorCompiler")};s.get("/anything",t,e),s.post("/anything",t,e),s.put("/anything",t,e),s.patch("/anything",t,e),s.delete("/anything",t,e)},"anythingRoute");import{Buffer as U}from"buffer";import{timingSafeEqual as Me}from"crypto";var Ae=r(s=>{if(!s||typeof s!="string")return;let e=s.indexOf(" ");if(e===-1)return;let t=s.slice(0,e),o=s.slice(e+1);if(!(t.toLowerCase()!=="basic"||!o))try{let a=U.from(o,"base64").toString("utf8"),i=a.indexOf(":");if(i===-1)return;let n=a.slice(0,i),d=a.slice(i+1);return n===""?void 0:{username:n,password:d}}catch{return}},"parseBasic"),pe=r((s,e)=>{if(s.length!==e.length)return!1;try{return Me(U.from(s,"utf8"),U.from(e,"utf8"))}catch{return!1}},"safeCompare"),Ie={description:"HTTP Basic authentication. Succeeds only if the user/pass provided in the path matches the Basic Authorization header.",tags:["Auth"],params:{type:"object",properties:{user:{type:"string"},passwd:{type:"string"}},required:["user","passwd"]},response:{200:{type:"object",properties:{authenticated:{type:"boolean"},user:{type:"string"}},required:["authenticated","user"]},401:{type:"object",properties:{message:{type:"string"}},required:["message"]}}},E=r(s=>{s.get("/basic-auth/:user/:passwd",{schema:Ie},async(e,t)=>{let{user:o,passwd:a}=e.params;if(!o||typeof o!="string"||typeof a!="string")return t.header("WWW-Authenticate",'Basic realm="mockhttp"'),t.status(401).send({message:"Unauthorized"});let i=Ae(e.headers.authorization);return!i||!pe(i.username,o)||!pe(i.password,a)?(t.header("WWW-Authenticate",'Basic realm="mockhttp"'),t.status(401).send({message:"Unauthorized"})):t.send({authenticated:!0,user:o})})},"basicAuthRoute");var ze=r(s=>{if(!s)return;let[e,t]=s.split(" ");if(!(!e||e.toLowerCase()!=="bearer"||!t))return t},"parseBearer"),Le={description:"HTTP Bearer authentication. Succeeds if any Bearer token is present unless ?required=true is provided.",tags:["Auth"],querystring:{type:"object",properties:{required:{type:"boolean",default:!0}}},response:{200:{type:"object",properties:{authenticated:{type:"boolean"},token:{type:"string"}},required:["authenticated","token"]},401:{type:"object",properties:{message:{type:"string"}},required:["message"]}}},O=r(s=>{s.get("/bearer",{schema:Le},async(e,t)=>{let o=ze(e.headers.authorization),i=e.query?.required??!0;return!o&&i?(t.header("WWW-Authenticate","Bearer"),t.status(401).send({message:"Unauthorized"})):o?t.send({authenticated:!0,token:o}):t.send({authenticated:!1,token:""})})},"bearerAuthRoute");import le from"crypto";var w=r(()=>le.randomBytes(16).toString("hex"),"makeNonce"),Ue=new Set(["MD5","md5","SHA-256","sha-256","SHA-512","sha-512"]),he=r(s=>{if(!s)return"md5";let e=s.toLowerCase();return e==="md5"?"md5":e==="sha-256"?"sha256":e==="sha-512"?"sha512":"md5"},"hashAlg"),x=r((s,e)=>le.createHash(s).update(e).digest("hex"),"h"),me=r(s=>{if(!s)return;let e=s.indexOf(" ");if(e===-1)return;let t=s.slice(0,e),o=s.slice(e+1);if(!t||t.toLowerCase()!=="digest"||!o)return;let a={},i=[],n="",d=!1;for(let g of o)g==='"'?(d=!d,n+=g):g===","&&!d?(n.trim()&&i.push(n.trim()),n=""):n+=g;if(n.trim()&&i.push(n.trim()),i.length===0)return a;for(let g of i){let h=g.indexOf("=");if(h===-1)continue;let l=g.slice(0,h).trim(),p=g.slice(h+1).trim();p.startsWith('"')&&p.endsWith('"')&&(p=p.slice(1,-1)),a[l]=p}return a},"parseDigest"),ue={description:"HTTP Digest authentication. Mirrors httpbin behavior for testing clients.",tags:["Auth"],params:{type:"object",properties:{qop:{type:"string"},user:{type:"string"},passwd:{type:"string"},algorithm:{type:"string"},stale_after:{type:"string"}},required:["qop","user","passwd"]}},B=r(s=>{s.get("/digest-auth/:qop/:user/:passwd",{schema:ue},async(e,t)=>{let{user:o,passwd:a}=e.params,i="mockhttp",n=w(),d=me(e.headers.authorization);if(!d)return t.header("WWW-Authenticate",`Digest realm="${i}", qop="auth,auth-int", nonce="${n}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"});if(d.username!==o)return t.header("WWW-Authenticate",`Digest realm="${i}", qop="auth,auth-int", nonce="${n}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"});let g="GET",h=d.uri??e.url.replace(/^https?:\/\/[^/]+/,""),l=he(d.algorithm),c=x(l,`${o}:${i}:${a}`),p=x(l,`${g}:${h}`),u="";return u=d.qop?x(l,`${c}:${d.nonce}:${d.nc}:${d.cnonce}:${d.qop}:${p}`):x(l,`${c}:${d.nonce}:${p}`),!d.response||d.response!==u?(t.header("WWW-Authenticate",`Digest realm="${i}", qop="auth,auth-int", nonce="${n}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"})):t.send({authenticated:!0,user:o})}),s.get("/digest-auth/:qop/:user/:passwd/:algorithm",{schema:ue},async(e,t)=>{let{user:o,passwd:a,algorithm:i}=e.params,n="mockhttp",d=Ue.has(String(i))?String(i):"MD5",g=w(),h=me(e.headers.authorization);if(!h)return t.header("WWW-Authenticate",`Digest realm="${n}", qop="auth,auth-int", algorithm=${d}, nonce="${g}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"});if(h.username!==o)return t.header("WWW-Authenticate",`Digest realm="${n}", qop="auth,auth-int", algorithm=${d}, nonce="${g}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"});let l="GET",c=h.uri??e.url.replace(/^https?:\/\/[^/]+/,""),p=he(h.algorithm??d),u=x(p,`${o}:${n}:${a}`),m=x(p,`${l}:${c}`),y=h.qop?x(p,`${u}:${h.nonce}:${h.nc}:${h.cnonce}:${h.qop}:${m}`):x(p,`${u}:${h.nonce}:${m}`);return!h.response||h.response!==y?(t.header("WWW-Authenticate",`Digest realm="${n}", qop="auth,auth-int", algorithm=${d}, nonce="${g}", opaque="${w()}"`),t.status(401).send({message:"Unauthorized"})):t.send({authenticated:!0,user:o})})},"digestAuthRoute");import{Buffer as Ee}from"buffer";var Oe=r(s=>{if(!s)return;let[e,t]=s.split(" ");if(!(!e||e.toLowerCase()!=="basic"||!t))try{let o=Ee.from(t,"base64").toString("utf8"),a=o.indexOf(":");return a===-1?void 0:{username:o.slice(0,a),password:o.slice(a+1)}}catch{return}},"parseBasic"),Be={description:"HTTP Basic authentication with docs hidden. Mirrors /basic-auth but hides from schema.",tags:["Auth"],hide:!0,params:{type:"object",properties:{user:{type:"string"},passwd:{type:"string"}},required:["user","passwd"]}},F=r(s=>{s.get("/hidden-basic-auth/:user/:passwd",{schema:Be},async(e,t)=>{let{user:o,passwd:a}=e.params,i=Oe(e.headers.authorization);return!i||i.username!==o||i.password!==a?(t.header("WWW-Authenticate",'Basic realm="mockhttp"'),t.status(401).send({message:"Unauthorized"})):t.send({authenticated:!0,user:o})})},"hiddenBasicAuthRoute");var Fe={description:"Delete a cookie",tags:["Cookies"],querystring:{type:"object",properties:{name:{type:"string"}},required:["name"],additionalProperties:!1},response:{204:{type:"null"}}},W=r(s=>{s.delete("/cookies",{schema:Fe},async(e,t)=>{let{name:o}=e.query;return t.clearCookie(o,{path:"/"}),t.status(204).send()})},"deleteCookieRoute");var We={description:"Return cookies from the request",tags:["Cookies"],response:{200:{type:"object",properties:{cookies:{type:"object",additionalProperties:{type:"string"}}},required:["cookies"]}}},N=r(s=>{s.get("/cookies",{schema:We},async(e,t)=>{t.type("application/json"),await t.send({cookies:e.cookies})})},"getCookiesRoute");var Ne={description:"Set a cookie",tags:["Cookies"],body:{type:"object",properties:{name:{type:"string"},value:{type:"string"},expires:{type:"string",format:"date-time"}},required:["name","value"],additionalProperties:!1},response:{200:{type:"object",properties:{cookies:{type:"object",additionalProperties:{type:"string"}}},required:["cookies"]}}},G=r(s=>{s.post("/cookies",{schema:Ne},async(e,t)=>{let{name:o,value:a,expires:i}=e.body;if(i){let n=new Date(i);t.setCookie(o,a,{path:"/",expires:n})}else t.setCookie(o,a,{path:"/"});return t.status(200).send()})},"postCookieRoute");var Ge={description:"Handles a DELETE request and returns request information",tags:["HTTP Methods"],response:{200:{type:"object",properties:{method:{type:"string"},headers:{type:"object",additionalProperties:{type:"string"}},body:{oneOf:[{type:"object",additionalProperties:!0},{type:"string"},{type:"null"}]}},required:["method","headers"]}}},J=r(s=>{s.delete("/delete",{schema:Ge},async e=>({method:"DELETE",headers:e.headers,body:e.body}))},"deleteRoute");var Je={description:"Returns request information for GET requests",tags:["HTTP Methods"],querystring:{type:"object",additionalProperties:!0,properties:{},description:"Query parameters sent in the request"},headers:{type:"object",additionalProperties:!0,properties:{},description:"Headers sent in the request"},response:{200:{type:"object",properties:{method:{type:"string"},headers:{type:"object",additionalProperties:{type:"string"}},queryParams:{type:"object",additionalProperties:{type:"string"}}},required:["method","headers","queryParams"]}}},Y=r(s=>{s.get("/get",{schema:Je},async(e,t)=>({method:"GET",headers:e.headers,queryParams:e.query}))},"getRoute");var Ye={description:"Handles a PATCH request and returns request information",tags:["HTTP Methods"],body:{type:"object",additionalProperties:!0,description:"The body of the PATCH request"},response:{200:{type:"object",properties:{method:{type:"string"},headers:{type:"object",additionalProperties:{type:"string"}},body:{type:"object",additionalProperties:!0}},required:["method","headers","body"]}}},Z=r(s=>{s.patch("/patch",{schema:Ye},async e=>({method:"PATCH",headers:e.headers,body:e.body}))},"patchRoute");var Ze={description:"Handles a POST request and returns request information",tags:["HTTP Methods"],body:{type:"object",additionalProperties:!0,description:"The body of the POST request"},response:{200:{type:"object",properties:{method:{type:"string"},headers:{type:"object",additionalProperties:{type:"string"}},body:{type:"object",additionalProperties:!0}},required:["method","headers","body"]}}},V=r(s=>{s.post("/post",{schema:Ze},async e=>({method:"POST",headers:e.headers,body:e.body}))},"postRoute");var Ve={description:"Handles a PUT request and returns request information",tags:["HTTP Methods"],body:{type:"object",additionalProperties:!0,description:"The body of the PUT request"},response:{200:{type:"object",properties:{method:{type:"string"},headers:{type:"object",additionalProperties:{type:"string"}},body:{type:"object",additionalProperties:!0}},required:["method","headers","body"]}}},X=r(s=>{s.put("/put",{schema:Ve},async e=>({method:"PUT",headers:e.headers,body:e.body}))},"putRoute");var ge=r(s=>{s.get("/",{schema:{hide:!0}},async(e,t)=>{await t.type("text/html").send(`
|
|
2
2
|
<!doctype html>
|
|
3
3
|
<html>
|
|
4
4
|
<head>
|
|
@@ -78,7 +78,7 @@ var De=Object.defineProperty;var r=(s,e)=>De(s,"name",{value:e,configurable:!0})
|
|
|
78
78
|
<title>Redirecting...</title>
|
|
79
79
|
<h1>Redirecting...</h1>
|
|
80
80
|
<p>You should be redirected automatically to target URL: <a href="${a}">${a}</a>. If not click the link.</p>
|
|
81
|
-
`),await t.header("Location",a).status(302).type("text/html").send(i)})},"relativeRedirectRoute");var Qe={description:"Returns all headers of the client request",tags:["Request Inspection"],response:{200:{type:"object",properties:{headers:{type:"object",additionalProperties:{type:"string"},description:"All headers of the client request"}},required:["headers"]}}},te=r(s=>{s.get("/headers",{schema:Qe},async e=>{let{headers:t}=e;return{headers:t}})},"headersRoute");var et={description:"Returns the IP address of the client",tags:["Request Inspection"],response:{200:{type:"object",properties:{ip:{type:"string",description:"The IP address of the client"}},required:["ip"]}}},se=r(s=>{s.get("/ip",{schema:et},async e=>{let t=e.headers["cf-connecting-ip"],o=e.headers["x-forwarded-for"],a=e.ip;return{ip:t??(typeof o=="string"?o.split(",")[0].trim():a)}})},"ipRoute");var tt={description:"Returns the User-Agent header of the client request",tags:["Request Inspection"],response:{200:{type:"object",properties:{userAgent:{type:"string",description:"The User-Agent header of the client request"}},required:["userAgent"]}}},oe=r(s=>{s.get("/user-agent",{schema:tt},async e=>({userAgent:e.headers["user-agent"]}))},"userAgentRoute");import{brotliCompressSync as fe,deflateSync as ye,gzipSync as be}from"zlib";var S={description:"Returns random plain text content",tags:["Response Formats"],response:{200:{type:"string",description:"Random plain text content"}}},j={description:"Returns random text content",tags:["Response Formats"],response:{200:{type:"string",description:"Random text content"}}},C={description:"Returns random HTML content",tags:["Response Formats"],response:{200:{type:"string",description:"Random HTML content"}}},P={description:"Returns random XML content",tags:["Response Formats"],response:{200:{type:"string",description:"Random XML content"}}},q={description:"Returns random JSON content",tags:["Response Formats"],response:{200:{type:"object",description:"Random JSON content",additionalProperties:!0}}},_={description:"Returns page denied by robots.txt rules",tags:["Response Formats"],response:{403:{type:"string",description:"Page denied by robots.txt rules"}}},H={description:"Returns GZip-encoded data",tags:["Response Formats"],response:{200:{type:"string",description:"GZip-encoded content"}}}
|
|
81
|
+
`),await t.header("Location",a).status(302).type("text/html").send(i)})},"relativeRedirectRoute");var Qe={description:"Returns all headers of the client request",tags:["Request Inspection"],response:{200:{type:"object",properties:{headers:{type:"object",additionalProperties:{type:"string"},description:"All headers of the client request"}},required:["headers"]}}},te=r(s=>{s.get("/headers",{schema:Qe},async e=>{let{headers:t}=e;return{headers:t}})},"headersRoute");var et={description:"Returns the IP address of the client",tags:["Request Inspection"],response:{200:{type:"object",properties:{ip:{type:"string",description:"The IP address of the client"}},required:["ip"]}}},se=r(s=>{s.get("/ip",{schema:et},async e=>{let t=e.headers["cf-connecting-ip"],o=e.headers["x-forwarded-for"],a=e.ip;return{ip:t??(typeof o=="string"?o.split(",")[0].trim():a)}})},"ipRoute");var tt={description:"Returns the User-Agent header of the client request",tags:["Request Inspection"],response:{200:{type:"object",properties:{userAgent:{type:"string",description:"The User-Agent header of the client request"}},required:["userAgent"]}}},oe=r(s=>{s.get("/user-agent",{schema:tt},async e=>({userAgent:e.headers["user-agent"]}))},"userAgentRoute");import{brotliCompressSync as fe,deflateSync as ye,gzipSync as be}from"zlib";var S={description:"Returns random plain text content",tags:["Response Formats"],response:{200:{type:"string",description:"Random plain text content"}}},j={description:"Returns random text content",tags:["Response Formats"],response:{200:{type:"string",description:"Random text content"}}},C={description:"Returns random HTML content",tags:["Response Formats"],response:{200:{type:"string",description:"Random HTML content"}}},P={description:"Returns random XML content",tags:["Response Formats"],response:{200:{type:"string",description:"Random XML content"}}},q={description:"Returns random JSON content",tags:["Response Formats"],response:{200:{type:"object",description:"Random JSON content",additionalProperties:!0}}},_={description:"Returns page denied by robots.txt rules",tags:["Response Formats"],response:{403:{type:"string",description:"Page denied by robots.txt rules"}}},H={description:"Returns GZip-encoded data",tags:["Response Formats"],response:{200:{type:"string",description:"GZip-encoded content"}}},$={description:"Returns Deflate-encoded data",tags:["Response Formats"],response:{200:{type:"string",description:"Deflate-encoded content"}}},D={description:"Returns Brotli-encoded data",tags:["Response Formats"],response:{200:{type:"string",description:"Brotli-encoded content"}}},z=["The quick brown fox jumps over the lazy dog.","Lorem ipsum dolor sit amet, consectetur adipiscing elit.","To be or not to be, that is the question.","All work and no play makes Jack a dull boy.","The only way to do great work is to love what you do.","In the beginning was the Word, and the Word was with God.","Once upon a time in a galaxy far, far away...","It was the best of times, it was the worst of times.","The journey of a thousand miles begins with a single step.","Knowledge is power. France is bacon."],Re=[`<!DOCTYPE html>
|
|
82
82
|
<html lang="en">
|
|
83
83
|
<head>
|
|
84
84
|
<title>Sample Page</title>
|
|
@@ -202,7 +202,7 @@ var De=Object.defineProperty;var r=(s,e)=>De(s,"name",{value:e,configurable:!0})
|
|
|
202
202
|
<pubDate>${new Date().toUTCString()}</pubDate>
|
|
203
203
|
</item>
|
|
204
204
|
</channel>
|
|
205
|
-
</rss>`],xe=[()=>({message:"Hello from MockHTTP",timestamp:new Date().toISOString(),status:"success",code:200}),()=>({user:{id:1,name:"John Doe",email:"john@example.com",role:"admin",createdAt:"2024-01-15T10:30:00Z"},permissions:["read","write","delete"]}),()=>({products:[{id:101,name:"Laptop",price:999.99,stock:50},{id:102,name:"Mouse",price:29.99,stock:200}],total:2,page:1}),()=>({config:{theme:"dark",language:"en",notifications:{email:!0,push:!1,sms:!1},privacy:{profile:"public",activity:"friends"}}}),()=>({metrics:{cpu:45.2,memory:78.5,disk:62.3,network:{inbound:"1.2MB/s",outbound:"0.8MB/s"},uptime:"15 days",services:[{name:"api",status:"healthy"},{name:"database",status:"healthy"},{name:"cache",status:"warning"}]}})],ke=r(s=>{let e=r(async(l,c)=>{let p=Math.floor(Math.random()*
|
|
205
|
+
</rss>`],xe=[()=>({message:"Hello from MockHTTP",timestamp:new Date().toISOString(),status:"success",code:200}),()=>({user:{id:1,name:"John Doe",email:"john@example.com",role:"admin",createdAt:"2024-01-15T10:30:00Z"},permissions:["read","write","delete"]}),()=>({products:[{id:101,name:"Laptop",price:999.99,stock:50},{id:102,name:"Mouse",price:29.99,stock:200}],total:2,page:1}),()=>({config:{theme:"dark",language:"en",notifications:{email:!0,push:!1,sms:!1},privacy:{profile:"public",activity:"friends"}}}),()=>({metrics:{cpu:45.2,memory:78.5,disk:62.3,network:{inbound:"1.2MB/s",outbound:"0.8MB/s"},uptime:"15 days",services:[{name:"api",status:"healthy"},{name:"database",status:"healthy"},{name:"cache",status:"warning"}]}})],ke=r(s=>{let e=r(async(l,c)=>{let p=Math.floor(Math.random()*z.length),u=z[p];return c.type("text/plain"),u},"plainHandler");s.get("/plain",{schema:S},e),s.post("/plain",{schema:S},e),s.put("/plain",{schema:S},e),s.patch("/plain",{schema:S},e),s.delete("/plain",{schema:S},e);let t=r(async(l,c)=>{let p=Math.floor(Math.random()*z.length),u=z[p];return c.type("text/plain"),u},"textHandler");s.get("/text",{schema:j},t),s.post("/text",{schema:j},t),s.put("/text",{schema:j},t),s.patch("/text",{schema:j},t),s.delete("/text",{schema:j},t);let o=r(async(l,c)=>{let p=Math.floor(Math.random()*Re.length),u=Re[p];return c.type("text/html"),u},"htmlHandler");s.get("/html",{schema:C},o),s.post("/html",{schema:C},o),s.put("/html",{schema:C},o),s.patch("/html",{schema:C},o),s.delete("/html",{schema:C},o);let a=r(async(l,c)=>{let p=Math.floor(Math.random()*we.length),u=we[p];return c.type("application/xml"),u},"xmlHandler");s.get("/xml",{schema:P},a),s.post("/xml",{schema:P},a),s.put("/xml",{schema:P},a),s.patch("/xml",{schema:P},a),s.delete("/xml",{schema:P},a);let i=r(async(l,c)=>{let p=Math.floor(Math.random()*xe.length),u=xe[p],m=u();return c.type("application/json"),m},"jsonHandler");s.get("/json",{schema:q},i),s.post("/json",{schema:q},i),s.put("/json",{schema:q},i),s.patch("/json",{schema:q},i),s.delete("/json",{schema:q},i);let n=r(async(l,c)=>{let p=[`<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
|
|
206
206
|
<html><head>
|
|
207
207
|
<title>403 Forbidden</title>
|
|
208
208
|
</head><body>
|
|
@@ -232,14 +232,14 @@ var De=Object.defineProperty;var r=(s,e)=>De(s,"name",{value:e,configurable:!0})
|
|
|
232
232
|
<hr>
|
|
233
233
|
<small>MockHTTP Server</small>
|
|
234
234
|
</body>
|
|
235
|
-
</html>`],u=Math.floor(Math.random()*p.length),m=p[u];return c.code(403),c.type("text/html"),m},"denyHandler");s.get("/deny",{schema:_},n),s.post("/deny",{schema:_},n),s.put("/deny",{schema:_},n),s.patch("/deny",{schema:_},n),s.delete("/deny",{schema:_},n);let d=r(async(l,c)=>{let p=[{message:"This is GZip compressed data from MockHTTP",timestamp:new Date().toISOString(),compression:"gzip",originalSize:0,compressedSize:0},{title:"Sample Document",content:"Lorem ipsum dolor sit amet, consectetur adipiscing elit. ".repeat(50),metadata:{author:"MockHTTP Server",format:"gzip",version:"1.0"}},{data:Array.from({length:100},(R,f)=>({id:f+1,value:`Item ${f+1}`,description:`This is item number ${f+1} in the dataset`})),info:"Large dataset compressed with GZip"}],u=Math.floor(Math.random()*p.length),m=p[u],y=JSON.stringify(m);m.originalSize!==void 0&&(m.originalSize=Buffer.byteLength(y));let b=be(y);if(m.compressedSize!==void 0){let R={...m,compressedSize:b.length},f=JSON.stringify(R),v=be(f);return c.header("Content-Encoding","gzip"),c.header("Content-Type","application/json"),c.type("application/octet-stream"),v}return c.header("Content-Encoding","gzip"),c.header("Content-Type","application/json"),c.type("application/octet-stream"),b},"gzipHandler");s.get("/gzip",{schema:H},d),s.post("/gzip",{schema:H},d),s.put("/gzip",{schema:H},d),s.patch("/gzip",{schema:H},d),s.delete("/gzip",{schema:H},d);let g=r(async(l,c)=>{let p=[{message:"This is Deflate compressed data from MockHTTP",timestamp:new Date().toISOString(),compression:"deflate",originalSize:0,compressedSize:0},{title:"Deflate Compressed Document",content:"The deflate algorithm is used for compression. ".repeat(40),details:{algorithm:"DEFLATE",method:"zlib deflate",server:"MockHTTP"}},{items:Array.from({length:50},(R,f)=>({index:f,name:`Entry ${f}`,data:`This is test data for entry number ${f}`,timestamp:new Date(Date.now()-f*1e6).toISOString()})),metadata:{compression:"deflate",count:50}}],u=Math.floor(Math.random()*p.length),m=p[u],y=JSON.stringify(m);m.originalSize!==void 0&&(m.originalSize=Buffer.byteLength(y));let b=ye(y);if(m.compressedSize!==void 0){let R={...m,compressedSize:b.length},f=JSON.stringify(R),v=ye(f);return c.header("Content-Encoding","deflate"),c.header("Content-Type","application/json"),c.type("application/octet-stream"),v}return c.header("Content-Encoding","deflate"),c.header("Content-Type","application/json"),c.type("application/octet-stream"),b},"deflateHandler");s.get("/deflate",{schema
|
|
235
|
+
</html>`],u=Math.floor(Math.random()*p.length),m=p[u];return c.code(403),c.type("text/html"),m},"denyHandler");s.get("/deny",{schema:_},n),s.post("/deny",{schema:_},n),s.put("/deny",{schema:_},n),s.patch("/deny",{schema:_},n),s.delete("/deny",{schema:_},n);let d=r(async(l,c)=>{let p=[{message:"This is GZip compressed data from MockHTTP",timestamp:new Date().toISOString(),compression:"gzip",originalSize:0,compressedSize:0},{title:"Sample Document",content:"Lorem ipsum dolor sit amet, consectetur adipiscing elit. ".repeat(50),metadata:{author:"MockHTTP Server",format:"gzip",version:"1.0"}},{data:Array.from({length:100},(R,f)=>({id:f+1,value:`Item ${f+1}`,description:`This is item number ${f+1} in the dataset`})),info:"Large dataset compressed with GZip"}],u=Math.floor(Math.random()*p.length),m=p[u],y=JSON.stringify(m);m.originalSize!==void 0&&(m.originalSize=Buffer.byteLength(y));let b=be(y);if(m.compressedSize!==void 0){let R={...m,compressedSize:b.length},f=JSON.stringify(R),v=be(f);return c.header("Content-Encoding","gzip"),c.header("Content-Type","application/json"),c.type("application/octet-stream"),v}return c.header("Content-Encoding","gzip"),c.header("Content-Type","application/json"),c.type("application/octet-stream"),b},"gzipHandler");s.get("/gzip",{schema:H},d),s.post("/gzip",{schema:H},d),s.put("/gzip",{schema:H},d),s.patch("/gzip",{schema:H},d),s.delete("/gzip",{schema:H},d);let g=r(async(l,c)=>{let p=[{message:"This is Deflate compressed data from MockHTTP",timestamp:new Date().toISOString(),compression:"deflate",originalSize:0,compressedSize:0},{title:"Deflate Compressed Document",content:"The deflate algorithm is used for compression. ".repeat(40),details:{algorithm:"DEFLATE",method:"zlib deflate",server:"MockHTTP"}},{items:Array.from({length:50},(R,f)=>({index:f,name:`Entry ${f}`,data:`This is test data for entry number ${f}`,timestamp:new Date(Date.now()-f*1e6).toISOString()})),metadata:{compression:"deflate",count:50}}],u=Math.floor(Math.random()*p.length),m=p[u],y=JSON.stringify(m);m.originalSize!==void 0&&(m.originalSize=Buffer.byteLength(y));let b=ye(y);if(m.compressedSize!==void 0){let R={...m,compressedSize:b.length},f=JSON.stringify(R),v=ye(f);return c.header("Content-Encoding","deflate"),c.header("Content-Type","application/json"),c.type("application/octet-stream"),v}return c.header("Content-Encoding","deflate"),c.header("Content-Type","application/json"),c.type("application/octet-stream"),b},"deflateHandler");s.get("/deflate",{schema:$},g),s.post("/deflate",{schema:$},g),s.put("/deflate",{schema:$},g),s.patch("/deflate",{schema:$},g),s.delete("/deflate",{schema:$},g);let h=r(async(l,c)=>{let p=[{message:"This is Brotli compressed data from MockHTTP",timestamp:new Date().toISOString(),compression:"br",algorithm:"Brotli",originalSize:0,compressedSize:0},{title:"Brotli Compression Example",description:"Brotli is a generic-purpose lossless compression algorithm that compresses data using a combination of a modern variant of the LZ77 algorithm, Huffman coding and 2nd order context modeling.",content:"Brotli compression typically achieves 20-26% better compression ratios than gzip. ".repeat(10),metadata:{encoding:"br",quality:11,server:"MockHTTP"}},{benchmark:{title:"Compression Benchmark Data",results:Array.from({length:75},(R,f)=>({id:`test-${f}`,name:`Benchmark Test ${f}`,value:Math.random()*1e3,unit:"ms",timestamp:new Date(Date.now()-f*6e4).toISOString()})),summary:{compression:"brotli",totalTests:75,encoding:"br"}}}],u=Math.floor(Math.random()*p.length),m=p[u],y=JSON.stringify(m);m.originalSize!==void 0&&(m.originalSize=Buffer.byteLength(y));let b=fe(y);if(m.compressedSize!==void 0){let R={...m,compressedSize:b.length},f=JSON.stringify(R),v=fe(f);return c.header("Content-Encoding","br"),c.header("Content-Type","application/json"),c.type("application/octet-stream"),v}return c.header("Content-Encoding","br"),c.header("Content-Type","application/json"),c.type("application/octet-stream"),b},"brotliHandler");s.get("/brotli",{schema:D},h),s.post("/brotli",{schema:D},h),s.put("/brotli",{schema:D},h),s.patch("/brotli",{schema:D},h),s.delete("/brotli",{schema:D},h)},"responseFormatRoutes");var st={description:"Handles cache validation and retrieval.",tags:["Response Inspection"],response:{200:{type:"string",description:"The cached content or resource."},304:{type:"null",description:"Indicates the resource has not been modified."}}},ot={description:"Sets a Cache-Control header for n seconds.",tags:["Response Inspection"],params:{type:"object",properties:{value:{type:"integer",description:"Number of seconds to cache the resource."}},required:["value"]},response:{200:{type:"string",description:"Confirmation message for setting cache."}}},re=r(s=>{s.get("/cache",{schema:st},async(e,t)=>{let o=e.headers["if-modified-since"],a=e.headers["if-none-match"];if(o??a){await t.status(304).send();return}await t.send("Cache content or resource response here.")}),s.get("/cache/:value",{schema:ot},async(e,t)=>{let{value:o}=e.params;await t.header("Cache-Control",`max-age=${o}`).send(`Cache-Control set for ${o} seconds.`)})},"cacheRoutes");var rt={description:"Handles ETag-based conditional requests.",tags:["Response Inspection"],params:{type:"object",properties:{etag:{type:"string",description:"The ETag value for the resource."}},required:["etag"]},response:{200:{type:"string",description:"Resource content for matching ETag."},304:{type:"null",description:"Indicates the resource has not been modified."},412:{type:"null",description:"Indicates a precondition failed due to mismatched ETag."}}},ae=r(s=>{s.get("/etag/:etag",{schema:rt},async(e,t)=>{let{etag:o}=e.params,a=e.headers["if-none-match"],i=e.headers["if-match"];if(a===o){await t.status(304).send();return}if(i&&i!==o){await t.status(412).send();return}await t.header("ETag",o).send("Resource content for matching ETag.")})},"etagRoutes");import{escape as M}from"html-escaper";var ve={description:"Returns a set of response headers based on the query string.",tags:["Response Inspection"],querystring:{type:"object",additionalProperties:!0,description:"Freeform query string parameters to be added as response headers."},response:{200:{type:"object",additionalProperties:!0,description:"Response headers as per query string parameters."}}},ie=r(s=>{s.get("/response-headers",{schema:ve},async(e,t)=>{let o=e.query;for(let[i,n]of Object.entries(o))t.header(i,M(n));let a=Object.fromEntries(Object.entries(o).map(([i,n])=>[i,M(n)]));await t.send(a)}),s.post("/response-headers",{schema:ve},async(e,t)=>{let o=e.query??{},a=e.body??{};for(let[n,d]of Object.entries(o))t.header(n,M(d));for(let[n,d]of Object.entries(a))t.header(n,M(d));let i=Object.fromEntries(Object.entries({...o,...a}).map(([n,d])=>[n,M(d)]));await t.send(i)})},"responseHeadersRoutes");var Te=r(s=>{s.get("/sitemap.xml",{schema:{hide:!0}},async(e,t)=>{try{let o=e.headers.host??"mockhttp.org",n=`<?xml version="1.0" encoding="UTF-8"?>
|
|
236
236
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
237
237
|
<url>
|
|
238
238
|
<loc>${e.headers["x-forwarded-proto"]?.includes("https")?"https":"http"}://${o}/</loc>
|
|
239
239
|
<changefreq>monthly</changefreq>
|
|
240
240
|
<priority>1.0</priority>
|
|
241
241
|
</url>
|
|
242
|
-
</urlset>`;await t.type("text/xml").send(n)}catch(o){s.log.error(o),await t.status(500).send({error:"Internal Server Error"})}})},"sitemapRoute");import{randomInt as at}from"crypto";var ne=[{code:100,message:"Continue"},{code:101,message:"Switching Protocols"},{code:102,message:"Processing"},{code:103,message:"Early Hints"},{code:200,message:"OK"},{code:201,message:"Created"},{code:202,message:"Accepted"},{code:203,message:"Non-Authoritative Information"},{code:204,message:"No Content"},{code:205,message:"Reset Content"},{code:206,message:"Partial Content"},{code:207,message:"Multi-Status"},{code:208,message:"Already Reported"},{code:226,message:"IM Used"},{code:300,message:"Multiple Choices"},{code:301,message:"Moved Permanently"},{code:302,message:"Found"},{code:303,message:"See Other"},{code:304,message:"Not Modified"},{code:305,message:"Use Proxy"},{code:306,message:"Switch Proxy"},{code:307,message:"Temporary Redirect"},{code:308,message:"Permanent Redirect"},{code:400,message:"Bad Request"},{code:401,message:"Unauthorized"},{code:402,message:"Payment Required"},{code:403,message:"Forbidden"},{code:404,message:"Not Found"},{code:405,message:"Method Not Allowed"},{code:406,message:"Not Acceptable"},{code:407,message:"Proxy Authentication Required"},{code:408,message:"Request Timeout"},{code:409,message:"Conflict"},{code:410,message:"Gone"},{code:411,message:"Length Required"},{code:412,message:"Precondition Failed"},{code:413,message:"Payload Too Large"},{code:414,message:"URI Too Long"},{code:415,message:"Unsupported Media Type"},{code:416,message:"Range Not Satisfiable"},{code:417,message:"Expectation Failed"},{code:418,message:"I'm a teapot"},{code:421,message:"Misdirected Request"},{code:422,message:"Unprocessable Entity"},{code:423,message:"Locked"},{code:424,message:"Failed Dependency"},{code:425,message:"Too Early"},{code:426,message:"Upgrade Required"},{code:428,message:"Precondition Required"},{code:429,message:"Too Many Requests"},{code:431,message:"Request Header Fields Too Large"},{code:451,message:"Unavailable For Legal Reasons"},{code:500,message:"Internal Server Error"},{code:501,message:"Not Implemented"},{code:502,message:"Bad Gateway"},{code:503,message:"Service Unavailable"},{code:504,message:"Gateway Timeout"},{code:505,message:"HTTP Version Not Supported"},{code:506,message:"Variant Also Negotiates"},{code:507,message:"Insufficient Storage"},{code:508,message:"Loop Detected"},{code:510,message:"Not Extended"},{code:511,message:"Network Authentication Required"}],A={description:"Return status code or random status code if more than one are given ",tags:["Status Codes"],params:{type:"object",properties:{code:{type:"string",description:"HTTP status code to be returned"}}},response:{200:{type:"object",properties:{status:{type:"string"}}}}},Se=r(s=>{let e=r(async(t,o)=>{let{code:a}=t.params;(!a||!ne.map(i=>i.code).includes(Number(a)))&&(a=ne[at(0,ne.length)].code.toString()),await o.code(Number(a)).send({status:`Response with status code ${a}`})},"handler");s.get("/status/:code?",{schema:A},e),s.post("/status/:code?",{schema:A},e),s.put("/status/:code?",{schema:A},e),s.patch("/status/:code?",{schema:A},e),s.delete("/status/:code?",{schema:A},e)},"statusCodeRoute");import{fastifySwaggerUi as nt}from"@fastify/swagger-ui";var je={name:"@jaredwray/mockhttp",version:"1.0.
|
|
242
|
+
</urlset>`;await t.type("text/xml").send(n)}catch(o){s.log.error(o),await t.status(500).send({error:"Internal Server Error"})}})},"sitemapRoute");import{randomInt as at}from"crypto";var ne=[{code:100,message:"Continue"},{code:101,message:"Switching Protocols"},{code:102,message:"Processing"},{code:103,message:"Early Hints"},{code:200,message:"OK"},{code:201,message:"Created"},{code:202,message:"Accepted"},{code:203,message:"Non-Authoritative Information"},{code:204,message:"No Content"},{code:205,message:"Reset Content"},{code:206,message:"Partial Content"},{code:207,message:"Multi-Status"},{code:208,message:"Already Reported"},{code:226,message:"IM Used"},{code:300,message:"Multiple Choices"},{code:301,message:"Moved Permanently"},{code:302,message:"Found"},{code:303,message:"See Other"},{code:304,message:"Not Modified"},{code:305,message:"Use Proxy"},{code:306,message:"Switch Proxy"},{code:307,message:"Temporary Redirect"},{code:308,message:"Permanent Redirect"},{code:400,message:"Bad Request"},{code:401,message:"Unauthorized"},{code:402,message:"Payment Required"},{code:403,message:"Forbidden"},{code:404,message:"Not Found"},{code:405,message:"Method Not Allowed"},{code:406,message:"Not Acceptable"},{code:407,message:"Proxy Authentication Required"},{code:408,message:"Request Timeout"},{code:409,message:"Conflict"},{code:410,message:"Gone"},{code:411,message:"Length Required"},{code:412,message:"Precondition Failed"},{code:413,message:"Payload Too Large"},{code:414,message:"URI Too Long"},{code:415,message:"Unsupported Media Type"},{code:416,message:"Range Not Satisfiable"},{code:417,message:"Expectation Failed"},{code:418,message:"I'm a teapot"},{code:421,message:"Misdirected Request"},{code:422,message:"Unprocessable Entity"},{code:423,message:"Locked"},{code:424,message:"Failed Dependency"},{code:425,message:"Too Early"},{code:426,message:"Upgrade Required"},{code:428,message:"Precondition Required"},{code:429,message:"Too Many Requests"},{code:431,message:"Request Header Fields Too Large"},{code:451,message:"Unavailable For Legal Reasons"},{code:500,message:"Internal Server Error"},{code:501,message:"Not Implemented"},{code:502,message:"Bad Gateway"},{code:503,message:"Service Unavailable"},{code:504,message:"Gateway Timeout"},{code:505,message:"HTTP Version Not Supported"},{code:506,message:"Variant Also Negotiates"},{code:507,message:"Insufficient Storage"},{code:508,message:"Loop Detected"},{code:510,message:"Not Extended"},{code:511,message:"Network Authentication Required"}],A={description:"Return status code or random status code if more than one are given ",tags:["Status Codes"],params:{type:"object",properties:{code:{type:"string",description:"HTTP status code to be returned"}}},response:{200:{type:"object",properties:{status:{type:"string"}}}}},Se=r(s=>{let e=r(async(t,o)=>{let{code:a}=t.params;(!a||!ne.map(i=>i.code).includes(Number(a)))&&(a=ne[at(0,ne.length)].code.toString()),await o.code(Number(a)).send({status:`Response with status code ${a}`})},"handler");s.get("/status/:code?",{schema:A},e),s.post("/status/:code?",{schema:A},e),s.put("/status/:code?",{schema:A},e),s.patch("/status/:code?",{schema:A},e),s.delete("/status/:code?",{schema:A},e)},"statusCodeRoute");import{fastifySwaggerUi as nt}from"@fastify/swagger-ui";var je={name:"@jaredwray/mockhttp",version:"1.0.1",description:"Mock Http - Easy way to mock http with httpbin replacement",type:"module",main:"dist/index.js",directories:{test:"test"},scripts:{lint:"biome check --write --error-on-warnings",test:"pnpm lint && vitest run --coverage","test:ci":"biome check --error-on-warnings && vitest run --coverage",dev:"pnpm lint && tsx src/index.ts --watch",build:"rimraf ./dist && tsup src/index.ts --format esm --dts --clean --minify","docker:build":"docker build -t jaredwray/mockhttp .","docker:run":"docker run -p 3000:3000 jaredwray/mockhttp","docker:push":"docker push jaredwray/mockhttp","docker:stop":'docker stop $(docker ps -a -q --filter ancestor=jaredwray/mockhttp --format="{{.ID}}")',"docker:readme":"tsx ./scripts/create-docker-readme.ts","docker:compose:up":"docker-compose up -d","docker:compose:down":"docker-compose down",prepare:"pnpm run build",start:"node dist/index.js"},repository:{type:"git",url:"git+https://github.com/jaredwray/mockhttp.git"},keywords:["mock","http","httpbin","test"],author:"Jared Wray <me@jaredwray.com>",license:"MIT",bugs:{url:"https://github.com/jaredwray/mockhttp/issues"},homepage:"https://github.com/jaredwray/mockhttp#readme",devDependencies:{"@biomejs/biome":"^2.2.5","@swc/core":"^1.13.5","@types/html-escaper":"^3.0.4","@vitest/coverage-v8":"^3.2.4",rimraf:"^6.0.1",tsup:"^8.5.0",tsx:"^4.20.6",typescript:"^5.9.3",vitest:"^3.2.4"},dependencies:{"@fastify/cookie":"^11.0.2","@fastify/helmet":"^13.0.2","@fastify/static":"^8.2.0","@fastify/swagger":"^9.5.2","@fastify/swagger-ui":"^5.2.3","@scalar/api-reference":"^1.37.0","detect-port":"^2.1.0",fastify:"^5.6.1",hookified:"^1.12.1","html-escaper":"^3.0.3",pino:"^10.0.0","pino-pretty":"^13.1.1"},files:["dist","public","LICENCE"],pnpm:{onlyBuiltDependencies:["@swc/core","unrs-resolver","vue-demi"]}};var ct=`
|
|
243
243
|
A simple HTTP server that can be used to mock HTTP responses for testing purposes. Inspired by [httpbin](https://httpbin.org/) and built using \`nodejs\` and \`fastify\` with the idea of running it via https://mockhttp.org, via docker \`jaredwray/mockhttp\`, or nodejs \`npm install jaredwray/mockhttp\`.
|
|
244
244
|
|
|
245
245
|
* [GitHub Repository](https://github.com/jaredwray/mockhttp)
|
|
@@ -249,4 +249,4 @@ A simple HTTP server that can be used to mock HTTP responses for testing purpose
|
|
|
249
249
|
# About mockhttp.org
|
|
250
250
|
|
|
251
251
|
[mockhttp.org](https://mockhttp.org) is a free service that runs this codebase and allows you to use it for testing purposes. It is a simple way to mock HTTP responses for testing purposes. Ran via [Cloudflare](https://cloudflare.com) and [Google Cloud Run](https://cloud.google.com/run/) across 7 regions globally and can do millions of requests per second.
|
|
252
|
-
`,Ce={openapi:{info:{title:"Mock HTTP API",description:ct,version:je.version},consumes:["application/json"],produces:["application/json"]}},Pe=r(async s=>{await s.register(nt,{routePrefix:"/docs",uiConfig:{docExpansion:"none",deepLinking:!1},uiHooks:{onRequest(e,t,o){o()},preHandler(e,t,o){o()}},staticCSP:!0,transformSpecification:r((e,t,o)=>e,"transformSpecification"),transformSpecificationClone:!0})},"registerSwaggerUi");import{randomUUID as dt}from"crypto";var L=class{static{r(this,"TapManager")}_injections;constructor(){this._injections=new Map}get injections(){return this._injections}get hasInjections(){return this._injections.size>0}inject(e,t){let o=dt(),a={id:o,response:e,matcher:t};return this._injections.set(o,a),a}removeInjection(e){let t=typeof e=="string"?e:e.id;return this._injections.delete(t)}matchRequest(e){for(let t of this._injections.values())if(this.requestMatches(e,t.matcher))return t}clear(){this._injections.clear()}requestMatches(e,t){if(!t)return!0;if(t.url&&!this.urlMatches(e.url,t.url)||t.hostname&&e.hostname!==t.hostname||t.method&&e.method.toUpperCase()!==t.method.toUpperCase())return!1;if(t.headers){for(let[o,a]of Object.entries(t.headers))if(e.headers[o.toLowerCase()]!==a)return!1}return!0}urlMatches(e,t){let o=e.split("?")[0];if(t===o)return!0;if(t.includes("*")){let a=t.split("*").map(n=>n.replaceAll(/[.*+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${a}$`).test(o)}return!1}};var k=class extends lt{static{r(this,"MockHttp")}_port=3e3;_host="0.0.0.0";_autoDetectPort=!0;_helmet=!0;_apiDocs=!0;_httpBin={httpMethods:!0,redirects:!0,requestInspection:!0,responseInspection:!0,responseFormats:!0,statusCodes:!0,cookies:!0,anything:!0,auth:!0};_server=He();_taps=new L;constructor(e){super(e?.hookOptions),e?.port&&(this._port=e.port),e?.host&&(this._host=e.host),e?.helmet!==void 0&&(this._helmet=e.helmet),e?.apiDocs!==void 0&&(this._apiDocs=e.apiDocs),e?.httpBin!==void 0&&(this._httpBin=e.httpBin)}get port(){return this._port}set port(e){this._port=e}get host(){return this._host}set host(e){this._host=e}get autoDetectPort(){return this._autoDetectPort}set autoDetectPort(e){this._autoDetectPort=e}get helmet(){return this._helmet}set helmet(e){this._helmet=e}get apiDocs(){return this._apiDocs}set apiDocs(e){this._apiDocs=e}get httpBin(){return this._httpBin}set httpBin(e){this._httpBin=e}get server(){return this._server}set server(e){this._server=e}get taps(){return this._taps}set taps(e){this._taps=e}async start(){try{this._server&&await this._server.close(),this._server=He(ce),this._server.addHook("onRequest",async(l,c)=>{let p=this._taps.matchRequest(l);if(p){let u=typeof p.response=="function"?p.response(l):p.response,{response:m,statusCode:y=200,headers:b}=u;if(c.code(y),b)for(let[R,f]of Object.entries(b))c.header(R,f);return c.send(m)}}),await this._server.register(_e,{root:qe.resolve("./node_modules/@scalar/api-reference/dist"),prefix:"/scalar"}),await this.server.register(_e,{root:qe.resolve("./public"),decorateReply:!1}),await this._server.register(Te),this._helmet&&await this._server.register(ht),this._apiDocs&&await this.registerApiDocs();let{httpMethods:e,redirects:t,requestInspection:o,responseInspection:a,responseFormats:i,statusCodes:n,cookies:d,anything:g,auth:h}=this._httpBin;if(e&&await this.registerHttpMethods(),n&&await this.registerStatusCodeRoutes(),o&&await this.registerRequestInspectionRoutes(),a&&await this.registerResponseInspectionRoutes(),i&&await this.registerResponseFormatRoutes(),t&&await this.registerRedirectRoutes(),d&&await this.registerCookieRoutes(),g&&await this.registerAnythingRoutes(),h&&await this.registerAuthRoutes(),this._autoDetectPort){let l=this._port;this._port=await this.detectPort(),l!==this._port&&this._server.log.info(`Port ${l} is in use, detected next available port: ${this._port}`)}await this._server.listen({port:this._port,host:this._host})}catch(e){this._server.log.error(e)}}async close(){await this._server.close()}async detectPort(){let{port:e}=this;return ut(e)}async registerApiDocs(e){let t=e??this._server;await t.register(mt,Ce),await Pe(t),await t.register(ge)}async registerHttpMethods(e){let t=e??this._server;await t.register(Y),await t.register(V),await t.register(
|
|
252
|
+
`,Ce={openapi:{info:{title:"Mock HTTP API",description:ct,version:je.version},consumes:["application/json"],produces:["application/json"]}},Pe=r(async s=>{await s.register(nt,{routePrefix:"/docs",uiConfig:{docExpansion:"none",deepLinking:!1},uiHooks:{onRequest(e,t,o){o()},preHandler(e,t,o){o()}},staticCSP:!0,transformSpecification:r((e,t,o)=>e,"transformSpecification"),transformSpecificationClone:!0})},"registerSwaggerUi");import{randomUUID as dt}from"crypto";var L=class{static{r(this,"TapManager")}_injections;constructor(){this._injections=new Map}get injections(){return this._injections}get hasInjections(){return this._injections.size>0}inject(e,t){let o=dt(),a={id:o,response:e,matcher:t};return this._injections.set(o,a),a}removeInjection(e){let t=typeof e=="string"?e:e.id;return this._injections.delete(t)}matchRequest(e){for(let t of this._injections.values())if(this.requestMatches(e,t.matcher))return t}clear(){this._injections.clear()}requestMatches(e,t){if(!t)return!0;if(t.url&&!this.urlMatches(e.url,t.url)||t.hostname&&e.hostname!==t.hostname||t.method&&e.method.toUpperCase()!==t.method.toUpperCase())return!1;if(t.headers){for(let[o,a]of Object.entries(t.headers))if(e.headers[o.toLowerCase()]!==a)return!1}return!0}urlMatches(e,t){let o=e.split("?")[0];if(t===o)return!0;if(t.includes("*")){let a=t.split("*").map(n=>n.replaceAll(/[.*+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${a}$`).test(o)}return!1}};var k=class extends lt{static{r(this,"MockHttp")}_port=3e3;_host="0.0.0.0";_autoDetectPort=!0;_helmet=!0;_apiDocs=!0;_httpBin={httpMethods:!0,redirects:!0,requestInspection:!0,responseInspection:!0,responseFormats:!0,statusCodes:!0,cookies:!0,anything:!0,auth:!0};_server=He();_taps=new L;constructor(e){super(e?.hookOptions),e?.port&&(this._port=e.port),e?.host&&(this._host=e.host),e?.helmet!==void 0&&(this._helmet=e.helmet),e?.apiDocs!==void 0&&(this._apiDocs=e.apiDocs),e?.httpBin!==void 0&&(this._httpBin=e.httpBin)}get port(){return this._port}set port(e){this._port=e}get host(){return this._host}set host(e){this._host=e}get autoDetectPort(){return this._autoDetectPort}set autoDetectPort(e){this._autoDetectPort=e}get helmet(){return this._helmet}set helmet(e){this._helmet=e}get apiDocs(){return this._apiDocs}set apiDocs(e){this._apiDocs=e}get httpBin(){return this._httpBin}set httpBin(e){this._httpBin=e}get server(){return this._server}set server(e){this._server=e}get taps(){return this._taps}set taps(e){this._taps=e}async start(){try{this._server&&await this._server.close(),this._server=He(ce),this._server.addHook("onRequest",async(l,c)=>{let p=this._taps.matchRequest(l);if(p){let u=typeof p.response=="function"?p.response(l):p.response,{response:m,statusCode:y=200,headers:b}=u;if(c.code(y),b)for(let[R,f]of Object.entries(b))c.header(R,f);return c.send(m)}}),await this._server.register(_e,{root:qe.resolve("./node_modules/@scalar/api-reference/dist"),prefix:"/scalar"}),await this.server.register(_e,{root:qe.resolve("./public"),decorateReply:!1}),await this._server.register(Te),this._helmet&&await this._server.register(ht),this._apiDocs&&await this.registerApiDocs();let{httpMethods:e,redirects:t,requestInspection:o,responseInspection:a,responseFormats:i,statusCodes:n,cookies:d,anything:g,auth:h}=this._httpBin;if(e&&await this.registerHttpMethods(),n&&await this.registerStatusCodeRoutes(),o&&await this.registerRequestInspectionRoutes(),a&&await this.registerResponseInspectionRoutes(),i&&await this.registerResponseFormatRoutes(),t&&await this.registerRedirectRoutes(),d&&await this.registerCookieRoutes(),g&&await this.registerAnythingRoutes(),h&&await this.registerAuthRoutes(),this._autoDetectPort){let l=this._port;this._port=await this.detectPort(),l!==this._port&&this._server.log.info(`Port ${l} is in use, detected next available port: ${this._port}`)}await this._server.listen({port:this._port,host:this._host})}catch(e){this._server.log.error(e)}}async close(){await this._server.close()}async detectPort(){let{port:e}=this;return ut(e)}async registerApiDocs(e){let t=e??this._server;await t.register(mt,Ce),await Pe(t),await t.register(ge)}async registerHttpMethods(e){let t=e??this._server;await t.register(Y),await t.register(V),await t.register(J),await t.register(X),await t.register(Z)}async registerStatusCodeRoutes(e){await(e??this._server).register(Se)}async registerRequestInspectionRoutes(e){let t=e??this._server;await t.register(se),await t.register(te),await t.register(oe)}async registerResponseInspectionRoutes(e){let t=e??this._server;await t.register(re),await t.register(ae),await t.register(ie)}async registerResponseFormatRoutes(e){await(e??this._server).register(ke)}async registerRedirectRoutes(e){let t=e??this._server;await t.register(K),await t.register(ee),await t.register(Q)}async registerCookieRoutes(e){let t=e??this._server;await t.register(pt),await t.register(N),await t.register(G),await t.register(W)}async registerAnythingRoutes(e){await(e??this._server).register(de)}async registerAuthRoutes(e){let t=e??this._server;await t.register(E),await t.register(F),await t.register(O),await t.register(B)}};var gt=r(async()=>{let s=new k;return I.env.PORT&&(s.port=Number.parseInt(I.env.PORT,10)),I.env.HOST&&(s.host=I.env.HOST),await s.start(),s},"start");import.meta.url===`file://${I.argv[1]}`&&await gt();export{k as default,k as mockhttp,gt as start};
|