Basic Routing in Node.js

In our previous tutorial, we have learned how to render HTML files in Node.js. But in a typical web application, there will more than one page to load on accessing assigned paths. We need a routing system to handle such.

In this tutorial, we will construct a simple router in Node.js, without the use of any framework like Express.js.

nodejs router

To begin with, we will create three different HTML files and we will load them on accessing three different paths. We will load

The three HTML files are as follows:

index.html

					
						<!DOCTYPE html>
						<html>
						<head>
							<title>Index Page</title>
						</head>
						<body>
							<div>
								Welcome to Node.js!
							</div>
						</body>
						</html>
					
				

about.html

					
						<!DOCTYPE html>
						<html>
						<head>
							<title>About Page</title>
						</head>
						<body>
							<div>
								About Page
							</div>
						</body>
						</html>
					
				

services.html

					
						<!DOCTYPE html>
						<html>
						<head>
							<title>Services Page</title>
						</head>
						<body>
							<div>
								Services Page
							</div>
						</body>
						</html>
					
				

Router Setup

We set up our server.js (or whatever name you gave your main file) as follows, making use of the switch-case block for various routes.

					
					const http = require('http');
					const fs = require('fs');

					const hostname = '127.0.0.1';
					const port = 3000;

					const server = http.createServer((req, res) => {
						let htmlFile = '';
						switch(req.url) {
							case '/':
								htmlFile = 'index.html';
								break;
							case '/about':
								htmlFile = 'about.html';
								break;
							case '/services':
								htmlFile = 'services.html';
								break;
							default:
								break;
						}

						if(htmlFile)
							render(res, htmlFile);
					});

					function render(res, htmlFile) {
					  	fs.stat(`./${htmlFile}`, (err, stats) => {
							res.statusCode = 200;
							res.setHeader('Content-Type', 'text/html');
					  		if(stats) {
							  	fs.createReadStream(htmlFile).pipe(res);
					  		} else {
					  			res.statusCode = 404;
					  			res.end('Sorry, page not found!');
					  		}
					  	});
					}

					server.listen(port, hostname, () => {
					  console.log(`Server running at http://${hostname}:${port}/`);
					});
					
				

We can do away with the switch-case block and use an object instead to map the paths to respective files, which is much neater and less cumbersome. The routing system is assigned as a key-value pair to the routeMap object.

					
					const http = require('http');
					const fs = require('fs');

					const hostname = '127.0.0.1';
					const port = 3000;

					const server = http.createServer((req, res) => {
						res.statusCode = 200;
						res.setHeader('Content-Type', 'text/html');

						const routeMap = {
							'': 'index.html',
							'about': 'about.html',
							'services': 'index.html'
						}

						render(res, routeMap[req.url.slice(1)]);
					});

					function render(res, htmlFile) {
					  	fs.stat(`./${htmlFile}`,  (err, stats) => {
							res.statusCode = 200;
							res.setHeader('Content-Type', 'text/html');

					  		if(stats) {
							  	fs.createReadStream(htmlFile).pipe(res);
					  		} else {
					  			res.statusCode = 404;
					  			res.end('Sorry, page not found');
					  		}
					  	});
					}

					server.listen(port, hostname, () => {
					  console.log(`Server running at http://${hostname}:${port}/`);
					});