• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #19717

06 Mar 2025 06:32PM UTC coverage: 88.525% (+0.03%) from 88.494%
#19717

push

github

web-flow
xds: Support filter state retention

This PR adds support filter state retention in Java. The mechanism
will be similar to the one described in [A83]
(https://github.com/grpc/proposal/blob/master/A83-xds-gcp-authn-filter.md#filter-call-credentials-cache)
for C-core, and will serve the same purpose. However, the
implementation details are very different due to the different nature
of xDS HTTP filter support in C-core and Java.

### Filter instance lifecycle
#### xDS gRPC clients
New filter instances are created per combination of:
1. `XdsNameResolver` instance,
2. Filter name+typeUrl as configured in 
   HttpConnectionManager (HCM) http_filters.

Existing client-side filter instances are shutdown:
- A single a filter instance is shutdown when an LDS update contains
  HCM that is missing filter configuration for name+typeUrl
  combination of this instance.
- All filter instances when watched LDS resource is missing from an
  LDS update.
- All filter instances name resolver shutdown.

#### xDS-enabled gRPC servers
New filter instances are created per combination of:
1. Server instance,
2. FilterChain name,
3. Filter name+typeUrl as configured in FilterChain's HCM.http_filters

Filter instances of Default Filter Chain is tracked separately per:
1. Server instance,
2. Filter name+typeUrl in default_filter_chain's HCM.http_filters.

Existing server-side filter instances are shutdown:
- A single a filter instance is shutdown when an LDS update contains
  FilterChain with HCM.http_filters that is missing configuration for
  filter name+typeUrl.
- All filter instances associated with the FilterChain when an LDS
  update no longer contains FilterChain's name.
- All filter instances when watched LDS resource is missing from an
  LDS update.
- All filter instances on server shutdown.

### Related
- Part 1: #11883

34577 of 39059 relevant lines covered (88.53%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.91
/../xds/src/main/java/io/grpc/xds/Filter.java
1
/*
2
 * Copyright 2021 The gRPC Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package io.grpc.xds;
18

19
import com.google.common.base.MoreObjects;
20
import com.google.protobuf.Message;
21
import io.grpc.ClientInterceptor;
22
import io.grpc.ServerInterceptor;
23
import java.io.Closeable;
24
import java.util.Objects;
25
import java.util.concurrent.ScheduledExecutorService;
26
import javax.annotation.Nullable;
27

28
/**
29
 * Defines the parsing functionality of an HTTP filter.
30
 *
31
 * <p>A Filter may optionally implement either {@link Filter#buildClientInterceptor} or
32
 * {@link Filter#buildServerInterceptor} or both, and return true from corresponding
33
 * {@link Provider#isClientFilter()}, {@link Provider#isServerFilter()} to indicate that the filter
34
 * is capable of working on the client side or server side or both, respectively.
35
 */
36
interface Filter extends Closeable {
37

38
  /** Represents an opaque data structure holding configuration for a filter. */
39
  interface FilterConfig {
40
    String typeUrl();
41
  }
42

43
  /**
44
   * Common interface for filter providers.
45
   */
46
  interface Provider {
47
    /**
48
     * The proto message types supported by this filter. A filter will be registered by each of its
49
     * supported message types.
50
     */
51
    String[] typeUrls();
52

53
    /**
54
     * Whether the filter can be installed on the client side.
55
     *
56
     * <p>Returns true if the filter implements {@link Filter#buildClientInterceptor}.
57
     */
58
    default boolean isClientFilter() {
59
      return false;
1✔
60
    }
61

62
    /**
63
     * Whether the filter can be installed into xDS-enabled servers.
64
     *
65
     * <p>Returns true if the filter implements {@link Filter#buildServerInterceptor}.
66
     */
67
    default boolean isServerFilter() {
68
      return false;
1✔
69
    }
70

71
    /**
72
     * Creates a new instance of the filter.
73
     *
74
     * <p>Returns a filter instance registered with the same typeUrls as the provider,
75
     * capable of working with the same FilterConfig type returned by provider's parse functions.
76
     *
77
     * <p>For xDS gRPC clients, new filter instances are created per combination of:
78
     * <ol>
79
     *   <li><code>XdsNameResolver</code> instance,</li>
80
     *   <li>Filter name+typeUrl in HttpConnectionManager (HCM) http_filters.</li>
81
     * </ol>
82
     *
83
     * <p>For xDS-enabled gRPC servers, new filter instances are created per combination of:
84
     * <ol>
85
     *   <li>Server instance,</li>
86
     *   <li>FilterChain name,</li>
87
     *   <li>Filter name+typeUrl in FilterChain's HCM.http_filters.</li>
88
     * </ol>
89
     */
90
    Filter newInstance();
91

92
    /**
93
     * Parses the top-level filter config from raw proto message. The message may be either a {@link
94
     * com.google.protobuf.Any} or a {@link com.google.protobuf.Struct}.
95
     */
96
    ConfigOrError<? extends FilterConfig> parseFilterConfig(Message rawProtoMessage);
97

98
    /**
99
     * Parses the per-filter override filter config from raw proto message. The message may be
100
     * either a {@link com.google.protobuf.Any} or a {@link com.google.protobuf.Struct}.
101
     */
102
    ConfigOrError<? extends FilterConfig> parseFilterConfigOverride(Message rawProtoMessage);
103
  }
104

105
  /** Uses the FilterConfigs produced above to produce an HTTP filter interceptor for clients. */
106
  @Nullable
107
  default ClientInterceptor buildClientInterceptor(
108
      FilterConfig config, @Nullable FilterConfig overrideConfig,
109
      ScheduledExecutorService scheduler) {
110
    return null;
1✔
111
  }
112

113
  /** Uses the FilterConfigs produced above to produce an HTTP filter interceptor for the server. */
114
  @Nullable
115
  default ServerInterceptor buildServerInterceptor(
116
      FilterConfig config, @Nullable FilterConfig overrideConfig) {
117
    return null;
1✔
118
  }
119

120
  /**
121
   * Releases filter resources like shared resources and remote connections.
122
   *
123
   * <p>See {@link Provider#newInstance()} for details on filter instance creation.
124
   */
125
  @Override
126
  default void close() {}
1✔
127

128
  /** Filter config with instance name. */
129
  final class NamedFilterConfig {
130
    // filter instance name
131
    final String name;
132
    final FilterConfig filterConfig;
133

134
    NamedFilterConfig(String name, FilterConfig filterConfig) {
1✔
135
      this.name = name;
1✔
136
      this.filterConfig = filterConfig;
1✔
137
    }
1✔
138

139
    String filterStateKey() {
140
      return name + "_" + filterConfig.typeUrl();
1✔
141
    }
142

143
    @Override
144
    public boolean equals(Object o) {
145
      if (this == o) {
1✔
146
        return true;
×
147
      }
148
      if (o == null || getClass() != o.getClass()) {
1✔
149
        return false;
×
150
      }
151
      NamedFilterConfig that = (NamedFilterConfig) o;
1✔
152
      return Objects.equals(name, that.name)
1✔
153
          && Objects.equals(filterConfig, that.filterConfig);
1✔
154
    }
155

156
    @Override
157
    public int hashCode() {
158
      return Objects.hash(name, filterConfig);
1✔
159
    }
160

161
    @Override
162
    public String toString() {
163
      return MoreObjects.toStringHelper(this)
1✔
164
          .add("name", name)
1✔
165
          .add("filterConfig", filterConfig)
1✔
166
          .toString();
1✔
167
    }
168
  }
169
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc