// // Dependencies // 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_LEN = DATA_LOCATION.length; let DATA_FILE = __dirname + '/' + DATA_LOCATION; let PORT = 1280; // // Load store file // let store = {}; // deafult empty object 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.'); } // // Flush to store file on exit // let flush = function() { console.log('Caught deadly signal.'); 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 // // 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 + ']'); 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(key, req, resp) { console.log(req.method + ' request for key [' + key + ']'); switch (req.method) { case 'GET': let exactMatch=!key.endsWith('/'); let matchFound=false; if (exactMatch) { console.log(" - Exact Match."); if (store.hasOwnProperty(key)) { resp.writeHead(200, { 'Content-Type' : 'application/json' }); resp.write(JSON.stringify(store[key]) + '\n'); matchFound=true; } } else { console.log(" - All Matches."); let matches=[]; Object.keys(store).forEach(theKey=>{ if (theKey.startsWith(key)){ 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 not found."); } resp.end(); break; case 'PUT': case 'POST': let json = ''; req.on('data', function(chunk) { json += chunk; }); req.on('end', function() { try { let data = JSON.parse(json); store[key] = 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(); }); break; case 'OPTIONS': resp.end(); break; case 'DELETE': if (store.hasOwnProperty(key)) { delete store[key]; 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, POST, PUT, DELETE, OPTIONS'); let uri = req.url //.replace(/^\/+|\/+$/g, ''); // trim slashes console.log('Serving [' + req.url + ']'); if (uri === '/') { // server index file uri = 'index.html'; serveFile(uri, req, resp); } else { // rest request serveRestData(req.url, req, resp); } }).listen(PORT);