Hamburger Icon
  • Labs icon Lab
  • Core Tech
Labs

Guided: Implementing an API Gateway in Node.js

In this hands-on lab, you'll learn to implement an API Gateway using Node.js and Express. You'll set up routing of requests to downstream services, transform requests before sending them to a service, and aggregate responses across a set of multiple service. Additionally you will implement rate limiting and authentication across microservices. By the end, you'll have a working API Gateway that implements key concepts of this architectural pattern.

Labs

Path Info

Level
Clock icon Intermediate
Duration
Clock icon 56m
Published
Clock icon Apr 15, 2024

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Adding Routing And Proxying

    Introduction to Implementing Routing and Proxying Logic in the Node.js API Gateway

    In this first step of building an API Gateway using Node.js and Express, we will focus on implementing the routing and proxying logic. This functionality enables the API Gateway to forward incoming requests to the appropriate downstream services and return the responses back to the clients.

    Project Structure Overview:

    • gateway.js: The main file of our API Gateway, containing the Express server setup, routing logic, and middleware configuration. This file will be the focal point for implementing the routing and proxying logic.

    info> If you get stuck along the way, a solution for each task is included in the solutions folder within your filetree.

    Implementing Routing and Proxying Logic

    Your task is to implement the routing and proxying logic inside the predefined route handler for /api/:service in gateway.js. This involves extracting the service parameter from the request URL, constructing the appropriate URL for the downstream service, making an HTTP request to the service using axios, and sending the response back to the client.

    Method Design:

    • Define Route Handler:

      • Use the app.get() method to define a route handler for the /api/:service endpoint.
      • The route handler should be an asynchronous function (using async/await) with req and res parameters.
    • Extract Service Parameter:

      • Inside the route handler function, extract the service parameter from the request URL using req.params.service.
      • Store the extracted value in a variable named serviceName.
    • Construct Service URL:

      • Create a variable named serviceUrl to store the URL of the downstream service.
      • Use a template literal to construct the URL in the format http://localhost:3001/${serviceName}
    • Make HTTP Request:

      • Use a try-catch block to handle the HTTP request and any potential errors.
      • Inside the try block, use axios.get() with the await keyword to make an asynchronous HTTP GET request to serviceUrl.
      • If the request is successful, the response will be stored in a variable named response.
      • Use res.send() to send the response data (response.data) back to the client.
    • Error Handling:

      • Inside the catch block, handle any errors that occur during the HTTP request.
      • Set the response status code to 500 using res.status(500).
      • Use res.send() to send an error message back to the client, indicating that an error occurred while proxying the request.
  2. Challenge

    Adding Request Transformation Middleware

    Introduction to Implementing Request Transformation in the API Gateway

    In this step, you will enhance the API Gateway's functionality by implementing request transformations within the provided transformRequest middleware function. This process involves modifying incoming requests by adding custom headers and query parameters before they are forwarded to the downstream services.

    Implementing Request Transformation Logic

    Your task is to complete the implementation of the transformRequest middleware function in gateway.js. This function should modify incoming HTTP requests by adding a custom header and a query parameter. Additionally, you need to ensure that this middleware is applied to the /api/:service route.

    Method Design:

    • Complete the Middleware Function:

      • Locate the transformRequest function in gateway.js.
      • Add a custom header named X-Custom-Header with the value Hello from API Gateway to the req.headers object.
      • Add a query parameter named apiKey with the value your-api-key to the req.query object.
    • Apply the Middleware:

      • Ensure that the transformRequest middleware is applied to the /api/:service route by passing it as an argument to app.get().
      • The middleware should be applied before the request is proxied to the downstream service.
  3. Challenge

    Adding Response Aggregation

    Introduction to Implementing Response Aggregation in the API Gateway

    For this next step, you will enhance the API Gateway to aggregate responses from two distinct services. By completing this task, you will create a single endpoint that consolidates data from multiple sources, simplifying client-side interactions.

    Implementing Response Aggregation Logic

    Your task is to implement the response aggregation logic within the /aggregate endpoint's route handler in gateway.js. This involves making concurrent requests to two service URLs, aggregating the responses into a single object, and sending the aggregated response back to the client.

    Method Design:

    • Endpoint Configuration:

      • Use the existing app.get() setup for the /aggregate route.
    • Initialization of Service URLs:

      • Within the route handler, define service1Url with the value http://localhost:3001/service1 and service2Url with the value http://localhost:3002/service2
    • Concurrent Requests Setup:

      • Inside a try block, use Promise.all() to make concurrent HTTP GET requests to service1Url and service2Url using axios.get().
      • Assign the result to a constant named responses.
    • Aggregation of Responses:

      • Construct an object named aggregatedResponse.
      • Assign responses[0].data to aggregatedResponse.service1 and responses[1].data to aggregatedResponse.service2.
    • Successful Response Handling:

      • Send the aggregatedResponse back to the client using res.json().
    • Error Management:

      • Implement a catch block to handle any errors that occur during the request or aggregation process.
      • Use console.error() to log the error details.
      • Respond to the client with a 500 internal server error using res.status(500).send().
  4. Challenge

    Adding Rate Limiting

    Rate limiting is crucial for protecting your API Gateway from excessive usage and ensuring fair access to resources. In this task, you will implement rate limiting using the express-rate-limit middleware, which allows you to define rate limiting rules based on the number of requests per IP address within a specified time window.

    Implementing Rate Limiting Logic in gateway.js

    Your task is to implement rate limiting within your gateway.js file by incorporating the express-rate-limit middleware. You will configure the middleware to allow a maximum of 100 requests per 15 minutes for each IP address and apply it globally to protect all routes.

    Method Design:

    • Import Rate Limiting Middleware:

      • At the top of gateway.js, import the express-rate-limit package.
    • Define Rate Limiting Configuration:

      • After importing the necessary modules and initializing the Express app, define a constant variable named apiLimiter to store the rate limiting configuration.
      • Assign the rate limiting middleware to apiLimiter with the following options:
        • Set windowMs to 15 * 60 * 1000 (15 minutes in milliseconds).
        • Set max to 100 (maximum number of requests per IP within the time window).
        • Set standardHeaders to true (include rate limit information in response headers).
        • Set legacyHeaders to false (disable legacy rate limit headers).
    • Apply Rate Limiting Middleware:

      • Immediately after defining apiLimiter, apply it globally to all routes using app.use(apiLimiter)
  5. Challenge

    Adding Authentication

    Introduction to Implementing Authentication in the API Gateway

    In this step, we will focus on implementing basic authentication within the API Gateway. Authentication is a crucial security measure that ensures only authorized users can access protected resources. By adding authentication, you can control who can make requests to your API Gateway and the underlying services.

    Implementing Authentication Logic

    Your task is to implement basic authentication using the express-basic-auth middleware within the API Gateway. This will demonstrate how the API Gateway can secure the routes and protect the backend services by requiring users to provide valid credentials.

    Method Design:

    • Install Authentication Middleware:

      • Ensure you have the express-basic-auth package installed in your project. If not, install it using npm or yarn.
    • Define Authentication Middleware:

      • Create a constant variable named authMiddleware using the basicAuth function from express-basic-auth. This middleware will handle authentication for incoming requests.
    • Define Authentication Credentials:

      • Within the basicAuth configuration object, create an object named users that holds the valid username and password combinations for basic authentication. For example: { admin: 'password' }.
    • Apply Authentication Middleware:

      • Apply the authMiddleware to the routes you want to protect. For instance, you can apply it to specific routes by adding it as a middleware function before the route handler.
    • Handle Unauthorized Access:

      • If a user fails to provide valid credentials, the middleware will automatically challenge them for authentication. You can customize the response message if desired.
  6. Challenge

    Conclusion

    Congratulations on successfully completing the API Gateway Implementation Lab!

    Throughout this lab, you've made substantial progress in developing a comprehensive API Gateway using Node.js and Express. This gateway serves as a critical component in managing the flow of data between clients and multiple backend services, enhancing both security and efficiency.

    Summary of Your Achievements:

    • API Gateway Pattern: You've explored the API Gateway pattern extensively, learning how it integrates into microservice architectures to provide a unified entry point for various services.

    • Routing and Proxying: You've successfully set up routing configurations that direct requests to the correct downstream services, along with proxying logic that ensures these requests are handled appropriately.

    • Request Transformation: By modifying requests as they pass through your gateway, you've ensured that each one is tailored to the needs of the downstream services it interacts with.

    • Response Aggregation: You've implemented logic to aggregate responses from multiple services, simplifying client-side interactions by providing a single, cohesive response.

    • Rate Limiting and Authentication: You've added security layers by implementing rate limiting to protect your services from overuse and authentication to ensure that only authorized users can access your API Gateway.

    Interacting with Your API Gateway:

    Feel free to test and interact with your API Gateway by starting the server with node gateway.js and visiting the endpoints you've configured. For example, you can:

    • Add new routes to handle different types of requests.
    • Adjust the rate limiting settings to see how they affect incoming traffic.
    • Enhance security measures by refining the authentication process.

    Further Development:

    Your API Gateway is now set up to handle basic tasks, but there's room for further enhancement. Consider integrating more advanced security features, such as OAuth, or adding logging and monitoring capabilities to gain insights into traffic patterns and potential security threats.

    Further Learning Resources:

    To continue improving your skills in Node.js, Express, and general backend development, consider exploring additional courses on Pluralsight. Delve deeper into areas like advanced routing techniques, security enhancements, and performance optimization to build more robust and scalable applications.

Victor is an Assessment Author.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.