routes/router.js
"use strict";
const handlers = require("../private/handlers"); // handlers module
const httpStatus = require("http-status-codes");
const contentTypes = {
"text": { "Content-Type": "text/plain; charset=utf-8" },
"start": { "Content-Type": "text/html; charset=utf-8" },
"js": { "Content-Type": "application/js" },
"css": { "Content-Type": "text/css" },
"png": { "Content-Type": "image/png" },
"jpg": { "Content-Type": "image/jpg" },
"gif": { "Content-Type": "image/gif" },
"ico": { "Content-Type": "image/x-icon" },
"svg": { "Content-Type": "image/svg+xml" }
};
const routes = { // register handles to routes
"GET": {
"/start": handlers.getAndRespond,
"/side": handlers.findCities,
"/about": handlers.getAndRespond,
"/contact": handlers.getAndRespond,
"js": handlers.getAndRespond,
"css": handlers.getAndRespond,
"png": handlers.getAndRespond,
"jpg": handlers.getAndRespond,
"gif": handlers.getAndRespond,
"ico": handlers.getAndRespond,
"svg": handlers.getAndRespond
},
"POST": {
"/contact": handlers.receiveData
}
};
exports.route = function(req, res, body) { // routing
let asset;
let type;
let routedUrl;
if (req.url.indexOf(".js") !== -1) { // check for asset types
asset = "js";
routedUrl = "public/javascripts" + req.url;
type = contentTypes.js;
} else if (req.url.indexOf(".css") !== -1) {
asset = "css";
routedUrl = "public/stylesheets" + req.url;
type = contentTypes.css;
} else if (req.url.indexOf(".png") !== -1) {
asset = "png";
routedUrl = "public/images" + req.url;
type = contentTypes.png;
} else if (req.url.indexOf(".jpg") !== -1) {
asset = "jpg";
routedUrl = "public/images" + req.url;
type = contentTypes.jpg;
} else if (req.url.indexOf(".gif") !== -1) {
asset = "gif";
routedUrl = "public/images" + req.url;
type = contentTypes.gif;
} else if (req.url.indexOf(".svg") !== -1) {
asset = "svg";
routedUrl = "public/images" + req.url;
type = contentTypes.svg;
} else if (req.url.indexOf(".ico") !== -1) {
asset = "ico";
routedUrl = req.url;
type = contentTypes.ico;
} else {
if (req.url.charAt(req.url.length - 1) === "/") {
asset = "/start";
routedUrl = "views/index.html";
type = contentTypes.html;
} else if (req.url === "/start") {
asset = req.url;
routedUrl = "views/index.html";
type = contentTypes.html;
} else if (req.url === "/side") {
asset = req.url;
routes[req.method][asset](req, res);
return;
} else if (req.url === "/contact" && req.method === "POST") {
asset = req.url;
routes[req.method][asset](req, res, body);
return;
} else {
asset = req.url;
routedUrl = "views" + req.url + ".html";
type = contentTypes.html;
}
}
try {
if (routes[req.method][asset]) { // does handler exist to this route
routes[req.method][asset](routedUrl, type, res); // yes, call it with params
} else { // no, return error msg
res.writeHead(httpStatus.NOT_FOUND, contentTypes.text);
res.end(`route for <kbd>${req.url}</kbd> not found`);
}
} catch (ex) { // routing exception
console.log("Log: Routing exception: " + ex);
}
};
private/handlers.js
'use strict';
/*
* handlers.js
* Requesthandlers to be called by the routing mechanism
*/
const fs = require("fs"); // file system access
const httpStatus = require("http-status-codes");
const lib = require("../private/libWebUtil"); // home grown utilities
const experimental = require("../private/myTemplater"); // highly experimental template
const experimental1 = require("../private/myCities"); // highly experimental template
const goError = function (res) {
res.writeHead(httpStatus.NOT_FOUND, { // http page not found, 404
"Content-Type": "text/html; charset=utf-8"
});
res.write("<h1>404 Not Found</h1>");
res.end();
};
const getAndRespond = function (path, contentType, res) {
if (fs.existsSync(path)) { // does file exist, sync
fs.readFile(path, function(err, data) { // read
if (err) { // if read error
console.log("nml: " + err); // inform server
goError(res); // inform user
return; // back to caller
}
res.writeHead(httpStatus.OK, contentType); // prep header
res.write(data); // prep body with read data
res.end(); // send response
});
} else {
goError(res); // doesnt exist error
}
}
const receiveData = function (req, res, data) {
let obj = lib.makeWebArrays(req, data); // home made GET and POST objects
res.writeHead(httpStatus.OK, { // yes, write relevant header
"Content-Type": "text/html; charset=utf-8"
});
res.write(experimental.receipt(obj)); // home made templating for native node
res.end();
}
const findCitiesOld = function (req, res) {
const mongo = require('mongodb');
const dbname = "world";
const constr = `mongodb://localhost:27017`;
mongo.connect(
constr, { useNewUrlParser: true, useUnifiedTopology: true},
function (error, con) {
if (error) {
throw error;
}
const db = con.db(dbname); // make dbname the current db
/* Retrieve,
* reads cities from the database
*/
db.collection("city").find().toArray(function (err, city) {
if (err) {
throw err;
}
res.writeHead(httpStatus.OK, { // yes, write relevant header
"Content-Type": "text/html; charset=utf-8"
});
res.write(experimental1.cities(city)); // home made templating for native node
res.end();
con.close();
});
});
}
const getAndDisplay = async function (req, res, dbName, coll, query) {
const mon = require('./monModelMod');
let result = await mon.mongon.mongoFind(dbName, coll, null);
console.log(result);
res.write(experimental1.cities(result)); // home made templating for native node
res.end();
}
const findCities = function (req, res) {
const dbName = "world";
const coll = "city";
getAndDisplay(req, res, dbName, coll, null);
console.log("if you see me first, it asynch");
}
exports.getAndRespond = getAndRespond;
exports.receiveData = receiveData;
exports.findCitiesOld = findCitiesOld;
exports.getAndDisplay = getAndDisplay;
exports.findCities = findCities;
private/myCities.js
/* myCities.js Home made experimental templating */
"use strict";
const cities = function(obj) {
let htmltop = `<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>McKilroy's Second Test Template</title>
<link rel="stylesheet" href="side.css"/>
</head>
<body>
<header>
<h1>Kilroy's Cities</h1>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/side">Side</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
</header>
<div>`;
let htmlbot = ` </div>
</body>
</html>`;
let dynamic = "";
dynamic += `<p><em>${obj[0].name}</em></p>`;
return htmltop + dynamic + htmlbot;
}
exports.cities = cities;
On your CLI do npm test to start the server.
Then go to your browser and test the menu items.
Check the browser screen as well as the console log in each case.