Spring Cloud Gateway practice 5: built in filter

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 practical combat series, it's time to understand the role of filters. In this article, let's learn about the built-in filters in Spring Cloud Gateway. They are so diverse and powerful

    AddRequestHeader

  • As the name suggests, the AddRequestHeader filter is to add the specified content to the request header
  • Complete configuration with predicate:
server:
  #Service port
  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
  • Full 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

  • As the name suggests, the AddRequestParameter filter is to add request parameters
  • The configuration is as follows. In the request received by the service provider, there will be one more parameter named foo and the value is bar config:
server:
  #Service port
  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
  • Full 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 adds parameters to the response header
  • The configuration is as follows. For the response received by the client, there will be one more parameter in its header, named foo, and the value is bar config response:
server:
  #Service port
  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
  • Full 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 header of the response returned by the service provider, if a key has multiple values (for example, access control allow origin in the cross domain scenario), the DedupeResponseHeader filter can remove duplicate values. There are three removal strategies: RETAIN_FIRST (keep the first, default), RETAIN_LAST, RETAIN_UNIQUE (weight removal)
  • The configuration is as follows. The de duplication of two header key s is specified. The policy is to keep the last one:
server:
  #Service port
  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 header of the response returned by the service provider, if a key has multiple values (for example, access control allow origin in the cross domain scenario), the DedupeResponseHeader filter can remove duplicate values. There are three removal strategies: RETAIN_FIRST (keep the first, default), RETAIN_LAST, RETAIN_UNIQUE (weight removal)
  • The configuration is as follows. The de duplication of two header key s is specified. The policy is to keep the last one:
server:
  #Service port
  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

  • Circuit breaker 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 an open circuit 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 that if there is < font color = "blue" > Blue < / font > in the request header, a key named < font color = "red" > x-request red < / font > will be added, and its value is the same as that of < font color = "blue" > Blue < / font >
  • The configuration is as follows. The de duplication of two header key s is specified. The policy is to keep the last one:
server:
  #Service port
  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 following figure, there is Blue in the request header:

  • Looking at the service provider's log, it shows that X-Request-Red is added to the header:

  • What happens if < font color = "blue" > x-request red < / font > already exists in the request header? As shown in the figure below, let's write < font color = "blue" > x-request red < / font > in the request header:

  • At the service provider's interruption point, you can find a magical scene. The corresponding values of all key s in the header are actually collections, but in most cases, there is only one element in the collection, and the new elements in MapRequestHeader will be put into this collection without affecting the original content:

PrefixPath

  • PrefixPath is well understood. It is to prefix the path when forwarding to the service provider
  • 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 PrefixPath=hello for the gateway, there is no need for < font color = "blue" > Hello < / font > in the request path when accessing the gateway. The configuration is as follows:
server:
  #Service port
  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 following figure, the request path does not need < font color = "blue" > Hello < / font >:

PreserveHostHeader

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

  • Add the PreserveHostHeader, as shown in the red box below, which is the real host information:

RequestRateLimiter

  • RequestRateLimiter is used for current limiting. It involves a lot of contents. Let's put it in a separate chapter for in-depth 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:
  #Service port
  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 the foo in the request header:
server:
  #Service port
  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 the foo in the response header:
server:
  #Service port
  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 deletes the specified parameter from the request parameters
  • The following configuration will delete foo in the request parameters:
server:
  #Service port
  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. It transforms 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:
  #Service port
  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 by the gateway to hello and become the correct request path:

RewriteLocationResponseHeader

  • RewriteLocationResponseHeader is used to overwrite the location information in the response
  • The configuration is as follows: stripVersionMode, locationHeaderName, hostValue and 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 >, which will eventually be rewritten by the following filter as < font color = "blue" > api.example.com/some/object/id < / font >
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 does not match, the name filter does nothing

RewriteResponseHeader

  • RewriteResponseHeader is easy to understand: modify the response header. There are three parameters: the key of the header, the regular expression matching value, and the result of modifying 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:
  #Service port
  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 many security related contents to the response header. The configuration is as follows:
server:
  #Service port
  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. You can see that a lot of information has been added to the header:

  • If you don't want to return some contents in the figure above, you can close them in the configuration file, as shown in the red box in the figure below. X-frame options and strict transport security are set not to return:

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

SetPath

  • SetPath is used with predictions. 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 predictions and then used in filters:
server:
  #Service port
  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

  • As the name suggests, SetRequestHeader is to rewrite the request header, change the specified key to the specified value, and create it if the key does not exist:
server:
  #Service port
  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 cooperate with predictions. The variables defined in predictions 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:
  #Service port
  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

  • As the name suggests, SetResponseHeader is to rewrite the response header, change the specified key to the specified value, and create it if the key does not exist:
server:
  #Service port
  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, and the following settings will return 500:
server:
  #Service port
  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 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 modify the return code with SetStatus without losing the real return code, you can add the following configuration, so that the real return code will be placed in the key named < font color = "blue" > original status header name < / font >:
server:
  #Service port
  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 common filter. For example, if the request is < font color = "blue" > / AAA / BBB / hello / str < / font >, if we want to convert it to < font color = "blue" > / hello / str < / font >, we can use < font color = "blue" > StripPrefix = 2 < / font >, and the first two levels of path s have been deleted:
server:
  #Service port
  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 suggests, Retry means Retry. The following parameters are required:
  1. Retries: number of retries
  2. statuses: retry only after encountering the return status. Refer to org.springframework.http.HttpStatus for values
  3. Methods: those types of methods will only be retried (GET, POST, etc.), value reference: org.springframework.http.HttpMethod
  4. Series: try again only after encountering the series value. Refer to org.springframework.http.HttpStatus.Series for the value
  5. Exceptions: what exceptions are encountered before retrying
  6. backoff: retry policy, consisting 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 commonly used: to control the request size, you can use < font color = "blue" > KB < / font > or < font color = "blue" > MB < / font > and other units. If it exceeds this size, a 413 error (Payload Too Large) will be returned,
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:
  #Service port
  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
  • In the code of the service provider, break the point, 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. It is officially recommended to configure it with code, as shown below. The request body was originally a string, but the result was changed to an instance of 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. It is officially recommended 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 third-party authentication is used, such as OAuth2, the third-party token can be forwarded to the service provider with tokenray:
spring:
  cloud:
    gateway:
      routes:
      - id: resource
        uri: http://localhost:9000
        predicates:
        - Path=/resource
        filters:
        - TokenRelay=
  • Remember to add jar package dependency < font color = "blue" > org.springframework.boot: spring-boot-starter-oauth2-client < / font >

Set global filter

  • In the previous example, all filters are placed in the routing policy and used together with predictions. If you want to configure a globally effective filter, you can make the following settings in the configuration file. The following configuration means that AddResponseHeader and PrefixPath will process all requests, which has nothing to do with the routing settings:
spring:
  cloud:
    gateway:
      default-filters:
      - AddResponseHeader=X-Response-Default-Red, Default-Blue
      - PrefixPath=/httpbin
  • So far, we have understood most of the built-in filters, and several slightly complex ones are left for further study in the following chapters

You're not alone. Xinchen's original accompanies you all the way

  1. Java series
  2. Spring collection
  3. Docker series
  4. kubernetes series
  5. Database + middleware series
  6. DevOps series

Welcome to the official account: programmer Xin Chen

Wechat search "programmer Xinchen", I'm Xinchen, looking forward to traveling with you in the Java World
https://github.com/zq2599/blog_demos

Tags: cloud computing

Posted on Mon, 22 Nov 2021 02:46:42 -0500 by nitediver