Different Problem, One Solution : API Gateways
Grenish rai
Posted on July 10, 2024
Greetings fellow developers, both experienced and newcomers.
Have you ever found yourself dealing with various APIs featuring different endpoints, leading to confusion about which one the frontend should access? Perhaps you even accidentally exposed all endpoint responses to the frontend.
There exists a solution to this issue: the API Gateway.
What is API Gateway?
API Gateway is a service that helps manage and secure APIs (Application Programming Interfaces). It acts as a front door for the APIs, routing requests to the appropriate backend services, handling API versioning, security, and access control, and also providing features like rate limiting and caching. In simpler terms, API Gateway facilitates the communication and interaction between different software applications.
Lets say you have a mobile e-commerce app with various features like user authentication, product search, and ordering. To manage the APIs for this app, you can use Amazon API Gateway. With API Gateway, you can create different API endpoints for user authentication, product search, and order placement.
For instance, you can set up an API endpoint /auth
for user authentication that routes incoming requests to a Lambda function for verifying user credentials. Another endpoint /products
can handle product search requests by connecting to a separate backend service that retrieves product information from a database.
Additionally, let's implement API versioning by creating different versions of the APIs to support backward compatibility. The API Gateway allows you to easily manage and switch between versions without disrupting the app's functionalities.
Moreover, you can enhance security by setting up API key authentication or integrating with IAM roles to control access to specific APIs. With features like rate limiting, you can prevent abuse of the APIs by restricting the number of requests a user can make within a certain time period.
By utilizing API Gateway in this scenario, you can effectively manage and secure the communication between your mobile e-commerce app and the backend services, ensuring a seamless and protected experience for your users.
Some most used API Gateway examples include AWS API Gateway, Azure API Management, Google Cloud Endpoints, and Kong.
Work In Progress
After understanding What, let's move on to How.
To begin with, create an empty repository
mkdir api-gateway
Next, initialize npm
npm init
Once npm is initialized, proceed to install necessary packages for the application
npm i express nodemon morgan express-rate-limit axios
Create an index.js
file in the repository, and your final result should resemble this.
Ensure making slight alterations within package.json
file to initiate nodemon
. Optionally, you may set "type": "module"
for proceeding with ES6, although our approach will be in CommonJs.
Starting with necessary imports,
const express = require('express');
const axios = require('axios');
const rateLimit = require('express-rate-limit');
const morgan = require('morgan');
initializing the app
const app = express();
const PORT = 3000;
NOTE: Although CORS is not utilized in this example, it is essential to implement it.
Let's set the middleware for Morgan
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.use(limiter);
app.use(morgan('combined'));
And for error handlers middleware
const handleError = (err, req, res, next) => {
console.error(err);
res.status(500).send('Internal Server Error');
};
app.use(handleError);
In this instance, we will utilize the dummy APIs provided by JSONPlaceHolder and ReqRes.
-
JSONPlaceHolder
-
/posts
- Fetch a collection of posts. -
/comments
- Access a set of comments. -
/albums
- Get a listing of albums. -
/photos
- Obtain a series of photos. -
/todos
- Get a rundown of todos. -
/users
- Retrieve a register of users.
-
-
ReqRes
-
/login
- Used for requesting login access.
-
app.use('/api', async (req, res, next) => { ... }
inside we'll implement try
and catch
method
try{ ... } catch (error) { ... }
inside try
lets start the main work
let response;
const path = req.path;
if (
path.startsWith("/posts") ||
path.startsWith("/comments") ||
path.startsWith("/albums") ||
path.startsWith("/photos") ||
path.startsWith("/todos") ||
path.startsWith("/users")
) {
// Route to JSONPlaceholder
response = await axios.get(`https://jsonplaceholder.typicode.com${path}`);
} else if (path.startsWith("/reqres-users")) {
// Route to ReqRes
response = await axios.get(`https://reqres.in/api${path}`);
} else if (path.startsWith("/reqres-login")) {
// Handle ReqRes login
response = await axios.post("https://reqres.in/api/login", {
email: "eve.holt@reqres.in",
password: "cityslicka",
});
} else {
res.status(404).send("Endpoint not found");
return;
}
res.json(response.data);
And that is it. We're done implementing our first API Gateway.
The overall code should look like this.
const express = require("express");
const axios = require("axios");
const rateLimit = require("express-rate-limit");
const morgan = require("morgan");
const app = express();
const PORT = 3000;
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
});
app.use(limiter);
app.use(morgan("combined"));
// Error Handling Middleware
const handleError = (err, req, res, next) => {
console.error(err);
res.status(500).send("Internal Server Error");
};
app.use(handleError);
// Unified API endpoint
app.use("/api", async (req, res, next) => {
try {
let response;
const path = req.path;
if (
path.startsWith("/posts") ||
path.startsWith("/comments") ||
path.startsWith("/albums") ||
path.startsWith("/photos") ||
path.startsWith("/todos") ||
path.startsWith("/users")
) {
// Route to JSONPlaceholder
response = await axios.get(`https://jsonplaceholder.typicode.com${path}`);
} else if (path.startsWith("/reqres-users")) {
// Route to ReqRes
response = await axios.get(`https://reqres.in/api${path}`);
} else if (path.startsWith("/reqres-login")) {
// Handle ReqRes login
response = await axios.post("https://reqres.in/api/login", {
email: "eve.holt@reqres.in",
password: "cityslicka",
});
} else {
res.status(404).send("Endpoint not found");
return;
}
res.json(response.data);
} catch (error) {
next(error);
}
});
app.listen(PORT, () => {
console.log(`API Gateway running on port ${PORT}`);
});
Test and Results
Its time to test our API Endpoint, I'm using Insomnia, but you can use any of your choiceSure, let's go ahead and send a request to the API endpoint to see if everything is working as expected.
Keep Hacking!
Posted on July 10, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.