Adding some docker and terraform to it ... wip
This commit is contained in:
370
dumbserver.js
370
dumbserver.js
@@ -1,225 +1,233 @@
|
||||
//
|
||||
// Dependencies
|
||||
//
|
||||
let http = require('http');
|
||||
let fs = require('fs');
|
||||
let http = require("http");
|
||||
let fs = require("fs");
|
||||
|
||||
//
|
||||
// Constants
|
||||
//
|
||||
let DATA_LOCATION = 'data'; // both the url root and the location of data file
|
||||
let DATA_LOCATION = "dataDir/data"; // both the url root and the location of data file
|
||||
let DATA_LOCATION_LEN = DATA_LOCATION.length;
|
||||
let DATA_FILE = __dirname + '/' + DATA_LOCATION;
|
||||
let PORT = 1280;
|
||||
let DATA_FILE = __dirname + "/" + DATA_LOCATION;
|
||||
let PORT = 1280;
|
||||
|
||||
//
|
||||
// Load store file
|
||||
//
|
||||
let store = {}; // deafult empty object
|
||||
let json='';
|
||||
let json = "";
|
||||
try {
|
||||
let json = fs.readFileSync(DATA_FILE);
|
||||
store = JSON.parse(json);
|
||||
console.log('Read store file');
|
||||
} catch (e) { // lazy error handling
|
||||
console.log('Could not load store file. Using empty array.');
|
||||
let json = fs.readFileSync(DATA_FILE);
|
||||
store = JSON.parse(json);
|
||||
console.log("Read store file");
|
||||
} catch (e) {
|
||||
// lazy error handling
|
||||
console.log("Could not load store file. Using empty array.");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Flush to store file on exit
|
||||
//
|
||||
let flush = function()
|
||||
{
|
||||
console.log('Flushing data to file [' + DATA_FILE + ']\n');
|
||||
fs.writeFileSync(DATA_FILE, JSON.stringify(store));
|
||||
let flush = function () {
|
||||
console.log("Flushing data to file [" + DATA_FILE + "]\n");
|
||||
fs.writeFileSync(DATA_FILE, JSON.stringify(store));
|
||||
};
|
||||
|
||||
let handleInterrupt = function() { flush(); process.exit(); };
|
||||
|
||||
process.on('SIGINT', handleInterrupt);
|
||||
process.on('SIGTERM', handleInterrupt);
|
||||
process.on('SIGHUP', flush); // HUP flushes to file but keeps the server running
|
||||
let handleInterrupt = function () {
|
||||
flush();
|
||||
process.exit();
|
||||
};
|
||||
|
||||
process.on("SIGINT", handleInterrupt);
|
||||
process.on("SIGTERM", handleInterrupt);
|
||||
process.on("SIGHUP", flush); // HUP flushes to file but keeps the server running
|
||||
|
||||
//
|
||||
// If request URI is prefixed with the value of DATA_LOCATION, we treat incoming request as a REST request
|
||||
// Otherwise we serve the file referenced by the URI
|
||||
//
|
||||
let serveFile = function(loc, req, resp) {
|
||||
let fullPath = __dirname + '/' + loc;
|
||||
console.log('Trying to serve file at [' + fullPath + ']');
|
||||
let serveFile = function (loc, req, resp) {
|
||||
let fullPath = __dirname + "/" + loc;
|
||||
console.log("Trying to serve file at [" + fullPath + "]");
|
||||
|
||||
if (req.method !== 'GET') { // read only!
|
||||
resp.writeHead(405);
|
||||
resp.write('Unsupported method\n');
|
||||
resp.end();
|
||||
} else if (fs.existsSync(fullPath)) {
|
||||
resp.writeHead(200);
|
||||
fs.createReadStream(fullPath).pipe(resp);
|
||||
} else {
|
||||
resp.writeHead(404);
|
||||
resp.write('Not Found\n');
|
||||
resp.end();
|
||||
}
|
||||
if (req.method !== "GET") {
|
||||
// read only!
|
||||
resp.writeHead(405);
|
||||
resp.write("Unsupported method\n");
|
||||
resp.end();
|
||||
} else if (fs.existsSync(fullPath)) {
|
||||
resp.writeHead(200);
|
||||
fs.createReadStream(fullPath).pipe(resp);
|
||||
} else {
|
||||
resp.writeHead(404);
|
||||
resp.write("Not Found\n");
|
||||
resp.end();
|
||||
}
|
||||
};
|
||||
|
||||
let serveRestData = function(urlPath, req, resp) {
|
||||
console.log(req.method + ' request for path [' + urlPath + ']');
|
||||
let serveRestData = function (urlPath, req, resp) {
|
||||
console.log(req.method + " request for path [" + urlPath + "]");
|
||||
|
||||
switch (req.method) {
|
||||
switch (req.method) {
|
||||
case "GET":
|
||||
let exactMatch = !urlPath.endsWith("/");
|
||||
let matchFound = false;
|
||||
|
||||
case 'GET':
|
||||
let exactMatch=!urlPath.endsWith('/');
|
||||
let matchFound=false;
|
||||
|
||||
if (exactMatch) { // assumes that only a single resource has this ID.
|
||||
console.log(" - Exact Match.");
|
||||
if (store.hasOwnProperty(urlPath)) {
|
||||
resp.writeHead(200, { 'Content-Type' : 'application/json' });
|
||||
resp.write(JSON.stringify(store[urlPath]) + '\n');
|
||||
matchFound=true;
|
||||
}
|
||||
} else {
|
||||
console.log(" - All Matches.");
|
||||
let matches=[];
|
||||
Object.keys(store).forEach(theKey=>{
|
||||
if (theKey.startsWith(urlPath)){
|
||||
matches.push(store[theKey]);
|
||||
matchFound=true;
|
||||
}
|
||||
});
|
||||
|
||||
if (matchFound) {
|
||||
resp.writeHead(200, { 'Content-Type' : 'application/json' });
|
||||
resp.write(JSON.stringify(matches));
|
||||
}
|
||||
}
|
||||
|
||||
if (!matchFound) {
|
||||
console.log(" - Match NOT found.");
|
||||
resp.writeHead(404, { 'Content-Type' : 'application/json' });
|
||||
resp.write('{"success":false, "error":"Not Found"}');
|
||||
} else {
|
||||
console.log(" - Match found.");
|
||||
}
|
||||
resp.end();
|
||||
break;
|
||||
if (exactMatch) {
|
||||
// assumes that only a single resource has this ID.
|
||||
console.log(" - Exact Match.");
|
||||
if (store.hasOwnProperty(urlPath)) {
|
||||
resp.writeHead(200, { "Content-Type": "application/json" });
|
||||
resp.write(JSON.stringify(store[urlPath]) + "\n");
|
||||
matchFound = true;
|
||||
}
|
||||
} else {
|
||||
console.log(" - All Matches.");
|
||||
let matches = [];
|
||||
Object.keys(store).forEach((theKey) => {
|
||||
if (theKey.startsWith(urlPath)) {
|
||||
matches.push(store[theKey]);
|
||||
matchFound = true;
|
||||
}
|
||||
});
|
||||
|
||||
case 'PUT':
|
||||
json = '';
|
||||
req.on('data', function(chunk) { json += chunk; });
|
||||
req.on('end', function() {
|
||||
try {
|
||||
let data = JSON.parse(json);
|
||||
store[urlPath] = data;
|
||||
resp.writeHead(201, { 'Content-Type' : 'application/json' });
|
||||
resp.write('{"success":true}');
|
||||
} catch (e) {
|
||||
resp.writeHead(400, { 'Content-Type' : 'application/json' });
|
||||
resp.write('{"success":false, "error":"Invalid JSON"}');
|
||||
}
|
||||
resp.end();
|
||||
flush();
|
||||
});
|
||||
break;
|
||||
|
||||
|
||||
case 'POST':
|
||||
json = '';
|
||||
req.on('data', function(chunk) { json += chunk; });
|
||||
req.on('end', function() {
|
||||
try {
|
||||
let data = JSON.parse(json);
|
||||
if (data.ID === undefined) {
|
||||
resp.writeHead(400, { 'Content-Type' : 'application/json' });
|
||||
resp.write('{"success":false, "error":"The ID Field needs to be given"}');
|
||||
} else {
|
||||
// make sure the ID from the data is used as the final resource Identifier,
|
||||
// even if the URL has none or says different.
|
||||
let re=new RegExp("/[^/]*$");
|
||||
urlPath=urlPath.replace(re,"");
|
||||
urlPath=urlPath+"/"+data.ID;
|
||||
console.log(" - storing with resource key: [" + urlPath + "]");
|
||||
if (matchFound) {
|
||||
resp.writeHead(200, { "Content-Type": "application/json" });
|
||||
resp.write(JSON.stringify(matches));
|
||||
}
|
||||
}
|
||||
|
||||
store[urlPath] = data;
|
||||
if (!matchFound) {
|
||||
console.log(" - Match NOT found.");
|
||||
resp.writeHead(404, { "Content-Type": "application/json" });
|
||||
resp.write('{"success":false, "error":"Not Found"}');
|
||||
} else {
|
||||
console.log(" - Match found.");
|
||||
}
|
||||
resp.end();
|
||||
break;
|
||||
|
||||
resp.writeHead(201, { 'Content-Type' : 'application/json' });
|
||||
resp.write(JSON.stringify(store[urlPath]));
|
||||
}
|
||||
} catch (e) {
|
||||
resp.writeHead(400, { 'Content-Type' : 'application/json' });
|
||||
resp.write('{"success":false, "error":"Invalid JSON"}');
|
||||
}
|
||||
resp.end();
|
||||
flush();
|
||||
});
|
||||
break;
|
||||
|
||||
case 'PATCH':
|
||||
json = '';
|
||||
req.on('data', function(chunk) { json += chunk; });
|
||||
req.on('end', function() {
|
||||
try {
|
||||
let data = JSON.parse(json);
|
||||
Object.keys(data).forEach(theKey=>{
|
||||
store[urlPath][theKey] = data[theKey]
|
||||
});
|
||||
|
||||
resp.writeHead(201, { 'Content-Type' : 'application/json' });
|
||||
resp.write('{"success":true}');
|
||||
} catch (e) {
|
||||
resp.writeHead(400, { 'Content-Type' : 'application/json' });
|
||||
resp.write('{"success":false, "error":"Invalid JSON"}');
|
||||
}
|
||||
resp.end();
|
||||
flush();
|
||||
});
|
||||
break;
|
||||
|
||||
|
||||
case 'OPTIONS':
|
||||
resp.end();
|
||||
break;
|
||||
case "PUT":
|
||||
json = "";
|
||||
req.on("data", function (chunk) {
|
||||
json += chunk;
|
||||
});
|
||||
req.on("end", function () {
|
||||
try {
|
||||
let data = JSON.parse(json);
|
||||
store[urlPath] = data;
|
||||
resp.writeHead(201, { "Content-Type": "application/json" });
|
||||
resp.write('{"success":true}');
|
||||
} catch (e) {
|
||||
resp.writeHead(400, { "Content-Type": "application/json" });
|
||||
resp.write('{"success":false, "error":"Invalid JSON"}');
|
||||
}
|
||||
resp.end();
|
||||
flush();
|
||||
});
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
if (store.hasOwnProperty(urlPath)) {
|
||||
delete store[urlPath];
|
||||
resp.writeHead(204, { 'Content-Type' : 'application/json' });
|
||||
resp.write('{"success":true}');
|
||||
} else {
|
||||
resp.writeHead(404, { 'Content-Type' : 'application/json' });
|
||||
resp.write('{"success":false, "error":"Not Found"}');
|
||||
}
|
||||
resp.end();
|
||||
flush();
|
||||
break;
|
||||
case "POST":
|
||||
json = "";
|
||||
req.on("data", function (chunk) {
|
||||
json += chunk;
|
||||
});
|
||||
req.on("end", function () {
|
||||
try {
|
||||
let data = JSON.parse(json);
|
||||
if (data.ID === undefined) {
|
||||
resp.writeHead(400, { "Content-Type": "application/json" });
|
||||
resp.write('{"success":false, "error":"The ID Field needs to be given"}');
|
||||
} else {
|
||||
// make sure the ID from the data is used as the final resource Identifier,
|
||||
// even if the URL has none or says different.
|
||||
let re = new RegExp("/[^/]*$");
|
||||
urlPath = urlPath.replace(re, "");
|
||||
urlPath = urlPath + "/" + data.ID;
|
||||
console.log(" - storing with resource key: [" + urlPath + "]");
|
||||
|
||||
default:
|
||||
resp.writeHead(405, { 'Content-Type' : 'application/json' });
|
||||
resp.write('{"success":false, "error":"Unsupported method"}');
|
||||
resp.end();
|
||||
}
|
||||
store[urlPath] = data;
|
||||
|
||||
resp.writeHead(201, { "Content-Type": "application/json" });
|
||||
resp.write(JSON.stringify(store[urlPath]));
|
||||
}
|
||||
} catch (e) {
|
||||
resp.writeHead(400, { "Content-Type": "application/json" });
|
||||
resp.write('{"success":false, "error":"Invalid JSON"}');
|
||||
}
|
||||
resp.end();
|
||||
flush();
|
||||
});
|
||||
break;
|
||||
|
||||
case "PATCH":
|
||||
json = "";
|
||||
req.on("data", function (chunk) {
|
||||
json += chunk;
|
||||
});
|
||||
req.on("end", function () {
|
||||
try {
|
||||
let data = JSON.parse(json);
|
||||
Object.keys(data).forEach((theKey) => {
|
||||
store[urlPath][theKey] = data[theKey];
|
||||
});
|
||||
|
||||
resp.writeHead(201, { "Content-Type": "application/json" });
|
||||
resp.write('{"success":true}');
|
||||
} catch (e) {
|
||||
resp.writeHead(400, { "Content-Type": "application/json" });
|
||||
resp.write('{"success":false, "error":"Invalid JSON"}');
|
||||
}
|
||||
resp.end();
|
||||
flush();
|
||||
});
|
||||
break;
|
||||
|
||||
case "OPTIONS":
|
||||
resp.end();
|
||||
break;
|
||||
|
||||
case "DELETE":
|
||||
if (store.hasOwnProperty(urlPath)) {
|
||||
delete store[urlPath];
|
||||
resp.writeHead(204, { "Content-Type": "application/json" });
|
||||
resp.write('{"success":true}');
|
||||
} else {
|
||||
resp.writeHead(404, { "Content-Type": "application/json" });
|
||||
resp.write('{"success":false, "error":"Not Found"}');
|
||||
}
|
||||
resp.end();
|
||||
flush();
|
||||
break;
|
||||
|
||||
default:
|
||||
resp.writeHead(405, { "Content-Type": "application/json" });
|
||||
resp.write('{"success":false, "error":"Unsupported method"}');
|
||||
resp.end();
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Listen for connections
|
||||
//
|
||||
http.createServer(function(req, resp) {
|
||||
// CORS headers
|
||||
resp.setHeader('Access-Control-Allow-Origin', '*');
|
||||
resp.setHeader('Access-Control-Allow-Headers', 'X-Request-With, content-type');
|
||||
resp.setHeader('Vary', 'Origin');
|
||||
|
||||
resp.setHeader('Access-Control-Allow-Methods','GET, PATCH, POST, PUT, DELETE, OPTIONS');
|
||||
|
||||
console.log('Serving [' + req.url + ']');
|
||||
|
||||
if (req.url === '/') { // server index file
|
||||
serveFile('index.html', req, resp);
|
||||
} else { // rest request
|
||||
serveRestData(req.url, req, resp);
|
||||
}
|
||||
http
|
||||
.createServer(function (req, resp) {
|
||||
// CORS headers
|
||||
resp.setHeader("Access-Control-Allow-Origin", "*");
|
||||
resp.setHeader("Access-Control-Allow-Headers", "X-Request-With, content-type");
|
||||
resp.setHeader("Vary", "Origin");
|
||||
|
||||
}).listen(PORT);
|
||||
resp.setHeader("Access-Control-Allow-Methods", "GET, PATCH, POST, PUT, DELETE, OPTIONS");
|
||||
|
||||
console.log("Serving [" + req.url + "]");
|
||||
|
||||
if (req.url === "/") {
|
||||
// server index file
|
||||
serveFile("index.html", req, resp);
|
||||
} else {
|
||||
// rest request
|
||||
serveRestData(req.url, req, resp);
|
||||
}
|
||||
})
|
||||
.listen(PORT);
|
||||
|
||||
Reference in New Issue
Block a user