Welcome to my GitHub

https://github.com/zq2599/blog_demos

Content: Classification and summary of all original articles and supporting source code, involving Java, Docker, Kubernetes, DevOPS, etc.;

Overview of this article

  • As the fifth article in the "Spring Cloud Gateway Actual Combat" series, it’s time to understand the role of filters. In this article, let’s learn about the built-in filters of Spring Cloud Gateway. They are so versatile and powerful.

    AddRequestHeader

  • The AddRequestHeader filter, as the name implies, is to add the specified content to the request header
  • Complete configuration with predicate:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/hello/**
          filters:
            - AddRequestHeader=x-request-foo, bar-config
  • Complete dynamic configuration with predicate:
[
    {
        "id": "path_route_addr",
        "uri": "http://127.0.0.1:8082",
        "predicates": [
            {
                "name": "Path",
                "args": {
                    "pattern": "/hello/**"
                }
            }
        ],
        "filters": [
            {
                "name": "AddRequestHeader",
                "args": {
                    "name": "x-request-foo",
                    "value": "bar-dynamic"
                }
            }
        ]
    }
]
  • actual effect:

在这里插入图片描述

AddRequestParameter

  • The AddRequestParameter filter, as the name implies, is to add request parameters
  • The configuration is as follows, there will be an additional parameter in the request received by the service provider, named foo and value bar-config:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/hello/**
          filters:
            - AddRequestParameter=foo, bar-config
  • Complete dynamic configuration with predicate:
[
    {
        "id": "path_route_addr",
        "uri": "http://127.0.0.1:8082",
        "predicates": [
            {
                "name": "Path",
                "args": {
                    "pattern": "/hello/**"
                }
            }
        ],
        "filters": [
            {
                "name": "AddRequestParameter",
                "args": {
                    "name": "foo",
                    "value": "bar-dynamic"
                }
            }
        ]
    }
]
  • actual effect:

在这里插入图片描述

AddResponseHeader

  • The AddResponseHeader filter is to add parameters to the response header
  • The configuration is as follows, the response received by the client will have an additional parameter in the header, named foo, and value bar-config-response:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/hello/**
          filters:
          - AddResponseHeader=foo, bar-config-response
  • Complete dynamic configuration with predicate:
[
    {
        "id": "path_route_addr",
        "uri": "http://127.0.0.1:8082",
        "predicates": [
            {
                "name": "Path",
                "args": {
                    "pattern": "/hello/**"
                }
            }
        ],
        "filters": [
            {
                "name": "AddResponseHeader",
                "args": {
                    "name": "foo",
                    "value": "bar-dynamic-response"
                }
            }
        ]
    }
]
  • actual effect:

在这里插入图片描述

DedupeResponseHeader

  • In the response header returned by the service provider, if a key has multiple values (for example, Access-Control-Allow-Origin in a cross-domain scenario), the DedupeResponseHeader filter can eliminate duplicate values. There are three elimination strategies. :RETAIN_FIRST (keep the first one, default), RETAIN_LAST (keep the last one), RETAIN_UNIQUE (de-duplicate)
  • The configuration is as follows, the deduplication of the two header keys is specified, and the strategy is to keep the last one:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/hello/**
          filters:
          - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_LAST

DedupeResponseHeader

  • In the response header returned by the service provider, if a key has multiple values (for example, Access-Control-Allow-Origin in a cross-domain scenario), the DedupeResponseHeader filter can eliminate duplicate values. There are three elimination strategies. :RETAIN_FIRST (keep the first one, default), RETAIN_LAST (keep the last one), RETAIN_UNIQUE (de-duplicate)
  • The configuration is as follows, the deduplication of the two header keys is specified, and the strategy is to keep the last one:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/hello/**
          filters:
          - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_LAST

CircuitBreaker

  • CircuitBreaker is a circuit breaker. Let’s experience this powerful function in a separate article.

FallbackHeaders

  • FallbackHeaders are generally used in conjunction with CircuitBreaker. Look at the following configuration. After a circuit break occurs, the request will be forwarded to FallbackHeaders for processing. At this time, FallbackHeaders will add exception information to the key specified in the header:
spring:
  cloud:
    gateway:
      routes:
      - id: ingredients
        uri: lb://ingredients
        predicates:
        - Path=//ingredients/**
        filters:
        - name: CircuitBreaker
          args:
            name: fetchIngredients
            fallbackUri: forward:/fallback
      - id: ingredients-fallback
        uri: http://localhost:9994
        predicates:
        - Path=/fallback
        filters:
        - name: FallbackHeaders
          args:
            executionExceptionTypeHeaderName: Test-Header

MapRequestHeader

  • MapRequestHeader is used to copy key-value pairs in the header. The following configuration means: if there is <font color="blue">Blue</font> in the request header, add the name <font color="red">X- The key of Request-Red</font> has the same value as the value of <font color="blue">Blue</font>
  • The configuration is as follows, the deduplication of the two header keys is specified, and the strategy is to keep the last one:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/hello/**
          filters:
          - MapRequestHeader=Blue, X-Request-Red
  • As shown in the figure below, there is Blue in the request header:

在这里插入图片描述

  • Looking at the service provider's log again, it shows that there is more X-Request-Red in the header:

在这里插入图片描述

  • What happens if <font color="blue">X-Request-Red</font> already exists in the requested header? As shown in the figure below, we write <font color="blue">X-Request-Red</font> in the request header:

在这里插入图片描述

  • At the interruption point of the service provider, you can find a magical scene. All the keys in the header and the corresponding values are actually collections, but in most cases there is only one element in the collection, and the new elements of MapRequestHeader will be put into this Collection, will not affect the original content:

在这里插入图片描述

PrefixPath

  • PrefixPath is well understood, that is, when forwarding to the service provider, prefix the path
  • For example, the original address of my service provider is <font color="blue"> http://127.0.0.1:8082/hello/str </font> The configuration is as follows, if I configure the gateway with PrefixPath=hello, then When accessing the gateway, <font color="blue">hello</font> is not needed in the request path, and the configuration is as follows:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/str
          filters:
          - PrefixPath=/hello
  • As shown in the figure below, the request path does not need to be <font color="blue">hello</font>:

在这里插入图片描述

PreserveHostHeader

  • When PreserveHostHeader forwards the request to the service provider, it will retain the host information (otherwise it can only be determined by the HTTP client)
  • First look at the effect of using PreserveHostHeader. As shown in the figure below, the host in the request header received by the service provider is the information configured by the gateway:

在这里插入图片描述

  • Try adding PreserveHostHeader, the red box in the following figure is the real host information:

在这里插入图片描述

RequestRateLimiter

  • RequestRateLimiter is used for current limiting and involves more content, so let’s put it in a separate chapter for further study.

RedirectTo

  • The function of RedirectTo is simple and straightforward: Jump to the specified location. In the following configuration, the uri field is obviously an invalid address, but the request will still be forwarded to the specified location by RedirectTo:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.1.1.1:11111
          predicates:
          - Path=/hello/**
          filters:
          - RedirectTo=302, http://127.0.0.1:8082/hello/str

RemoveRequestHeader

  • RemoveRequestHeader is well understood, delete the specified value in the request header
  • The following configuration will delete foo in the request header:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/hello/**
          filters:
          - RemoveRequestHeader=foo

RemoveResponseHeader

  • RemoveResponseHeader deletes the specified value in the response header
  • The following configuration will delete foo in the response header:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/hello/**
          filters:
          - RemoveResponseHeader=foo

RemoveRequestParameter

  • RemoveRequestParameter delete the specified parameter in the request parameter
  • The following configuration will delete foo in the request parameters:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/hello/**
          filters:
          - RemoveRequestParameter=foo1

RewritePath

  • RewritePath is very practical, changing the path in the request parameters
  • The following configuration will convert <font color="blue">/test/str</font> to <font color="blue">/hello/str</font>:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/test/**
          filters:
          - RewritePath=/test/?(?<segment>.*), /hello/$\{segment}
  • The request is as follows, it can be seen that the test in the path will be modified to hello by the gateway, which becomes the correct request path:

在这里插入图片描述

RewriteLocationResponseHeader

  • RewriteLocationResponseHeader is used to rewrite the location information in the response
  • The configuration is as follows, there are four parameters in total: stripVersionMode, locationHeaderName, hostValue, protocolsRegex
  • For example, the request is <font color="blue">api.example.com/some/object/name</font>, and the location of the response is <font color="blue">object-service.prod.example.net/v2 /some/object/id</font>, will eventually be rewritten as <font color="blue">api.example.com/some/object/id</font> by the filter below
spring:
  cloud:
    gateway:
      routes:
      - id: rewritelocationresponseheader_route
        uri: http://example.org
        filters:
        - RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,
  • There are three strategies for stripVersionMode:

NEVER_STRIP: Do not execute
AS_IN_REQUEST: The original request is executed without vesion
ALWAYS_STRIP: fixed execution

  • Location is used to replace the host:port part, if not, use the host in the Request
  • protocolsRegex is used to match the protocol. If it fails to match, the name filter will do nothing.

RewriteResponseHeader

  • RewriteResponseHeader is well understood: modify the response header, there are three parameters: the key of the header, the regular expression that matches the value, and the result of modifying the value
  • The following configuration means to modify the value of the key <font color="blue">X-Response-Red</font> in the response header, find the content of password=xxx, and change it to password= *
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/test/**
          filters:
          - RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***

SecureHeaders

  • SecureHeaders will add a lot of security-related content to the response header, the configuration is as follows:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
          - Path=/hello/**
          filters:
          - SecureHeaders
  • The response is as follows, it can be seen that a lot of information has been added to the header:

在这里插入图片描述

  • If you don’t want to return some of the content in the above picture, you can close it in the configuration file.

在这里插入图片描述

  • Try again and get the following response. It can be seen that neither x-frame-options nor strict-transport-security returned:

在这里插入图片描述

SetPath

  • SetPath is used with predicates, the following configuration will change the request <font color="blue">/test/str</font> to <font color="blue">/hello/str</font>, it can be seen that this segment is Assigned in predicates, and then used in filters:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      filter:
        secure-headers:
          disable:
            - x-frame-options
            - strict-transport-security
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/test/{segment}
          filters:
            - SetPath=/hello/{segment}

SetRequestHeader

  • SetRequestHeader, as the name implies, is to rewrite the request header, change the specified key to the specified value, and create it if the key does not exist:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      filter:
        secure-headers:
          disable:
            - x-frame-options
            - strict-transport-security
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/hello/**
          filters:
            - SetRequestHeader=X-Request-Red, Blue
  • Similar to SetPath, SetRequestHeader can also work with predicates. Variables defined in predicates can be used in SetRequestHeader. As shown below, when the request is /hello/str, the value of X-Request-Red in the header is <font color ="blue">Blue-str</font>:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      filter:
        secure-headers:
          disable:
            - x-frame-options
            - strict-transport-security
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/hello/{segment}
          filters:
            - SetRequestHeader=X-Request-Red, Blue-{segment}

SetResponseHeader

  • SetResponseHeader, as the name implies, is to rewrite the response header, change the specified key to the specified value, and create it if the key does not exist:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      filter:
        secure-headers:
          disable:
            - x-frame-options
            - strict-transport-security
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/hello/**
          filters:
            - SetResponseHeader=X-Request-Red, Blue

SetStatus

  • SetStatus is easy to understand: control returns code, the following settings will return 500:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/hello/**
          filters:
            - SetStatus=500
  • The test effect is as shown in the figure below. The content of the service provider will be returned normally, but the return code has been changed to 500:

在这里插入图片描述

  • If you want to use SetStatus to modify the return code without losing the real return code, you can add the following configuration so that the real return code is named <font color="blue">original-status-header-name< /font>'s key:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      set-status:
        original-status-header-name: aaabbbccc
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/hello/**
          filters:
            - SetStatus=500

StripPrefix

  • StripPrefix is a very commonly used filter. For example, the request is <font color="blue">/aaa/bbb/hello/str</font>, we need to convert it to <font color="blue">/hello/str </font>, just use <font color="blue">StripPrefix=2</font>, the first two levels of path have been deleted:
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      set-status:
        original-status-header-name: aaabbbccc
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/aaa/**
          filters:
            - StripPrefix=2
  • As shown in the figure below, the response is normal:

在这里插入图片描述

Retry

  • As the name implies, Retry is a retry, and the following parameters are required:
  1. retries: number of retries
  2. statuses: What kind of return status is encountered before retrying, value reference: org.springframework.http.HttpStatus
  3. methods: Those types of methods will be retried (GET, POST, etc.), for value reference: org.springframework.http.HttpMethod
  4. series: What kind of series value is encountered before retrying, value reference: org.springframework.http.HttpStatus.Series
  5. exceptions: What kind of exceptions are encountered before retrying
  6. backoff: Retry strategy, composed of multiple parameters, such as firstBackoff
  • The reference configuration is as follows:
spring:
  cloud:
    gateway:
      routes:
      - id: retry_test
        uri: http://localhost:8080/flakey
        predicates:
        - Host=*.retry.com
        filters:
        - name: Retry
          args:
            retries: 3
            statuses: BAD_GATEWAY
            methods: GET,POST
            backoff:
              firstBackoff: 10ms
              maxBackoff: 50ms
              factor: 2
              basedOnPreviousValue: false

RequestSize

  • RequestSize is also very commonly used: to control the size of the request, you can use units such as <font color="blue">KB</font> or <font color="blue">MB</font>. If it exceeds this size, it will return a 413 error ( Payload Too Large),
spring:
  cloud:
    gateway:
      routes:
      - id: request_size_route
        uri: http://localhost:8080/upload
        predicates:
        - Path=/upload
        filters:
        - name: RequestSize
          args:
            maxSize: 5000000
  • Note that if RequestSize is not set, the default upper limit of Spring Cloud Gateway is <font color="red"> 5MB </font>

SetRequestHostHeader

  • SetRequestHostHeader will modify the host value in the request header
  • The following configuration will change the host in the request header to <font color="blue">aaabbb</font>
server:
  #服务端口
  port: 8081
spring:
  application:
    name: hello-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/hello/**
          filters:
        - name: SetRequestHostHeader
        args:
          host: aaabbb
  • At the break point in the code of the service provider, as shown in the figure below, it can be seen that the host has been changed to <font color="blue">aaabbb</font>

在这里插入图片描述

ModifyRequestBody

  • ModifyRequestBody is used to modify the body content of the request. The official recommendation here is to configure it with code. As shown below, the request body was originally a string, but the result was changed to an instance of the Hello object:

    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
      return builder.routes()
          .route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")
              .filters(f -> f.prefixPath("/httpbin")
                  .modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
                      (exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri))
          .build();
    }
    
    static class Hello {
      String message;
    
      public Hello() { }
    
      public Hello(String message) {
          this.message = message;
      }
    
      public String getMessage() {
          return message;
      }
    
      public void setMessage(String message) {
          this.message = message;
      }
    }

ModifyResponseBody

  • ModifyResponseBody is similar to the previous ModifyRequestBody. The official recommendation is to implement it in code. The following code is used to change the content of the response body to all uppercase:
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
            .filters(f -> f.prefixPath("/httpbin")
                .modifyResponseBody(String.class, String.class,
                    (exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri))
        .build();
}

TokenRelay

  • When using third-party authentication, such as OAuth2, use TokenRelay to forward the third-party token to the service provider:
spring:
  cloud:
    gateway:
      routes:
      - id: resource
        uri: http://localhost:9000
        predicates:
        - Path=/resource
        filters:
        - TokenRelay=
  • Remember to add the jar package dependency<font color="blue">org.springframework.boot:spring-boot-starter-oauth2-client</font>

Set up a global filter

  • In the previous example, all filters are placed in the routing strategy and used with predicates. If you want to configure a globally effective filter, you can set the following settings in the configuration file. The following configuration means that AddResponseHeader and PrefixPath will process all requests. It has nothing to do with routing settings:
spring:
  cloud:
    gateway:
      default-filters:
      - AddResponseHeader=X-Response-Default-Red, Default-Blue
      - PrefixPath=/httpbin
  • At this point, we have already understood most of the built-in filters, and there are a few slightly more complicated ones that are left for in-depth study in later chapters.

You are not alone, Xinchen and original are with you all the way

  1. Java series
  2. Spring series
  3. Docker series
  4. kubernetes series
  5. Database + Middleware Series
  6. DevOps series

Welcome to pay attention to the public account: programmer Xin Chen

Search "Programmer Xin Chen" on WeChat, I am Xin Chen, and I look forward to traveling the Java world with you...
https://github.com/zq2599/blog_demos

程序员欣宸
147 声望24 粉丝

热爱Java和Docker