DEV Community

Cover image for #5 Pure NodeJs: Routing (Part 5)
Bashar
Bashar

Posted on

#5 Pure NodeJs: Routing (Part 5)

In the previous tutorials i showed you how to return html ,Json, and plain text as response to nodejs server but all that was on the root route of the application to localhost:2121 in this tutorial we will handle multi routes to serve different type of data in different routes.

programs and versions:
nodejs: v18.19.0
npm: v10.2.3
vscode: v1.85.2

should work on any nodejs > 14

Lets Start:

first we will use the previous server code:

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html' });
  res.end('<h1>Hello World!</h1>');
});

const PORT = 2121;
server.listen(PORT, 'localhost', () => {
  console.log(`server run on port ${PORT}`);
});

Enter fullscreen mode Exit fullscreen mode

first we will move the createServer callback function like this:

//server.js
const listener = (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html' });
  res.end('<h1>Hello World!</h1>');
};

const server = http.createServer(listener);
Enter fullscreen mode Exit fullscreen mode

now we will create routes object:

//server.js
const getHeaders = (type) => ({
  'Content-Type': type,
});

const routes = {
  '/text': (req, res) => {
    res.writeHead(200, getHeaders('text/plain'));
    res.end('hello world!');
  },
  '/json': (req, res) => {
    res.writeHead(200, getHeaders('application/json'));
    res.end(JSON.stringify({ res: 'hello world' }));
  },
};
Enter fullscreen mode Exit fullscreen mode

notice that we create function getHeaders that take content type as parameter and return the header object because we will use it in all routes handler functions.

as you can see we created two routes /json and /text that will return the plain text and json data. now i will add html file and error page to be redirected to if the route not found.

//server.js
const htmlHandler = (req, res) => {
  fs.readFile('index.html', function (err, data) {
    res.writeHead(200, getHeaders('text/html'));
    res.end(data);
  });
};
const errorHandler = (req, res) => {
  res.writeHead(404, getHeaders('application/json'));
  res.end(JSON.stringify({ res: 'Not Found' }));
};
const routes = {
...
 '/html': htmlHandler,
 '/': htmlHandler,
 '/error': errorHandler,
....
}
Enter fullscreen mode Exit fullscreen mode

as you can see we created two handlers for the html and the error because we can reuse it in different routes as we use the html in the root "/" route and in the "/html' route

now to use this routes we need to modifies the listener function:

//server.js
const listener = (req, res) => {
  const route = req.url.split('?')[0].split('/')[1];

  const handler = routes[`/${route}`] || routes['/error'];

  handler(req, res);
};
Enter fullscreen mode Exit fullscreen mode

We can access the request URL from the 'req' object. I split the URL at the '?' to obtain the URL without any query parameters. For example, '/html?foo=bar' will now return only '/html.' I then use another split operation to extract just the first route. Consequently, if the URL is '/html/1,' it will only return 'html' in the handler constant. In the handler constant, I'm attempting to retrieve the route handler from the 'routes' object. I would like to highlight that I added a '/' before the '${route}' to align with the 'routes' object. if the route is in the object it will route that route handler function if not it will return the error handler

you can run and test the server:

//server.js is the file we work on it 
node server.js
Enter fullscreen mode Exit fullscreen mode

now you can open localhost:2121 and test the routes:
html
text
json

the complete code:

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

const getHeaders = (type) => ({
  'Content-Type': type,
});
const htmlHandler = (req, res) => {
  fs.readFile('index.html', function (err, data) {
    res.writeHead(200, getHeaders('text/html'));
    res.end(data);
  });
};
const errorHandler = (req, res) => {
  res.writeHead(404, getHeaders('application/json'));
  res.end(JSON.stringify({ res: 'Not Found' }));
};

const routes = {
  '/text': (req, res) => {
    res.writeHead(200, getHeaders('text/plain'));
    res.end('hello world!');
  },
  '/json': (req, res) => {
    res.writeHead(200, getHeaders('application/json'));
    res.end(JSON.stringify({ res: 'hello world' }));
  },
  '/html': htmlHandler,
  '/': htmlHandler,
  '/error': errorHandler,
};
const listener = (req, res) => {
  const route = req.url.split('?')?.[0].split('/')?.[1];

  const handler = routes?.[`/${route}`] || routes['/error'];

  handler(req, res);
};

const server = http.createServer(listener);

const PORT = 2121;
const HOST = 'localhost';
server.listen(PORT, HOST, () => {
  console.log(`server run on port http://${HOST}:${PORT}`);
});

Enter fullscreen mode Exit fullscreen mode

side note: in the html route i used html file like we did in the Previous article #3 Pure NodeJs: return html file (Part 3) so you should create html file in the same directory as the server.js file.

Conclusion:

In this article, we demonstrate how to manage various routes. In the upcoming article, we will also address the process of serving images.

Top comments (0)