7. Global Filters

The GlobalFilter interface has the same signature as GatewayFilter. These are special filters that are conditionally applied to all routes. (This interface and usage are subject to change in future milestones).

7.1 Combined Global Filter and GatewayFilter Ordering

When a request comes in (and matches a Route) the Filtering Web Handler will add all instances of GlobalFilter and all route specific instances of GatewayFilter to a filter chain. This combined filter chain is sorted by the org.springframework.core.Ordered interface, which can be set by implementing the getOrder() method.

As Spring Cloud Gateway distinguishes between "pre" and "post" phases for filter logic execution (see: How it Works), the filter with the highest precedence will be the first in the "pre"-phase and the last in the "post"-phase.

ExampleConfiguration.java. 

@Bean
public GlobalFilter customFilter() {
    return new CustomGlobalFilter();
}

public class CustomGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("custom global filter");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

7.2 Forward Routing Filter

The ForwardRoutingFilter looks for a URI in the exchange attribute ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR. If the url has a forward scheme (ie forward:///localendpoint), it will use the Spring DispatcherHandler to handler the request. The path part of the request URL will be overridden with the path in the forward URL. The unmodified original url is appended to the list in the ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR attribute.

7.3 LoadBalancerClient Filter

The LoadBalancerClientFilter looks for a URI in the exchange attribute ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR. If the url has a lb scheme (ie lb://myservice), it will use the Spring Cloud LoadBalancerClient to resolve the name (myservice in the previous example) to an actual host and port and replace the URI in the same attribute. The unmodified original url is appended to the list in the ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR attribute. The filter will also look in the ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR attribute to see if it equals lb and then the same rules apply.

application.yml. 

spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**

[Note]Note

By default when a service instance cannot be found in the LoadBalancer a 503 will be returned. You can configure the Gateway to return a 404 by setting spring.cloud.gateway.loadbalancer.use404=true.

[Note]Note

The isSecure value of the ServiceInstance returned from the LoadBalancer will override the scheme specified in the request made to the Gateway. For example, if the request comes into the Gateway over HTTPS but the ServiceInstance indicates it is not secure, then the downstream request will be made over HTTP. The opposite situation can also apply. However if GATEWAY_SCHEME_PREFIX_ATTR is specified for the route in the Gateway configuration, the prefix will be stripped and the resulting scheme from the route URL will override the ServiceInstance configuration.

[Warning]Warning

LoadBalancerClientFilter uses a blocking Ribbon LoadBalancerClient under the hood. We suggest you use ReactiveLoadBalancerClientFilter instead. You can switch to using it by adding org.springframework.cloud:spring-cloud-loadbalancer dependency to your project and setting the value of the spring.cloud.loadbalancer.ribbon.enabled to false.

7.4 ReactiveLoadBalancerClientFilter

The ReactiveLoadBalancerClientFilter looks for a URI in the exchange attribute ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR. If the url has a lb scheme (ie lb://myservice), it will use the Spring Cloud ReactorLoadBalancer to resolve the name (myservice in the previous example) to an actual host and port and replace the URI in the same attribute. The unmodified original url is appended to the list in the ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR attribute. The filter will also look in the ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR attribute to see if it equals lb and then the same rules apply.

application.yml. 

spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**

[Note]Note

By default when a service instance cannot be found by the ReactorLoadBalancer, a 503 will be returned. You can configure the Gateway to return a 404 by setting spring.cloud.gateway.loadbalancer.use404=true.

[Note]Note

The isSecure value of the ServiceInstance returned from the ReactiveLoadBalancerClientFilter will override the scheme specified in the request made to the Gateway. For example, if the request comes into the Gateway over HTTPS but the ServiceInstance indicates it is not secure, then the downstream request will be made over HTTP. The opposite situation can also apply. However if GATEWAY_SCHEME_PREFIX_ATTR is specified for the route in the Gateway configuration, the prefix will be stripped and the resulting scheme from the route URL will override the ServiceInstance configuration.

7.5 Netty Routing Filter

The Netty Routing Filter runs if the url located in the ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange attribute has a http or https scheme. It uses the Netty HttpClient to make the downstream proxy request. The response is put in the ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange attribute for use in a later filter. (There is an experimental WebClientHttpRoutingFilter that performs the same function, but does not require netty)

7.6 Netty Write Response Filter

The NettyWriteResponseFilter runs if there is a Netty HttpClientResponse in the ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange attribute. It is run after all other filters have completed and writes the proxy response back to the gateway client response. (There is an experimental WebClientWriteResponseFilter that performs the same function, but does not require netty)

7.7 RouteToRequestUrl Filter

The RouteToRequestUrlFilter runs if there is a Route object in the ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR exchange attribute. It creates a new URI, based off of the request URI, but updated with the URI attribute of the Route object. The new URI is placed in the ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange attribute.

If the URI has a scheme prefix, such as lb:ws://serviceid, the lb scheme is stripped from the URI and placed in the ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR for use later in the filter chain.

7.8 Websocket Routing Filter

The Websocket Routing Filter runs if the url located in the ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange attribute has a ws or wss scheme. It uses the Spring Web Socket infrastructure to forward the Websocket request downstream.

Websockets may be load-balanced by prefixing the URI with lb, such as lb:ws://serviceid.

[Note]Note

If you are using SockJS as a fallback over normal http, you should configure a normal HTTP route as well as the Websocket Route.

application.yml. 

spring:
  cloud:
    gateway:
      routes:
      # SockJS route
      - id: websocket_sockjs_route
        uri: http://localhost:3001
        predicates:
        - Path=/websocket/info/**
      # Normal Websocket route
      - id: websocket_route
        uri: ws://localhost:3001
        predicates:
        - Path=/websocket/**

7.9 Gateway Metrics Filter

To enable Gateway Metrics add spring-boot-starter-actuator as a project dependency. Then, by default, the Gateway Metrics Filter runs as long as the property spring.cloud.gateway.metrics.enabled is not set to false. This filter adds a timer metric named "gateway.requests" with the following tags:

  • routeId: The route id
  • routeUri: The URI that the API will be routed to
  • outcome: Outcome as classified by HttpStatus.Series
  • status: Http Status of the request returned to the client
  • httpStatusCode: Http Status of the request returned to the client
  • httpMethod: The Http method used for the request

These metrics are then available to be scraped from /actuator/metrics/gateway.requests and can be easily integrated with Prometheus to create a Grafana dashboard.

[Note]Note

To enable the prometheus endpoint add micrometer-registry-prometheus as a project dependency.

7.10 Marking An Exchange As Routed

After the Gateway has routed a ServerWebExchange it will mark that exchange as "routed" by adding gatewayAlreadyRouted to the exchange attributes. Once a request has been marked as routed, other routing filters will not route the request again, essentially skipping the filter. There are convenience methods that you can use to mark an exchange as routed or check if an exchange has already been routed.

  • ServerWebExchangeUtils.isAlreadyRouted takes a ServerWebExchange object and checks if it has been "routed"
  • ServerWebExchangeUtils.setAlreadyRouted takes a ServerWebExchange object and marks it as "routed"