Spring Cloud Gateway: Concepts, Configuration, Routing, Filters, and CORS Handling

This article introduces Spring Cloud Gateway as a unified entry for microservices, explains its core functions, advantages over Zuul, Maven dependencies, YAML routing configuration, detailed route components, filter types with code examples, custom global filters, execution order, and CORS solutions for backend development.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Spring Cloud Gateway: Concepts, Configuration, Routing, Filters, and CORS Handling

1. Basic Concepts of Gateway

Spring Cloud Gateway is the unified entry point for all microservices, providing reverse proxy (request forwarding), routing & load balancing, authentication & authorization, and request rate limiting.

1.1 Main Functions

Reverse proxy (request forwarding)

Routing and load balancing

Authentication and permission control

Request rate limiting

1.2 Advantages over Zuul

Spring Cloud Gateway is built on Spring 5 WebFlux, using reactive programming for superior performance, whereas Zuul relies on the older servlet‑based, blocking model.

Although Nginx can also act as a gateway, it requires Lua scripts and has a higher learning curve; performance‑wise Nginx is the fastest, but it is rarely used as a gateway.

1.3 Architecture Diagram

Gateway Architecture
Gateway Architecture

Only requests coming from the gateway are accepted by microservices; direct access is denied, which greatly protects services and enables request throttling under high load.

2. Configuring Gateway in Spring Boot

2.1 Maven Dependency

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

<!-- Nacos service discovery starter -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2.2 application.yml Configuration

server:
  port: 10086   # gateway port
spring:
  application:
    name: gateway   # service name
  cloud:
    nacos:
      server-addr: localhost:8848   # Nacos address
    gateway:
      routes:
        - id: user-service   # unique route id
          uri: lb://userservice   # load‑balanced target
          predicates:
            - Path=/user/**   # match paths starting with /user/
        - id: card-service
          uri: lb://cardservice
          predicates:
            - Path=/card/**

Note: Using lb://serviceName allows the address to change without modifying the YAML file, as the load balancer resolves the service name at runtime.

3. Detailed Route Configuration

Each route consists of four parts:

Route ID (id)

Target URI (uri)

Predicates – rules that determine whether a request matches the route

Filters – processing applied to the request/response

3.1 Route ID

The unique identifier for the route.

3.2 Route Target

The destination address; lb://serviceName uses load balancing, while a fixed http://... address is static and less maintainable.

3.3 Predicates

Predicates are strings parsed by Spring Cloud Gateway’s predicate factories. For example, Path=/user/** is handled by

org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory

. The Path factory is the most commonly used.

3.4 Filters

Filters manipulate requests or responses. Spring Cloud Gateway provides 34 built‑in filter factories.

Common Filters
Common Filters

3.4.1 Example of a Local Request Header Filter

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://userservice
          predicates:
            - Path=/user/**
          filters:
            - AddRequestHeader=token,test   # add request header

This adds a header token: test to all requests routed to userservice.

3.4.2 Example of a Global Filter

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://userservice
          predicates:
            - Path=/user/**
      default-filters:
        - AddRequestHeader=token,test   # applies to all routes

Filters defined under default-filters affect every route.

4. Custom Global Filter (Java)

@Component
public class GateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1. Get request parameters
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        String userName = params.getFirst("userName");
        // 2. Allow "root" user
        if ("root".equals(userName)) {
            return chain.filter(exchange);
        }
        // 3. Block others
        exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        return exchange.getResponse().setComplete();
    }

    @Override
    public int getOrder() {
        return -1; // higher priority (smaller value)
    }
}

The order value determines execution precedence; larger numbers mean lower priority.

5. Filter Execution Order

Three kinds of filters exist:

Default filters (default-filters)

Local filters defined per route (filters)

Global Java filters (implementing GlobalFilter)

The execution sequence is: default filters → route‑specific filters → global Java filters.

Filter Order
Filter Order

6. CORS Issues and Solutions

6.1 What Is CORS?

CORS (Cross‑Origin Resource Sharing) allows browsers to make AJAX requests to a different origin (different domain, port, or protocol).

6.2 Common Solutions

Configure CORS in application.yml:

spring:
  cloud:
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true
        corsConfigurations:
          '[/**]':
            allowedOrigins:
              - "http://localhost:8090"
            allowedMethods:
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*"
            allowCredentials: true
            maxAge: 360000

6.3 Programmatic CORS Configuration

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

@Configuration
public class CorsConfig {
    private static final String MAX_AGE = "18000L";

    @Bean
    public WebFilter corsFilter() {
        return (ServerWebExchange ctx, WebFilterChain chain) -> {
            var request = ctx.getRequest();
            if (!CorsUtils.isCorsRequest(request)) {
                return chain.filter(ctx);
            }
            var requestHeaders = request.getHeaders();
            var response = ctx.getResponse();
            var headers = response.getHeaders();
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
            headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());
            var method = requestHeaders.getAccessControlRequestMethod();
            if (method != null) {
                headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, method.name());
            }
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
            headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
            headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
            if (request.getMethod() == HttpMethod.OPTIONS) {
                response.setStatusCode(HttpStatus.OK);
                return Mono.empty();
            }
            return chain.filter(ctx);
        };
    }
}

This filter adds the necessary CORS response headers and short‑circuits OPTIONS pre‑flight requests.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendMicroservicesroutingCORSSpring Cloud GatewayFilters
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.