Home

Service Gateway

Li

Li Wei

December 27, 20257 min read

Service Gateway

Overview

As Gu Ming Siyi says, a gateway is the gateway of a network. When data is transmitted between networks, it must pass through a gateway for routing, forwarding, and security verification.

Frontend requests cannot directly access microservices; they must go through the gateway:

  • The gateway can enforce security controls, i.e., login identity verification, and only allow traffic after successful validation.
  • After authentication, the gateway determines which microservice should handle the request and forwards it accordingly.

Gateway

Basic Introduction

Spring Cloud Gateway is a brand‑new project of Spring Cloud. Built on Spring 5.0, Spring Boot 2.0, Project Reactor and other reactive programming and event‑stream technologies, it provides a simple, effective, unified API routing management solution for microservice architectures.

Official site: https://spring.io/projects/spring-cloud-gateway#learn

Basic Usage

Since the gateway itself is an independent microservice, you need to create a module for it. The general steps are:

  • Create the gateway microservice
  • Add the SpringCloudGateway and NacosDiscovery dependencies
    • Write the main class
    • Configure gateway routes; the application.yaml looks like this:
    • Route filters (excerpt):

The routes element has the following type:

It is a collection, meaning you can define many routing rules. Each RouteDefinition in the collection is a concrete routing rule definition, with common attributes such as:

The four attributes mean:

  • id: unique identifier of the route
  • predicates: route predicate, i.e., the matching condition
  • filters: route filter conditions, description of the filter part
  • uri: route target address; lb:// denotes load balancing, which obtains the list of target microservice instances from the service registry and selects one via load balancing

Here we focus on predicates, the route predicate. Spring Cloud Gateway supports many predicate types:

Name Description Example
After Requests after a specific time point After=2037-01-20T17:42:47.789-07:00[America/Denver]
Before Requests before a specific time point Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
Between Requests between two time points Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie Request must contain certain cookies Cookie=chocolate, ch.p
Header Request must contain certain headers Header=X-Request-Id, \d+
Host Request must target a specific host (domain) Host=**.somehost.org,**.anotherhost.org
Method Request method must be one of the listed methods Method=GET,POST
Path Request path must match the given pattern Path=/red/{segment},/blue/**
Query Request must include specified query parameters Query=name, Jack or Query=name
RemoteAddr Requester's IP must be within the specified range RemoteAddr=192.168.1.1/24
weight Weight handling

Login Verification

In a monolithic architecture, a single login and identity check suffices for all business logic. After splitting into microservices, each service is deployed independently and no longer shares data, meaning each microservice would need to perform login verification—clearly undesirable.

Authentication Idea

Login is usually implemented with JWT. Verifying JWTs is complex and requires secret keys. If every microservice validates JWTs, two major problems arise:

  • Each service must know the JWT secret key, which is insecure.
  • Each service repeats login‑verification and permission‑check code, causing unnecessary duplication.

Since the gateway is the entry point for all microservices, every request passes through it first. We can move login verification to the gateway, solving the above issues:

  • The secret key only needs to be stored in the gateway and the user service.
  • Only the gateway implements the login‑verification logic.

The login‑verification flow is shown below:

![Login flow diagram]

However, several questions remain:

  • The gateway routes are configured, and request forwarding is handled by internal Gateway code. How can we perform login verification before forwarding?
  • After the gateway validates the JWT, how do we pass user information to the downstream microservice?
  • Microservices also call each other directly, bypassing the gateway—how should user information be propagated in that case?

These questions will be addressed in the following sections.

Gateway Filters

Login verification must occur before the request is forwarded to a microservice; otherwise it defeats the purpose. Because request forwarding is implemented inside the Gateway, we need to understand the basic workings of the Gateway to insert verification logic beforehand.

As illustrated:

  • After a client request reaches the gateway, HandlerMapping evaluates it, finds the matching Route rule, and hands the request to WebHandler for processing.
  • WebHandler loads the filter chain (Filter chain) associated with the matched route and executes each filter in order.
  • In the diagram, filters are split by a dashed line into left and right parts because each filter’s internal logic consists of two phases: pre and post, which run before and after the request is routed to the microservice, respectively.
  • Only after all filters’ pre logic execute successfully does the request get routed to the microservice.
  • Once the microservice returns a response, the filters’ post logic run in reverse order.
  • Finally, the response is sent back to the client.

The final request forwarding is performed by a filter named NettyRoutingFilter, which is the last filter in the chain. If we can define a filter that implements login verification and place it before **NettyRoutingFilter**, our requirement is satisfied. How do we implement such a gateway filter?

There are two kinds of filters in the gateway filter chain:

  • **GatewayFilter**: Route filter, whose scope is flexible and can be attached to any specific Route.
  • **GlobalFilter**: Global filter, which applies to all routes and cannot be configured per route.

Note: Outside the filter chain there is another kind of filter, HttpHeadersFilter, used to manipulate request headers sent downstream. For example, org.springframework.cloud.gateway.filter.headers.XForwardedHeadersFilter can forward the original Host header to the downstream service.

Both GatewayFilter and GlobalFilter have identical method signatures:

FilteringWebHandler decorates GlobalFilter as GatewayFilter during request handling, then places it into the same filter chain where it is ordered and executed sequentially.

Gateway provides many built‑in GatewayFilters; see the official docs for details:

Official site:

Gateway The built‑in GatewayFilter filter is extremely easy to use—no coding required, just a simple YAML configuration. Its scope is also flexible: wherever you place it under Route, it applies to the corresponding Route.

For example, there is a filter called AddRequestHeaderGatewayFilterFacotry, which simply adds a request header and passes it to downstream microservices.

To use it, add the following to application.yaml:

If you want the filter to apply to all routes, configure it like this:


Custom Filters

Both GatewayFilter and GlobalFilter support custom implementations, though the coding approach and usage differ slightly.

Custom GatewayFilter
Creating a custom GatewayFilter does not involve directly implementing GatewayFilter; instead you implement AbstractGatewayFilterFactory. The simplest way looks like this:

Note: The class name must end with GatewayFilterFactory!

Then reference it in the YAML configuration:

## example snippet

This type of filter can also accept dynamic parameters, though the implementation is more complex. Example:

## example snippet

When using this configuration, parameters must be supplied in the exact order defined by the method shortcutFieldOrder().

Alternatively, you can specify parameter names manually, avoiding the strict order:

## example snippet

Custom GlobalFilter
Creating a custom GlobalFilter is much simpler: just implement GlobalFilter. Dynamic parameters are not supported:

// example snippet

Originally written by Li Wei (李唯_) and published in Chinese on 后端技术栈全书 (Full-Stack Backend Engineering). Translated and adapted for DriftSeas with permission.

Keep reading

More related articles from DriftSeas.