NodeJS Gateway — Part 3: Routes and Middleware
Photo by Bogdan Karlenko on Unsplash
This is part of the Building a payment gateway using JavaScript series. You can check out the previous parts below;
Intro: How I built a Payment Gateway using JavaScript
Part 1: Initial Setup
Part 2: Setting Up our Database (MongoDB)
Part 3 (Here): Routes and Middleware
Routes
With NodeJS, comes the popular Express JS which is an open-source Node.js framework for building web applications. It provides a simple and flexible way to create server-side applications, handling HTTP requests and responses, routing, middleware, and more. Express makes it easy to build fast and scalable APIs, as well as dynamic web pages, and has a large community of developers who contribute to its development and offer support. With Express, developers can build robust and reliable web applications with a minimum of code and effort.
We can now go ahead and install Express in our application using the command below in our terminal.
npm install express --save
Great now we can create our routes. Since we are creating a payment gateway, lets use 2 endpoints that is status and collect.
For the endpoint responses you can have any data that you believe will be helpful to the API consumer, therefore, our responses will have a JSON structure as below.
{
"code": 200,
"status": "success",
"data": {}
}
From the above the code value can be any HTTP status code according to the action carried out and the status value has to correspond with the code.
You can learn more about the HTTP status codes below.
HTTP response status codes - HTTP | MDN
And from the introduction of these series, we are going to follow RESTFul API practices. To know more about these you can visit the sites below.
- Web API design best practices - Azure Architecture Center
- What is RESTful API? - RESTful API Beginner's Guide - AWS
Alright, let’s go ahead and create our 2 endpoints under api routes as below.
First we have the status endpoint:
//This is in the index.ts file under the routes folder
import express from 'express'
const router = express.Router();
const transactions = require('./transactions');
router.use(transactions);
router.get("/status", (req, res) => {
console.log('here');
res.status(200).json({
code: 200,
status: "success",
data: {
app: "Gateway",
msg: "You are welcome to my amazing payment gateway"
}
})
});
export default router;
From the above you can see that we imported the transaction routes that we used in our last step in to the index file of the routes, this can be helpful in organising our code so that we can just import only the index file in the app.ts file of the gateway.
When we start the Node server (refer to previous steps), we will get the response for this endpoint similar to the one below.
Response from the status endpoint.
Now let’s move to the collect endpoint. This will be the one used to initiate or complete payments. And our endpoint will look as below.
import express from 'express'
const router = express.Router();
import { collect } from '../controllers/collect'
router.post("/collect", (req, res) => {
//call the collection function from the controller
collect(req.body, res)
});
export default router;
Looking at our code, you can see that we imported the collect function from the collect controller (we will be looking at controllers in our next step) and we called it in the endpoint function. This means that when when we request to collect payment, the endpoint will relay our request and data over to the collect function to be processed as desired. We can also see that our endpoint uses the POST method and not the GET method like for our status.
A simple way of explaining how to use the 2 methods is, the GET method carries parameters appended in the URL for example an ID for a transaction whose status you can to get while to the POST method the parameters are carried in the body of the request.
Read more about this here
and here
Difference between HTTP GET and POST Methods - GeeksforGeeks
We can now add our collect endpoint to the index route file as below.
import express from 'express'
const router = express.Router();
import transactions from './transactions';
import collect from './collect';
router.use(transactions);
router.use(collect);
...
We can now go ahead and build then run the server. We will get a response as below for our collect endpoint.
Response for the collect endpoint
You can see that the response is different, do not worry the response was generated by a function which our route directed the request to.
Middleware
This refers to functions that have access to the request and response objects, and can perform actions such as parsing incoming requests, adding headers, or performing authentication and authorization. Middleware functions in web development can be thought of as “glue” that ties together different parts of an application and allows them to work together.
In frameworks such as Express.js, middleware is an important concept that allows developers to extend the functionality of their application by adding custom logic to the request/response cycle. Middleware functions can be added to an Express application by using the app.use() method, and they are executed in the order they are defined. This makes it easy to add or modify the behavior of an application, and can help to keep code clean and organized. If you have been following, we added our routes via app.use() in the app.ts file. In the Initial Step of these series we also looked at how the body-parser middleware was added using the same method.
You can also create a customised middleware according to what your desire is. They can be added in the app.ts file to work globally or for a specific function or even route. For example we can to pass a collection type value in the body of our collect request.
We can create a middleware that returns a error if the type value is not passed in the request body. For this we can use body which is a function provided by a NodeJS package called express-validator, and we are going to use it to check if type is available and not null in the request body of the collect endpoint.
First we install express-validator
npm install express-validator --save
We can now implement it in our collect endpoint to check the body for a value of type.
//This is in the collect router file
import express from 'express'
const router = express.Router();
const { body, validationResult } = require('express-validator');
import { collect } from '../controllers/collect'
router.get("/collect", body('type').not().isEmpty(), (req, res) => {
//Use Middleware to check if required values are available
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
code: 400,
status: "error",
data: errors.array()
});
}
//call the collection function from the controller
collect(req.body, res)
});
export default router;
In the above, we are checking if the type value in the body is not Empty, and to pass on the request to the controller if provided or return an error response if null.
Below is a response we get if we do not provide a value for type.
Error response from middleware.
Below is the response we get if we provide the type value in the request body.
The middleware can be customised further to help in securing the API access by checking for Authorisation headers, and sanitising the request for proper processing. There also other important middleware tat you can use in your project for example helmet (configure HTTP headers), cors (for Cross-Origin Resource Sharing configs) etc.
You can see the final code using the link below, otherwise let’s catchup in the next step talking about controllers.
GitHub - Cank256/payie: A payment solution project
Top comments (0)