From b11e5144e36e3fbc634eeeed5e9acf014cff5c4c Mon Sep 17 00:00:00 2001 From: Joe Tretter Date: Fri, 28 Aug 2020 23:58:45 -0500 Subject: [PATCH] - handle return all - handle put and post same - send feedback as JSON - add CORS headers --- dumbserver.js | 110 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 40 deletions(-) diff --git a/dumbserver.js b/dumbserver.js index 66f4699..0ab0246 100644 --- a/dumbserver.js +++ b/dumbserver.js @@ -1,25 +1,23 @@ // // Dependencies // -var http = require('http'); -var fs = require('fs'); - +let http = require('http'); +let fs = require('fs'); // // Constants // -var DATA_LOCATION = 'data'; // both the url root and the location of data file -var DATA_LOCATION_LEN = DATA_LOCATION.length; -var DATA_FILE = __dirname + '/' + DATA_LOCATION; -var PORT = 80; - +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 // -var store = {}; // deafult empty object +let store = {}; // deafult empty object try { - var json = fs.readFileSync(DATA_FILE); + let json = fs.readFileSync(DATA_FILE); store = JSON.parse(json); console.log('Read store file'); } catch (e) { // lazy error handling @@ -30,14 +28,14 @@ try { // // Flush to store file on exit // -var flush = function() +let flush = function() { console.log('Caught deadly signal.'); console.log('Flushing data to file [' + DATA_FILE + ']\n'); fs.writeFileSync(DATA_FILE, JSON.stringify(store)); }; -var handleInterrupt = function() { flush(); process.exit(); }; +let handleInterrupt = function() { flush(); process.exit(); }; process.on('SIGINT', handleInterrupt); process.on('SIGTERM', handleInterrupt); @@ -48,9 +46,8 @@ process.on('SIGHUP', flush); // HUP flushes to file but keeps the server runnin // 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 // -var serveFile = function(loc, req, resp) -{ - var fullPath = __dirname + '/' + loc; +let serveFile = function(loc, req, resp) { + let fullPath = __dirname + '/' + loc; console.log('Trying to serve file at [' + fullPath + ']'); if (req.method !== 'GET') { // read only! @@ -67,34 +64,61 @@ var serveFile = function(loc, req, resp) } }; -var serveRestData = function(key, req, resp) -{ +let serveRestData = function(key, req, resp) { console.log(req.method + ' request for key [' + key + ']'); switch (req.method) { case 'GET': - if (store.hasOwnProperty(key)) { - resp.writeHead(200, { 'Content-Type' : 'application/json' }); - resp.write(JSON.stringify(store[key]) + '\n'); + 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 { - resp.writeHead(404); - resp.write('Not Found\n'); - } + console.log(" - Match not found."); + } resp.end(); break; case 'PUT': - var json = ''; + case 'POST': + let json = ''; req.on('data', function(chunk) { json += chunk; }); req.on('end', function() { try { - var data = JSON.parse(json); + let data = JSON.parse(json); store[key] = data; - resp.writeHead(204); + resp.writeHead(201, { 'Content-Type' : 'application/json' }); + resp.write('{"success":true}'); } catch (e) { - resp.writeHead(400); - resp.write('Invalid JSON\n'); + resp.writeHead(400, { 'Content-Type' : 'application/json' }); + resp.write('{"success":false, "error":"Invalid JSON"}'); } resp.end(); }); @@ -103,16 +127,19 @@ var serveRestData = function(key, req, resp) case 'DELETE': if (store.hasOwnProperty(key)) { delete store[key]; - resp.writeHead(204); + resp.writeHead(204, { 'Content-Type' : 'application/json' }); + resp.write('{"success":true}'); } else { - resp.writeHead(404); + resp.writeHead(404, { 'Content-Type' : 'application/json' }); + resp.write('{"success":false, "error":"Not Found"}'); } resp.end(); + flush(); break; default: - resp.writeHead(405); - resp.write('Unsupported method\n'); + resp.writeHead(405, { 'Content-Type' : 'application/json' }); + resp.write('{"success":false, "error":"Unsupported method"}'); resp.end(); } @@ -122,15 +149,18 @@ var serveRestData = function(key, req, resp) // Listen for connections // http.createServer(function(req, resp) { - - console.log('Serving [' + req.url + ']'); - var uri = req.url.replace(/^\/+|\/+$/g, ''); // trim slashes - - if (uri.substr(0, DATA_LOCATION_LEN + 1) === DATA_LOCATION + '/') { // rest request - serveRestData(uri.substr(DATA_LOCATION_LEN + 1), req, resp); - } else { // try to serve the file - if (uri === '') { uri = 'index.html'; } + // CORS headers + resp.setHeader('Access-Control-Allow-Origin', '*'); + resp.setHeader('Vary', 'Origin'); + + 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);