We have just seen statically routed serving of an asset read
by the servers fs. Let change it a bit to cater
for dynamic routing. Dynamic in the sense that whatever url
you address will be looked for by the router. I found it will
be served, if not we get a 404.
Again, following the best practice outlined in
the section called “Project Creation - Best Practice” we create a project myg61
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. Here you may use a copy of the one we just saw
in the previous section.
The dynamic routing means that you may add .html
files to the views directory, and they will
be routed to and served if addressed by the url.
Indeed the main.js, and the server.js
need not be changed. They are thus far sufficiently dynamic.
They are repeated below for ease of reading.
The router and the handlers are naturally project specific,
as stated before, and must be adapted to the current project.
myg61/main.js, Unchanged!"use strict";
var server = require("./bin/server"); // make server module available
var router = require("./routes/router"); // router module
server.start(router); // start server
// callback to route
myg61/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}/`);
});
}
}myg61/router.js
The router has been changed here to accomodate the
/home route as well as the /side
which we shall return to promptly.
"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,
"/side": handlers.side,
"/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
}
}
}
myg61/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();
});
},
side(req, res) {
fs.readFile("views/side.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(`Handler 'notfound' was called for file ${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.
We have prepared an extra page for you:
views/side.html
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>myg6n Side Demo Page</title>
<link rel="stylesheet" href="side.css"/>
<script src="side.js"></script>
</head>
<body>
<header>
<h1>Welcome World!</h1>
</header>
<main>
<p>
To our regular old fashioned frontend static homepage.
</p>
<p style="background-color: black;">
<img src="iau_rocks.png" alt="ia rocks"/>
</p>
</main>
<footer>
<p>
© nml
</p>
</footer>
</body>
</html>
Now we show this:
file:///home/nml/nodeMyGPNode/myg61/views/side.html
in our browser in order to
verify that the css, js, and image works. Then addressing the
page through
http://localhost:3000/side we see that it doesn't.
Let us talk a bit about the HTTP protocol to understand why
not. Then we shall move on to the next section to make it work.