This is a series of articles, if you haven’t read the first one, please poke here:

  • Spring Cloud Gateway Service Gateway
  • Spring Cloud Gateway Service Gateway (2)

This article covers Gateway Gateway filters and global filters as well as custom filters.

  

The filter

  

Spring Cloud Gateway is divided into GatewayFilter and GlobalFilter according to scope. The differences are as follows:

  • GatewayFilter: Indicates the gateway filterspring.cloud.routes.filtersIn a specific route, the configuration applies only to the current route or passesspring.cloud.default-filtersThe configuration applies globally to all routes.
  • GlobalFilter: global filter, which does not need to be configured in the configuration file. It applies to all routes and finally passesGatewayFilterAdapterPackaged inGatewayFilterChainThe core filter that translates the URI of the request business and route to the address of the request for the real business service. It does not need to be loaded when the configuration system is initialized and acts on each route.

  

GatewayFilter GatewayFilter

  

Click the link to watch: Gateway filter video (for more please follow the public account “Mr. Hello Ward”)

  

The gateway filter is used to intercept and process Web requests in a chain manner, crosscutting application-independent requirements, such as security and access timeout Settings. Modifies the incoming HTTP request or outgoing HTTP response. The Spring Cloud Gateway contains a number of built-in Gateway filter factories 22 in all, including header filters, path-class filters, Hystrix filters, and filters for rewriting request urls, as well as other types of filters such as parameters and status codes. Filter factories can be classified into Header, Parameter, Path, Body, Status, Session, Redirect, Retry, RateLimiter, and Hystrix based on their purpose.

  

Next, we illustrate how to use some of them. The rest can be consulted when you need to use them in your work.

  

Path Path filter

  

Path The Path filter can rewrite urls. By rewriting urls, you can hide the actual Path, improve security, and make it easy for users to remember and type, and to be included in search engines. The implementation is as follows:

  

RewritePathGatewayFilterFactory

  

The RewritePath Gateway filter factory uses Java regular expressions to flexibly rewrite request paths using path regular expression arguments and replacement arguments.

spring:
  application:
    name: gateway-server # app name
  cloud:
    gateway:
      # Routing rules
      routes:
        - id: product-service           # route ID, unique
          uri: lb://product-service     # lb:// Get the service request address from the registry based on the service name
          predicates:                   # Assert (judgment condition)
            Append the matched request to the target URI
            - Path=/product/**, /api-gateway/**
          filters:                      # gateway filter
            /api-gateway/product/1 to /product/1
            - RewritePath=/api-gateway(? 
      
       /? . *),
       $\{segment}
Copy the code

  

Visit: http://localhost:9000/api-gateway/product/1 the results are as follows:

  

PrefixPathGatewayFilterFactory

  

The PrefixPath gateway filter factory adds the specified prefix to the matching URI.

spring:
  application:
    name: gateway-server # app name
  cloud:
    gateway:
      # Routing rules
      routes:
        - id: product-service           # route ID, unique
          uri: lb://product-service     # lb:// Get the service request address from the registry based on the service name
          predicates:                   # Assert (judgment condition)
            Append the matched request to the target URI
            - Path=/**
          filters:                       # gateway filter
            # rewrite /1 as /product/1
            - PrefixPath=/product
Copy the code

  

Visit: http://localhost:9000/1 The results are as follows:

  

StripPrefixGatewayFilterFactory

  

The StripPrefix gateway filter factory takes a parameter, StripPrefix, which represents the number of paths that are stripped from the request before it is sent downstream.

spring:
  application:
    name: gateway-server # app name
  cloud:
    gateway:
      # Routing rules
      routes:
        - id: product-service           # route ID, unique
          uri: lb://product-service     # lb:// Get the service request address from the registry based on the service name
          predicates:                   # Assert (judgment condition)
            Append the matched request to the target URI
            - Path=/**
          filters:                       # gateway filter
            / API /123/product/1
            - StripPrefix=2
Copy the code

  

Visit: http://localhost:9000/api/123/product/1 the results are as follows:

  

SetPathGatewayFilterFactory

  

SetPath Gateway filter factory takes the path template parameter. It provides a simple way to manipulate request paths by allowing templated path segments, using URI templates in the Spring Framework that allow multiple matching segments.

spring:
  application:
    name: gateway-server # app name
  cloud:
    gateway:
      # Routing rules
      routes:
        - id: product-service           # route ID, unique
          uri: lb://product-service     # lb:// Get the service request address from the registry based on the service name
          predicates:                   # Assert (judgment condition)
            Append the matched request to the target URI
            - Path=/api/product/{segment}
          filters:                       # gateway filter
            / API /product/1 to /product/1
            - SetPath=/product/{segment}
Copy the code

  

Visit: http://localhost:9000/api/product/1 the results are as follows:

  

Parameter Parameter filter

  

The AddRequestParameter gateway filter factory adds the specified parameters to the matching downstream request.

spring:
  application:
    name: gateway-server # app name
  cloud:
    gateway:
      # Routing rules
      routes:
        - id: product-service           # route ID, unique
          uri: lb://product-service     # lb:// Get the service request address from the registry based on the service name
          predicates:                   # Assert (judgment condition)
            Append the matched request to the target URI
            - Path=/api-gateway/**
          filters:                       # gateway filter
            /api-gateway/product/1 to /product/1
            - RewritePath=/api-gateway(? 
      
       /? . *),
       $\{segment}
            # add flag=1 to downstream request
            - AddRequestParameter=flag, 1
Copy the code

  

Modify the control layer code for goods and services.

package com.example.controller;

import com.example.pojo.Product;
import com.example.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/product")
public class ProductController {

    @Autowired
    private ProductService productService;

    /** * select * from primary key@param id
     * @return* /
    @GetMapping("/{id}")
    public Product selectProductById(@PathVariable("id") Integer id, String flag) {
        System.out.println("flag = " + flag);
        returnproductService.selectProductById(id); }}Copy the code

  

Visit: http://localhost:9000/api-gateway/product/1 console the results are as follows:

flag = 1
Copy the code

  

Status Status filter

  

The SetStatus gateway filter factory takes a single status parameter, which must be a valid Spring HttpStatus. It can be a string representation of the integer 404 or enumeration NOT_FOUND.

spring:
  application:
    name: gateway-server # app name
  cloud:
    gateway:
      # Routing rules
      routes:
        - id: product-service           # route ID, unique
          uri: lb://product-service     # lb:// Get the service request address from the registry based on the service name
          predicates:                   # Assert (judgment condition)
            Append the matched request to the target URI
            - Path=/api-gateway/**
          filters:                       # gateway filter
            /api-gateway/product/1 to /product/1
            - RewritePath=/api-gateway(? 
      
       /? . *),
       $\{segment}
            In any case, the HTTP status of the response will be set to 404
            - SetStatus=404 			 # 404 or the corresponding enumeration NOT_FOUND
Copy the code

  

Visit: http://localhost:9000/api-gateway/product/1 the results are as follows:

  

GlobalFilter GlobalFilter

  

The global filter does not need to be configured in the configuration file. It applies to all routes and is packaged into a filter identified by the GatewayFilterChain through the GatewayFilterAdapter. It is the core filter that requests the service and translates the URI of the route into the real service request address. It does not need to be loaded during system initialization and acts on each route.

  

Custom filter

  

Although Spring Cloud Gateway comes with many useful GatewayFilter Factory, GatewayFilter, and Global Filter, we still want to be able to customize our own filters to achieve some operations in many situations.

  

User-defined gateway filters

  

To customize a GatewayFilter, implement the following two interfaces: GatewayFilter, Ordered.

  

Creating a filter

  

CustomGatewayFilter. Java

package com.example.filter;

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/** * Custom gateway filter */
public class CustomGatewayFilter implements GatewayFilter.Ordered {

    /** * Filter business logic **@param exchange
     * @param chain
     * @return* /
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("Custom gateway filter executed");
        return chain.filter(exchange); // Continue down
    }

    /** * Filter execution order, the smaller the value, the higher the priority **@return* /
    @Override
    public int getOrder(a) {
        return 0; }}Copy the code

  

Registration filter

  

package com.example.config;

import com.example.filter.CustomGatewayFilter;
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;

/** * Gateway configuration class */
@Configuration
public class GatewayRoutesConfiguration {

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes().route(r -> r
                // assert (judgment condition)
                .path("/product/**")
                // The destination URI, the address to route to the microserver
                .uri("lb://product-service")
                // Register a custom gateway filter
                .filters(new CustomGatewayFilter())
                // Route ID, unique
                .id("product-service")) .build(); }}Copy the code

  

access

  

Note all gateway configured in the configuration file, restart and visit: http://localhost:9000/product/1 console results are as follows:

The custom gateway filter is executedCopy the code

  

Custom global filters

  

To customize global filters, implement the following two interfaces: GlobalFilter and Ordered. The global filter can be used to verify permissions and security.

  

Creating a filter

  

Implement the specified interface by adding the @Component annotation.

CustomGlobalFilter. Java

package com.example.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/** * Custom global filter */
@Component
public class CustomGlobalFilter implements GlobalFilter.Ordered {

    /** * Filter business logic **@param exchange
     * @param chain
     * @return* /
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("Custom global filter executed");
        return chain.filter(exchange); // Continue down
    }

    /** * Filter execution order, the smaller the value, the higher the priority **@return* /
    @Override
    public int getOrder(a) {
        return 0; }}Copy the code

  

access

  

Visit: http://localhost:9000/product/1 console the results are as follows:

Custom global filters are executedCopy the code

  

Unified authentication

  

Next, we judge whether the user logs in through token in the gateway filter to complete a unified authentication case.

  

Creating a filter

  

AccessFilter. Java

package com.example.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/** * Permission validation filter */
@Component
public class AccessFilter implements GlobalFilter.Ordered {

    private Logger logger = LoggerFactory.getLogger(AccessFilter.class);

    /** * Filter business logic **@param exchange
     * @param chain
     * @return* /
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // Get the request parameters
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        // Business logic processing
        if (null == token) {
            logger.warn("token is null...");
            ServerHttpResponse response = exchange.getResponse();
            // Response type
            response.getHeaders().add("Content-Type"."application/json; charset=utf-8");
            // Response status code, HTTP 401 error indicates that the user does not have access rights
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            // Response content
            String message = "{\"message\":\"" + HttpStatus.UNAUTHORIZED.getReasonPhrase() + "\"}";
            DataBuffer buffer = response.bufferFactory().wrap(message.getBytes());
            // The request is complete and no further requests are made
            return response.writeWith(Mono.just(buffer));
        }
        // Use token for authentication
        logger.info("token is OK!");
        return chain.filter(exchange);
    }

    /** * Filter execution order, the smaller the value, the higher the priority **@return* /
    @Override
    public int getOrder(a) {
        return 1; }}Copy the code

  

access

  

Visit: http://localhost:9000/product/1 the results are as follows:

  

Visit: http://localhost:9000/product/1? Token =abc123 Result:

In the next article, we will explain how Gateway implements traffic limiting, integrates Sentinel to implement traffic limiting, and constructs high availability Gateway environment

This article is licensed under a Creative Commons attribution – Noncommercial – No Deductive 4.0 International license.

You can see more articles about Spring Cloud in the category.

  

🤗 your likes and retweets are the biggest support for me.

📢 Scan code pay attention to Mr. Hallward “document + video” each article is equipped with a special video explanation, learning more easily oh ~