mockifyjs
Version:
A Server Mocker for creating temperary rest api servers.
229 lines (198 loc) • 6.59 kB
JavaScript
const fs = require("fs");
const axios = require("axios")
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const package = require("./package.json")
const argv = process.argv.splice(2);
let MOCKERFILE = "";
let MOCKER = "";
let MOCKREQUESTS = [];
let PORT = 3000;
let REQUESTS = ["ALL", "GET", "POST", "HEAD", "OPTIONS", "DELETE", "PUT", "CONNECT", "TRACE"];
let REQUEST = null;
if (argv.lenght == 0) {
console.log("Missing Mocker File!");
} else {
MOCKERFILE = argv[0];
if (!isNaN(Number(argv[1]))) {
PORT = Number(argv[1]);
}
// Where Shit Gets Real
if (!fs.existsSync(MOCKERFILE)) {
console.log(MOCKERFILE + " Not Found!");
} else {
MOCKER = fs.readFileSync(MOCKERFILE, "utf-8") || "";
run(MOCKER);
fs.watchFile(MOCKERFILE, {
persistent: true,
interval: 500
}, function() {
MOCKREQUESTS = [];
MOCKER = fs.readFileSync(MOCKERFILE, "utf-8") || "";
run(MOCKER);
})
app.use(bodyParser.json());
app.use(express.urlencoded({ extended: true }));
app.all('*', async(req,res)=>{
await router(req, res)
}
)
// Server
app.listen(PORT, ()=>{
console.log(`Mock Server listening on port ${PORT}`)
}
)
}
}
// Mocker Function
function run(codes) {
let requests = [];
let request = "";
codes = codes.trim().split("\n");
codes.forEach(function(code, i) {
code = code.trimRight();
if (REQUESTS.includes(code.split(" ")[0])) {
let REQUESTNAME = code.split(" ")[0];
// console.log(REQUESTNAME)
if (request != "") {
requests.push(request.trim());
}
request = "";
request += (code + "\n");
} else {
request += (code + "\n");
}
if (i == (codes.length - 1)) {
requests.push(request.trim());
}
// console.log(i, code);
})
// console.log(requests)
return makeRequests(requests);
}
function getPath(command) {
command = command.trim();
let firstIndex = command.indexOf(" ");
let lastIndex = command.lastIndexOf(" ");
if (firstIndex == lastIndex) {
lastIndex = command.length;
}
let left = command.substring(lastIndex, command.length);
if (lastIndex != command.length) {
if (isNaN(left)) {
lastIndex = command.length;
}
}
return command.substring(firstIndex, lastIndex);
}
function getStatus(command) {
command = command.trim();
let firstIndex = command.lastIndexOf(" ");
let lastIndex = command.length;
if (firstIndex == lastIndex) {
return "200";
}
if (!isNaN(command.substring(firstIndex, lastIndex))) {
return command.substring(firstIndex, lastIndex);
} else {
return "200";
}
}
function makeRequests(requests) {
requests.forEach(function(request, i) {
let line = (i + 1);
let req = request.split("\n");
let REQUESTNAME = req[0].split(" ")[0] || "GET";
let REQUESTPATH = getPath(req[0]) || "/";
let REQUESTSTATUS = Number(getStatus(req[0]));
let BODY = "";
let headers = [];
if (!REQUESTS.includes(REQUESTNAME)) {
return console.log("Unexpected " + REQUESTNAME + " on line " + line + ":" + MOCKERFILE);
}
// Gather Headers
req.forEach(function(each, i) {
if (each.startsWith("\t") || each.startsWith(" ")) {
if (each.trim().split(":")[0].trim() != "") {
headers.push([each.trim().split(":")[0].trim(), each.trim().split(":")[1]?.trim()] || "");
}
}
if (i != 0 && !each.startsWith("\t") && !each.startsWith(" ")) {
BODY += (each + "\n");
}
})
MOCKREQUESTS.push({
method: REQUESTNAME,
path: REQUESTPATH,
status: REQUESTSTATUS,
headers,
body: BODY
})
})
return MOCKREQUESTS;
}
async function parseBody(body, index) {
if (body.trim().startsWith("$randNumber")) {
let arg = Number(body.trim().split(" ")[1]) || 1000;
return String(Math.floor(Math.random() * arg));
} else if (body.trim().startsWith("$readFile")) {
let arg = body.trim().substring(body.trim().indexOf(" ") + 1);
return fs.readFileSync(arg) || "";
} else if (body.trim().startsWith("$echo")) {
if (REQUEST) {
if (REQUEST.body) {
return REQUEST.body;
}
}
return body;
} else if (body.trim().startsWith("$get")) {
let oldReq = MOCKREQUESTS[index];
let arg = body.trim().substring(body.trim().indexOf(" ") + 1);
try {
let result = await axios(arg);
return result.data;
} catch (error) {
return "";
}
} else {
return body;
}
}
async function router(req, res) {
let sent = false;
let status = 404;
REQUEST = req;
res.set("X-Powered-By", "MockifyJS v" + package.version);
await new Promise(function(resolve, reject) {
MOCKREQUESTS.forEach(async function(request, i) {
req.url = decodeURI(req.url).trim();
request.path = request.path.trim();
if ((request.method == req.method.toUpperCase() || request.method == "ALL") && (request.path == req.url || encodeURIComponent(request.path) == req.url)) {
sent = true;
request.headers.forEach(async function(header) {
try {
res.set(header[0], header[1]);
} catch (error) {
}
})
if (request.status == 404) {
request.body = "";
}
let body = await parseBody(request.body, i);
resolve(body);
res.status(request.status).send(body);
status = request.status;
}
if(i == (MOCKREQUESTS.length - 1)){
resolve("");
}
});
});
if (!sent) {
res.status(404).send();
}
let time = (new Date()).toString().substring(0, (new Date()).toString().lastIndexOf(":") + 3);
console.log("[" + time + "] " + req.method + " - " + req.url + " " + status);
}