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

This article introduces Spring Cloud Gateway as a unified entry point for microservices, explains its core functions, compares it with Zuul, provides Maven and YAML configuration examples, details route definitions, filter types and ordering, shows how to implement custom filters, and demonstrates CORS solutions using both YAML and Java code.

Top Architect
Top Architect
Top Architect
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.

1.1 Main Functions

Reverse proxy (request forwarding)

Routing and load balancing

Authentication and authorization

Rate limiting

1.2 Advantages over Zuul

Spring Cloud Gateway is built on Spring 5 WebFlux, offering reactive programming and superior performance compared to the servlet‑based, blocking implementation of Zuul.

Although Nginx can also serve as a gateway, it requires Lua scripts, has a higher learning cost, and is rarely used for this purpose; however, in pure performance terms, Nginx is the fastest.

1.3 Architecture Diagram

Microservices only accept requests from the gateway; direct access is rejected, which greatly protects services and enables request‑level rate limiting.

2. Configuring Gateway in Spring Boot

2.1 Maven Dependency

<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'><!--网关 起步依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现 起步依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</code>

2.2 application.yml Configuration

<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>server:
  port: 10086   # 网关端口
spring:
  application:
    name: gateway   # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848   # nacos 地址
    gateway:
      routes:
        - id: user-service   # 路由 id,唯一
          uri: lb://userservice   # 使用服务名 + 负载均衡
          predicates:
            - Path=/user/**   # 路径匹配
        - id: card-service
          uri: lb://cardservice
          predicates:
            - Path=/card/**
</code>
Note: The routes list can contain multiple entries; each entry starts with a dash.

Using lb://userservice lets the program resolve the actual instance via load balancing, avoiding hard‑coded URLs.

2.3 Route Configuration Details

Four main parts of a route:

Route ID (id)

Target URI (uri)

Predicates – rules that determine whether a request matches the route

Filters – processing applied to request or response

2.3.1 Route ID

The unique identifier of the route.

2.3.2 Route Target

The destination address; lb://service-name uses service‑name based load balancing, which is more maintainable than a fixed HTTP URL.

2.3.3 Predicates

Predicates are strings parsed by PredicateFactory classes. For example, Path=/user/** is handled by PathRoutePredicateFactory.

2.3.4 Filters

Spring Cloud Gateway provides 34 filter factories. Common ones include adding request headers, rate limiting, etc.

2.4 Example of Local (Route‑Specific) Filter

<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://userservice
          predicates:
            - Path=/user/**
          filters:
            - AddRequestHeader=token,test   # 添加请求头
</code>

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

2.5 Example of Global (Default) Filter

<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://userservice
          predicates:
            - Path=/user/**
      default-filters:
        - AddRequestHeader=token,test   # 添加请求头
</code>

Filters under default-filters apply to all routes.

3. Custom Global Filter Implementation

When built‑in filter factories are insufficient, a Java class implementing GlobalFilter and Ordered can be created.

<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>@Component
public class GateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1. Get query parameters
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        String userName = params.getFirst("userName");
        if ("root".equals(userName)) {
            // allow
            return chain.filter(exchange);
        }
        // deny
        exchange.getResponse().setStatusCode(500);
        return exchange.getResponse().setComplete();
    }
    @Override
    public int getOrder() {
        return -1; // higher priority
    }
}
</code>

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

4. Filter Execution Order

Three kinds of filters exist:

Default filters (default-filters)

Route‑specific filters (filters)

Global Java filters (GlobalFilter)

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

5. Cross‑Origin (CORS) Issues

5.1 Concept

Cross‑origin occurs when the request origin (protocol, domain, or port) differs from the server’s. Browsers block such AJAX requests unless the server explicitly allows them.

5.2 Common Solution – CORS

Configure Spring Cloud Gateway to return appropriate CORS headers.

5.3 CORS Configuration via application.yml

<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>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
</code>

5.4 CORS Configuration via Java Bean

<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>@Configuration
public class CorsConfig {
    private static final String MAX_AGE = "18000L";
    @Bean
    public WebFilter corsFilter() {
        return (ServerWebExchange ctx, WebFilterChain chain) -> {
            ServerHttpRequest request = ctx.getRequest();
            if (!CorsUtils.isCorsRequest(request)) {
                return chain.filter(ctx);
            }
            HttpHeaders requestHeaders = request.getHeaders();
            ServerHttpResponse response = ctx.getResponse();
            HttpHeaders headers = response.getHeaders();
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
            headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());
            HttpMethod 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);
        };
    }
}
</code>

Both approaches ensure that browsers can successfully perform cross‑origin AJAX calls.

6. Additional Notes

The article also includes promotional sections and QR‑code images, which are not part of the technical content.

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.

api-gatewaySpring BootCORSSpring Cloud GatewayCustom Filter
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.