How to create routing process with Node.js native HTTP module

I will show you how to create a routing process using the native HTTP module of Node.js. The code is also posted on Git Hub, so please refer to it.

overview

I’ll show you how to easily use routing using Node.js’ native HTTP module. Routing is defined by specifying endpoints for handling HTTP requests.

Below, we’ll explore routing concepts, defining routes, creating route handlers, handling routing parameters, and options for routes in more detail.

Here, we will explain the routing method using the following versions.

nodejs v19.7.0

In addition, all the code created this time is posted on GitHub.

How to create a route

Routing defines how a Node.js application handles requests from clients when they reach specific endpoints.

Routing is defined by a combination of HTTP methods (GET, POST, PUT, DELETE, etc.) and paths (URLs). route.js

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

const server = http.createServer((req, res) => {
  const parsedUrl = url.parse(req.url, true);
  const path = parsedUrl.pathname;
  const trimmedPath = path. replace(/^\/+|\/+$/g, '');
  
  const chosenHandler = typeof(router[trimmedPath]) !== 'undefined' ? router[trimmedPath] : handlers.notFound;

  chosenHandler((statusCode, payload) => {
    res.writeHead(statusCode);
    res.end(JSON.stringify(payload));
  });
});

server.listen(3000, () => {
  console.log('Server started on port 3000');
});

const handlers = {
  sample: (callback) => {
    callback(200, {name: 'sample handler'});
  },
  notFound: (callback) => {
    callback(404);
  },
};

const router = {
  'sample': handlers. sample,
  "notFound": handlers.notFound
};

Commentary

  • Import HTTP and URL modules
const http = require('http');
const url = require('url');

This code imports the ‘http’ module, which provides HTTP server functionality, and the ‘url’ module, which provides URL parsing functionality.

  • Create and start HTTP server
const server = http.createServer((req, res) => {...});

server.listen(3000, () => {
  console.log('Server started on port 3000');
});

Here, an HTTP server is created using the createServer method of the ‘http’ module and started on port 3000.

  • parsing the request URL
const parsedUrl = url.parse(req.url, true);
const path = parsedUrl.pathname;
const trimmedPath = path. replace(/^\/+|\/+$/g, '');

When the server receives the request, it parses the request URL and removes leading and trailing slashes to get the path.

  • Handler selection
const chosenHandler = typeof(router[trimmedPath]) !== 'undefined' ? router[trimmedPath] : handlers.notFound;

Select the appropriate handler function based on the parsed path. Selects the default ’notFound’ handler if no handler for the path exists in the router object.

  • Execute handler and send response
chosenHandler((statusCode, payload) => {
  res.writeHead(statusCode);
  res.end(JSON.stringify(payload));
});

Executes the selected handler and returns the result to the client as an HTTP response. The handler function calls a callback function with the status code and payload as arguments.

  • Define handler functions and router objects
const handlers = {
  sample: (callback) => {
    callback(200, {name: 'sample handler'});
  },
  notFound: (callback) => {
    callback(404);
  },
};

const router = {
  'sample': handlers. sample,
  "notFound": handlers.notFound
};

Here we define handler functions for each request path. It also defines a router object that associates those handler functions with paths.

test

# test GET request
curl -X GET http://localhost:3000/sample
curl -X GET http://localhost:3000/notfound

How to use various API methods

api.js

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

const server = http.createServer((req, res) => {
  const parsedUrl = url.parse(req.url, true);
  const path = parsedUrl.pathname;
  const trimmedPath = path. replace(/^\/+|\/+$/g, '');

  const chosenHandler = typeof (router[req.method][trimmedPath]) !== 'undefined' ? router[req.method][trimmedPath] : handlers.notFound;

  collectRequestData(req, result => {
    chosenHandler(result, (statusCode, payload) => {
      res.writeHead(statusCode);
      res.end(JSON.stringify(payload));
    });
  });

});

function collectRequestData(request, callback) {
  const FORM_URLENCODED = 'application/json';
  if (request.headers['content-type'] === FORM_URLENCODED) {
    let body = '';
    request.on('data', chunk => {
      body += chunk.toString();
    });
    request.on('end', () => {
      callback(JSON.parse(body));
    });
  }
  else {
    callback(null);
  }
}

server.listen(3000, () => {
  console.log('Server started on port 3000');
});

const handlers = {
  getUsers: (data, callback) => {
    callback(200, { name: 'get users handler' });
  },
  postUser: (data, callback) => {
    callback(200, { name: 'post user handler', data: data });
  },
  putUser: (data, callback) => {
    callback(200, { name: 'put user handler', data: data });
  },
  deleteUser: (data, callback) => {
    callback(200, { name: 'delete user handler' });
  },
  notFound: (data, callback) => {
    callback(404);
  },
};

const router = {
  'GET': {
    'users': handlers. getUsers,
  },
  'POST': {
    'users': handlers.postUser,
  },
  'PUT': {
    'users': handlers. putUser,
  },
  'DELETE': {
    'users': handlers. deleteUser,
  }
};

Commentary

This code implements a simple Web API that uses Node.js to set up an HTTP server and handle requests for specific endpoints and HTTP methods. Specifically, it accepts GET/POST/PUT/DELETE methods against the ‘users’ path and handles them with appropriate handlers. Each part of the code is detailed below.

  • Import required modules
const http = require('http');
const url = require('url');

It imports two built-in modules called http and url. http is used to set up an HTTP server and url is used to parse the URL of the request.

  • Create HTTP server
const server = http.createServer((req, res) => {
  // continues below...
});
server.listen(3000, () => {
  console.log('Server started on port 3000');
});

Create an HTTP server using the http.createServer method and listen for requests on port 3000. Each request from the client is handled by the callback function passed to createServer.

  • parsing the request path
const parsedUrl = url.parse(req.url, true);
const path = parsedUrl.pathname;
const trimmedPath = path. replace(/^\/+|\/+$/g, '');

I am parsing the URL of the received request and getting the path it points to. We’ve also removed leading and trailing slashes from paths to make the routing process easier.

  • routing
const chosenHandler = typeof (router[req.method][trimmedPath]) !== 'undefined' ? router[req.method][trimmedPath] : handlers.notFound;

Select the appropriate handler based on the HTTP method and path of the request. A request to a non-existing path or method will choose the notFound handler which returns a 404 error.

  • Collection of request data
collectRequestData(req, result => {
  chosenHandler(result, (statusCode, payload) => {
    res.writeHead(statusCode);
    res.end(JSON.stringify(payload));
  });
});

The collectRequestData function reads data from the request body. The read data is passed to chosenHandler, which returns the result of processing the request to the client.

  • define handlers and routers
const handlers = {
  getUsers: (data, callback) => {
    callback(200, { name: 'get users handler' });
  },
  // continues below...
};

const router = {
  'GET': {
    'users': handlers. getUsers,
  },
  // continues below...
};

Defines handlers for GET/POST/PUT/DELETE methods for the ‘users’ path. Each handler receives a callback function along with the request data and calls that callback to return the response. Each handler is also registered with the router object as an HTTP method and path.

test

## get user
curl -X GET http://localhost:3000/users
# create user
curl -X POST -H "Content-Type: application/json" -d '{"id":"1","name":"John Doe"}' http://localhost:3000/users
# update user
curl -X PUT -H "Content-Type: application/json" -d '{"id":"1","name":"John Smith"}' http://localhost:3000/users
# remove user
curl -X DELETE -H "Content-Type: application/json" -d '{"id":"1"}' http://localhost:3000/users

summary

In this article, you learned about routing. Routing is the process of selecting the appropriate handler based on the request’s path and HTTP method. Implementing routing makes it easier to implement a Web API. Next time, we will implement a simple Web API using routing.