Home  >  Article  >  Java  >  Building a Simple API Gateway with Spring Cloud Gateway

Building a Simple API Gateway with Spring Cloud Gateway

Patricia Arquette
Patricia ArquetteOriginal
2024-11-03 12:14:02482browse

In modern microservices architectures, an API Gateway is essential. It provides a single entry point for multiple services, allowing us to manage routing, security, rate limiting, load balancing, and more. In this article, we’ll explore how to set up a basic API Gateway using Spring Cloud Gateway and direct requests to different endpoints based on paths. We'll also demonstrate how to use filters to manipulate paths dynamically.

Let’s dive into the code!

Building a Simple API Gateway with Spring Cloud Gateway

Oh no !!

Prerequisites

To follow along, you’ll need:

  • Java 11 or higher
  • Spring Boot (3.0 or later recommended)
  • Reactive Spring Cloud Gateway

Project Setup

Create a new Spring Boot project and include the Spring Cloud Gateway dependency. You can do this easily by setting up a new project on Spring Initializr, selecting Spring Boot and Reactive Spring Cloud Gateway under dependencies.

Here's the pom.xml snippet:

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

Building the API Gateway

Let’s configure our Gateway to handle requests for three different paths:

  1. /get/country/{name} – To fetch details about a country.
  2. /get/language/{name} – To get information based on language.
  3. /get/subregion/{name} – To retrieve data for specific subregions.

"We’ll use the REST Countries API to simulate the other microservices we have in our architecture."


Setting Up the Routes

I've created a folder called router near the application's main file. Inside it, we’ll create a file called Routes.java where we define our routes, configure each path, and apply filters to dynamically direct requests.

package dev.mspilari.api_gateway.router;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Routes {

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("country_route", p -> p
                        .path("/get/country/{name}")
                        .filters(f -> f.setPath("/v3.1/name/{name}"))
                        .uri("https://restcountries.com"))

                .route("language_route", p -> p
                        .path("/get/language/{name}")
                        .filters(f -> f.setPath("/v3.1/lang/{name}"))
                        .uri("https://restcountries.com"))

                .route("subregion_route", p -> p
                        .path("/get/subregion/{name}")
                        .filters(f -> f.setPath("/v3.1/subregion/{name}"))
                        .uri("https://restcountries.com"))
                .build();
    }
}

Explanation of the Code

  • Route Definitions: we define each route using the route method, which takes an identifier (e.g., country_route) and a lambda that defines the path.

  • Path Matching: .path("/get/country/{name}") is used to match the incoming URL pattern. {name} is a variable that can be dynamically replaced by any value, such as a country name like “Brazil”.

  • Filters: we use SetPath to modify the outgoing request path. For example, .setPath("/v3.1/name/{name}") rewrites /get/country/{name} to /v3.1/name/{name}, the endpoint required by the REST Countries API.

  • URI: we set the uri to https://restcountries.com, which serves as the base URL. Spring Cloud Gateway will send the modified path to this URI.


Running the Gateway

Start your Spring Boot application. Now, you can make requests to the Gateway, and it will forward them to the correct endpoint.

Try the following commands in your terminal to test the routes:

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

Each request will be routed by the Gateway to the respective REST Countries API endpoint, based on the path and parameter.


Verifying the Response

If everything is configured correctly, you should see responses that match what you'd get from directly calling the REST Countries API.

For example:

package dev.mspilari.api_gateway.router;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Routes {

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("country_route", p -> p
                        .path("/get/country/{name}")
                        .filters(f -> f.setPath("/v3.1/name/{name}"))
                        .uri("https://restcountries.com"))

                .route("language_route", p -> p
                        .path("/get/language/{name}")
                        .filters(f -> f.setPath("/v3.1/lang/{name}"))
                        .uri("https://restcountries.com"))

                .route("subregion_route", p -> p
                        .path("/get/subregion/{name}")
                        .filters(f -> f.setPath("/v3.1/subregion/{name}"))
                        .uri("https://restcountries.com"))
                .build();
    }
}

Benefits of Using Spring Cloud Gateway

  1. Single Entry Point: all requests pass through the Gateway, simplifying client interactions and API management.
  2. Flexible Routing: Routes can be easily customized with path parameters and filters.
  3. Dynamic Path Rewriting: The Gateway allows us to adjust request paths dynamically, making it easy to integrate with external APIs without changing the client-side code.

Next Steps

This setup covers the basics of routing with Spring Cloud Gateway. In the next posts, we'll explore additional features, like:

  • Authentication and Authorization – secure routes by integrating with OAuth or JWT.
  • Rate Limiting and Circuit Breakers – add resilience with built-in filters.
  • Load Balancing – distribute requests across multiple instances for better performance.
  • Logging and Observability – gain insights into application behavior and performance, and monitor traffic patterns through distributed tracing and centralized logging.

? Reference

  • Spring Cloud Gateway
  • Building a gateway

? Talk to me

  • LinkedIn
  • Github
  • Portfolio

The above is the detailed content of Building a Simple API Gateway with Spring Cloud Gateway. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn