Spring Boot Handbook

    Microservice: Spring Cloud API Gateway

    Introduction#

    Spring Cloud API Gateway is a key element of microservices architecture, acting as a unified entry point for managing API requests. Features like intelligent routing, security, load balancing, and request filtering make sure microservices are scalable and efficient.

    Noteworthy features:#

    • Dynamic Routing: Forwards requests to the correct microservice.
    • Security & Authentication: Support for OAuth2, JWT, and role-based access
    • Rate limiting and monitoring: Prevents abuse of APIs and allows for logging.
    • Resilience features: Integration with circuit breakers such as Resilience4J

    With Spring Boot and Spring Cloud together, developers get to implement API Gateway faster and more securely for microservices that at good performance.

    API-Gateway image

    API Gateway#

    APIs are pivotal to all communications of modern applications. In a microservices architecture, independent services run on one server, making the client aware of each microservices’ hostname.

    To easily facilitate this communication, we introduce the API Gateway, which is a fundamental part of an intermediary between clients and microservices. It handles all APIs and other features like:

    • Security: Authentication and authorization protection for APIs
    • Routing: Request routing and response manipulations, as circuit-breaking
    • Observability: Logging, tracing, and metrics aggregation for easier monitoring

    Spring Cloud API Gateway is one of the most widely used Java microservices to provide a scalable, secure, and performant API traffic management solution in distributed systems.

    Spring Cloud API Gateway#

    Spring Cloud API Gateway comes with a great deal of flexibility and strength for efficiently routing traffic between clients and microservices in a microservice architecture.

    Spring Cloud Gateway

    Spring Cloud API Gateway performs a multitude of key functions:#

    • Routing: Routing of the API calls to the required microservice based on URL and other relevant information.
    • Authentication/authorization: To ensure that particular services will be accessible only by authorized users using different built-in security mechanisms, like OAuth2 and JWT.
    • Request and response filtering: Transforming incoming requests and outgoing responses, for example, adding headers and modifying data.
    • Load balancing: Distributing the incoming requests to different instances of microservices according to performance and optimum reliability metrics.

    The Spring Cloud API Gateway provides a single point of management for those aspects of cross-cutting issues in distributed systems, with the bonus that one can add security and scalability on top of what it provides. Accordingly, such an API gateway is eminent when it comes to creating highly available, fault-tolerant, secure microservices.

    Generate Api-Gateway Service:#

    1. Go to https://start.spring.io/ and generate an application using needed dependencies#

    Spring Initializr

    Spring Cloud microservices' API gateway is an Eureka Client so that it can dynamically discover URLs for requests to other registered services without hardcoding them into the configuration. This arrangement provides load balancing, fault tolerance, and scalability because a service would appropriately register with the Eureka server, and the API gateway would dynamically find its whereabouts.

    2. Extract that zip file inside the ecommerce folder and open it as a maven project inside ide.#

    Set maven project

    3. Correcting the api-gateway dependency which is provided by spring initializr.#

    1. The gateway dependency from spring initializr. We need to remove that “-mvc” from it.
    Gateway dependency image
    1. After correction.
    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>

    Spring Cloud Gateway Building Blocks#

    The Spring Cloud Gateway depends on the three principal building blocks that increase the effectiveness with which requests are routed, processed, and filtered within the microservices architecture. Such building blocks allow your API Gateway to scale and extend and to gain additional layers of security.

    Spring Cloud Gateway Building Blocks

    Let us describe them one by one.

    1. Routes#

    • Routes may be understood as, in essence, the directives to connect incoming requests with a downstream service in Spring Cloud Routing.
    • A route comprises a destination URL, a predicate to apply as a condition, and some filters that make request modifications.
    • Routes take the request to the actual microservice through the criteria specified.

    2. Predicate#

    • A predicate is a condition that will check incoming requests against a rule of routing, allowing URL filters, request headers, query parameters, and much more.
    • Predicates help determine which route will be picked to run for a given request.
    • Common predicates include Path, Host, Method, and QueryParam, allowing the developer to route requests based on many factors.

    3. Filters#

    • Filters are used to modify request-and-response messages before leaving the Gateway.
    • There are two deviations of filters:
      1. Pre-filters execute before a request is sent to the backend service (an example is doing authentication).
      2. Post-filters happen after a response is returned from a backend service (an example is logging or response modification).
    • With filters, logging, authentication and authorization, rate limiting, and caching all are supported features.

    With those blocks set up, it's reasonable to configure Spring Cloud Gateway to provide dynamic routing, powerful request processing, and flexible configuration to enable it to be a major player in the microservices ecosystem.

    Spring Cloud Gateway Route#

    Routing specifies the destination endpoints for incoming requests in Spring Cloud Gateway.

    Spring Cloud Gateway Route
    • id: <service-id>: A unique identifier for the route in Spring Cloud Gateway.
    • uri: lb://<SERVICE-NAME>: Defines the destination service URL. Using lb://SERVICE-NAME enables load balancing via registers with the Eureka Server.

    Three core components constitute a route:#

    • Destination URI: The destination endpoint of some microservice where the request would need to be forwarded.
    • Predicates: These describe under which circumstances the route will be applicable (URL path, HTTP method, and so on).
    • Several functions were carried out on the requests before evaluating their routes: filters might be, for example, adding headers, passing authentication data, logging, etc.

    Many combinations of such components allow one to create dynamic routing and flexible request processing; a building block for handling traffic is important in a microservice architecture.

    Spring Cloud Gateway Predicate#

    Spring Cloud Gateway uses predicates to determine which route will service a given request. Predicates work almost like an "if" statement, testing other request properties, such as path, HTTP method, or header.

    Spring Cloud Gateway Predicate

    Some common predicates include:#

    Path Predicate (Path=/your-endpoint/**): Matches a request using the URL path (e.g., /api/v1/orders/**).

    Method Predicate (Method=HTTP_METHOD): Matches requests using the HTTP method (for example, GET).

    Header Predicate (Header=Header-Name, Header-Value): Matches requests depending on a specific header value (for example, matches if User-Agent includes "Mozilla/*").

    Dynamic routing, in turn, is done by configuring routes that will be selected by these predicates.

    servlet.context-path=/api/v1 sets a base path for all endpoints, so URLs will be prefixed with /api/v1. For example, /users become http://localhost:8080/api/v1/users. This helps with API versioning and organization.

    Spring Cloud Gateway Filter#

    In Spring Cloud Gateway, filters are utilized to manipulate the request as well as the response while passing through a gateway. A filter is an instance of Spring WebFilter and can be classified as either a pre-filter that operates before the request is routed to the back-end service (post-filter in all cases of returning response).

    Spring Cloud Gateway Filter

    filters:

    - AddRequestHeader=X-Request-Id, 12345

    - AddResponseHeader=X-Response-id, abcd

    - RedirectTo=302, <https://youtube.com>

    - StripPrefix=1

    - RemoveRequestHeader=Cookie

    AddRequestHeader: Add custom request headers. This adds a request header X-Request-Id with the value 12345.

    AddResponseHeader: Add custom response headers. This adds a response header X-Response-id with the value abcd.

    RedirectTo: Redirect a request to a different URL along with a specified HTTP status code. This redirects the request to https://youtube.com with a 302 HTTP status.

    StripPrefix: Remove a specified number of path segments from the request URL. This removes the first segment of the URL path from the request, useful for simplifying routing to backend services.

    RemoveRequestHeader: Remove some specific headers from incoming requests. This removes the Cookie header from the incoming request.

    These all are the inbuilt/default filters, but we can create our custom filters; we will see it in the next article.

    Filters in a microservice architecture help transform and control the flow of requests as well as responses.

    Configuring api-gateway#

    1. You can configure it inside the application.properties/application.yml file.
    spring: application: name: api-gateway #api-gateway config cloud: gateway: routes: - id: order-service uri: lb://ORDER-SERVICE predicates: - Path=/api/v1/orders/** filters: - StripPrefix=2 - RedirectTo=302, http://codingshuttle.com - id: inventory-service uri: lb://INVENTORY-SERVICE predicates: - Path=/api/v1/inventory/** filters: - StripPrefix=2 - AddRequestHeader=X-Custom-Header, ABCD #eureka client config eureka: client: service-url: defaultZone: http://localhost:8761/eureka instance: prefer-ip-address: true

    Configuring inventory-service#

    1. You can configure it inside the application.properties/application.yml file.
    spring.application.name=inventory-service server.servlet.context-path=/inventory server.port=9020 #DataBase Configuration spring.datasource.url=jdbc:postgresql://localhost:5432/InventoryDB spring.datasource.username=postgres spring.datasource.password=<Password> spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true #eureka config eureka.client.service-url.defaultZone=http://localhost:8761/eureka eureka.instance.prefer-ip-address=true
    1. ProductController Class Code:
    package com.codingshuttle.ecommerce.inventory_service.controllers; @RestController @Slf4j @RequiredArgsConstructor @RequestMapping("/products") public class ProductsController { private final DiscoveryClient discoveryClient; private final RestClient restClient; @GetMapping("/fetchOrder") public String fetchFromOrderService(HttpServletRequest httpServletRequest) { log.info(httpServletRequest.getHeader("X-Custom-Header")); ServiceInstance orderService = discoveryClient.getInstances("order-service").getFirst(); //here this service id came from application name only (go to order application properties u can see the application name return restClient.get() .uri(orderService.getUri()+"/orders/core/helloOrders") .retrieve() .body(String.class); } }

    Configuring order-service#

    1. You can configure it inside the application.properties/application.yml file.
    spring.application.name=order-service server.servlet.context-path=/orders server.port=9010 #DataBase Configuration spring.datasource.url=jdbc:postgresql://localhost:5432/OrderDB spring.datasource.username=postgres spring.datasource.password=$hreY@13082000 spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true #eureka config eureka.client.service-url.defaultZone=http://localhost:8761/eureka eureka.instance.prefer-ip-address=true
    1. OrderController Class Code
    package com.codingshuttle.ecommerce.order_service.controllers; @RestController @RequiredArgsConstructor @RequestMapping("/core") @Slf4j public class OrderController { private final OrderService orderService; @GetMapping("/helloOrders") public String helloOrders(){ return "Hello from OrderService"; } }

    Output#

    1. Run all services:#

    After running all services (the sequence is 1. Run Eureka Server (Discovery Service) 2. Run other clients services. 3. Last run gateway service on default port 8080)

    2. Wait for all registered client services inside Eureka:#

    if your services are not fully registered before another service tries to communicate with them, you may encounter a "Service Unavailable" exception.

    3. Hit the endpoint in the Browser or Postman:#

    After starting Eureka and all client services, test the API using a browser (for GET requests) or Postman (for all requests). If you are trying to fetch other services you can easily fetch it. Here, we are trying to fetch inventory service data by using api-gateway (port=8080). /api/v1 ignored because of using StripPrefix=2 .

    Fetching order

    Ensure the service is registered, then hit the correct URL. If you get a "503 Service Unavailable," wait and retry.

    4. For using AddRequestHeader=X-Custom-Header, ABCD#

    If you try to want the request header value you can print it or using a log you can check it. After hitting http://localhost:8080/api/v1/inventory/products/fetchOrder url in the browser.

    Output of request header value

    5. For usingRedirectTo=302, <http://codingshuttle.com>#

    If you hit the url you will redirect that website. After hitting http://localhost:8080/api/v1/orders/core/helloOrders url in the browser.

    Output as redirect website

    Conclusion#

    This article presents a simplified way to manage traffic to APIs deployed on microservices. It features dynamic routing, security, load balancing, and request filtering and serves as a central subsystem that improves the scalability, performance, and resilience of microservice-based systems.

     

    Last updated on Mar 05, 2025