You have wondered, and why the server does not respond with real HTML5, and not generated HTML5 fragments. Until now this has been done to show the structure of a server. Now we want more.
Following the best practice outlined in
the section called “Project Creation - Best Practice” we create a project myg60new
remotely, clone it, prepare the
package.json, and before we get to the server,
we create a project subdirectory views,
and in that we create a boilerplate index.html
for welcoming users to our site. The static front page
if you will.
myg60new/views/index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>myg6n Home Page</title>
</head>
<body>
<header>
<h1>Welcome World!</h1>
</header>
<main>
<p>
To our regular old fashioned frontend static homepage.
</p>
</main>
<footer>
<p>
© nml
</p>
</footer>
</body>
</html>
We shall get back to that page. First we adapt the modularized project code from the previous section. You will notice that some of the modules are written in such a way that they have become invariant, project agnostic, so that they can be used unchanged in all native Node.js projects.
Keeping the naming convention standard in all projects, the
invariant code is in main.js, and in
server.js. The routing and handling is certainly
project specific, because it holds the concrete logic for
the application, so they vary.
myg60new/main.js, Unchanged!"use strict";
var server = require("./server"); // make server module available
var router = require("./router"); // router module
server.start(router); // start server
// callback to route
myg60new/server.js, Unchanged!"use strict";
/*
* new server.js adds request body data
*/
const http = require("http"); // http module
const lib = require("../private/libWebUtil"); // home grown utilities
const hostname = "localhost";
const port = Number(process.argv[2]) || 3000;
module.exports = {
start(router) {
const server = http.createServer();
server.on("request", function (req, res) { // eventhandler for "request"
console.log(lib.makeLogEntry(req)); // home made utility for logging
let body = [];
req.on("data", function (bodyData) { // eventhandling for data reception
body.push(bodyData); // bodyData is an object
});
req.on("end", function () { // eventhandling for end-of-data
body = Buffer.concat(body).toString(); // body2string
router.route(req, res, body); // pass to router
});
});
server.listen(port, hostname, function () {
console.log(`Log: Server started on http://${hostname}:${port}/`);
});
}
}myg60new/router.js
In this particular instance, we use the same project as in the previous section, so the following code remains unchanged beause our stepwise refinement is in the handlers.
"use strict";
/*
* check if routed handler function exists
* if yes call it, else complain
*/
const handlers = require("./handlers"); // handlers module
const requestHandlers = { // application urls here
"/home": handlers.home,
"/info": handlers.info,
"/contact": handlers.contact,
"/about": handlers.about,
"/hello": handlers.hello,
"/notfound": handlers.notfound,
}
module.exports = {
route(req, res, body) {
if (typeof requestHandlers[req.url] === 'function') { // look for route
requestHandlers[req.url](req, res); // if found use it
} else {
requestHandlers["/notfound"](req, res); // use notfound
}
}
}
myg60new/handlers.js
'use strict';
/*
* handlers.js
* Requesthandlers to be called by the router mechanism
*/
const fs = require("fs"); // file system access
module.exports = {
home(req, res) {
fs.readFile("views/index.html", function(err, data) {
if (err) {
res.end("<h1>The page you wanted doesn't exist</h1>");
}
res.write(data);
res.end();
});
},
notfound(req, res) {
console.log(`Log: No handler found for route ${req.url}.`);
res.end();
}
}
On your CLI do npm test to start the server.
Then go to your browser and test the following
url(s).
Check the browser screen as well as the console log in each case.