Files
dumbserver/dumbserver.js

226 lines
6.9 KiB
JavaScript
Raw Normal View History

2013-12-21 19:39:08 -05:00
//
// Dependencies
//
let http = require('http');
let fs = require('fs');
2013-12-21 19:39:08 -05:00
//
// Constants
//
let DATA_LOCATION = '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;
2013-12-21 19:39:08 -05:00
//
// Load store file
//
let store = {}; // deafult empty object
2020-08-29 23:12:27 -05:00
let json='';
2013-12-21 19:39:08 -05:00
try {
let json = fs.readFileSync(DATA_FILE);
2013-12-21 19:39:08 -05:00
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()
2013-12-21 19:39:08 -05:00
{
console.log('Flushing data to file [' + DATA_FILE + ']\n');
fs.writeFileSync(DATA_FILE, JSON.stringify(store));
};
let handleInterrupt = function() { flush(); process.exit(); };
2013-12-21 19:39:08 -05:00
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;
2013-12-21 19:39:08 -05:00
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();
}
};
2020-08-29 23:12:27 -05:00
let serveRestData = function(urlPath, req, resp) {
console.log(req.method + ' request for path [' + urlPath + ']');
2013-12-21 19:39:08 -05:00
switch (req.method) {
case 'GET':
2020-08-29 23:12:27 -05:00
let exactMatch=!urlPath.endsWith('/');
let matchFound=false;
2020-08-29 23:12:27 -05:00
if (exactMatch) { // assumes that only a single resource has this ID.
console.log(" - Exact Match.");
2020-08-29 23:12:27 -05:00
if (store.hasOwnProperty(urlPath)) {
resp.writeHead(200, { 'Content-Type' : 'application/json' });
2020-08-29 23:12:27 -05:00
resp.write(JSON.stringify(store[urlPath]) + '\n');
matchFound=true;
}
} else {
console.log(" - All Matches.");
let matches=[];
Object.keys(store).forEach(theKey=>{
2020-08-29 23:12:27 -05:00
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"}');
2013-12-21 19:39:08 -05:00
} else {
2020-08-29 23:12:27 -05:00
console.log(" - Match found.");
}
2013-12-21 19:39:08 -05:00
resp.end();
break;
case 'PUT':
2020-08-29 23:12:27 -05:00
json = '';
2013-12-21 19:39:08 -05:00
req.on('data', function(chunk) { json += chunk; });
req.on('end', function() {
try {
let data = JSON.parse(json);
2020-08-29 23:12:27 -05:00
store[urlPath] = data;
resp.writeHead(201, { 'Content-Type' : 'application/json' });
resp.write('{"success":true}');
2013-12-21 19:39:08 -05:00
} catch (e) {
resp.writeHead(400, { 'Content-Type' : 'application/json' });
resp.write('{"success":false, "error":"Invalid JSON"}');
2013-12-21 19:39:08 -05:00
}
resp.end();
flush();
2013-12-21 19:39:08 -05:00
});
break;
2020-08-29 23:12:27 -05:00
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 + "]");
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;
2020-08-29 01:13:06 -05:00
case 'OPTIONS':
resp.end();
break;
2013-12-21 19:39:08 -05:00
case 'DELETE':
2020-08-29 23:12:27 -05:00
if (store.hasOwnProperty(urlPath)) {
delete store[urlPath];
resp.writeHead(204, { 'Content-Type' : 'application/json' });
resp.write('{"success":true}');
2013-12-21 19:39:08 -05:00
} else {
resp.writeHead(404, { 'Content-Type' : 'application/json' });
resp.write('{"success":false, "error":"Not Found"}');
2013-12-21 19:39:08 -05:00
}
resp.end();
flush();
2013-12-21 19:39:08 -05:00
break;
default:
resp.writeHead(405, { 'Content-Type' : 'application/json' });
resp.write('{"success":false, "error":"Unsupported method"}');
2013-12-21 19:39:08 -05:00
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');
2020-08-29 23:12:27 -05:00
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);
2013-12-21 19:39:08 -05:00
}
}).listen(PORT);