/* * * Copyright 2021 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ // Package httpfilter contains the HTTPFilter interface and a registry for // storing and retrieving their implementations. package httpfilter import ( "github.com/golang/protobuf/proto" iresolver "google.golang.org/grpc/internal/resolver" ) // FilterConfig represents an opaque data structure holding configuration for a // filter. Embed this interface to implement it. type FilterConfig interface { isFilterConfig() } // Filter defines the parsing functionality of an HTTP filter. A Filter may // optionally implement either ClientInterceptorBuilder or // ServerInterceptorBuilder or both, indicating it is capable of working on the // client side or server side or both, respectively. type Filter interface { // TypeURLs are the proto message types supported by this filter. A filter // will be registered by each of its supported message types. TypeURLs() []string // ParseFilterConfig parses the provided configuration proto.Message from // the LDS configuration of this filter. This may be an anypb.Any, a // udpa.type.v1.TypedStruct, or an xds.type.v3.TypedStruct for filters that // do not accept a custom type. The resulting FilterConfig will later be // passed to Build. ParseFilterConfig(proto.Message) (FilterConfig, error) // ParseFilterConfigOverride parses the provided override configuration // proto.Message from the RDS override configuration of this filter. This // may be an anypb.Any, a udpa.type.v1.TypedStruct, or an // xds.type.v3.TypedStruct for filters that do not accept a custom type. // The resulting FilterConfig will later be passed to Build. ParseFilterConfigOverride(proto.Message) (FilterConfig, error) // IsTerminal returns whether this Filter is terminal or not (i.e. it must // be last filter in the filter chain). IsTerminal() bool } // ClientInterceptorBuilder constructs a Client Interceptor. If this type is // implemented by a Filter, it is capable of working on a client. type ClientInterceptorBuilder interface { // BuildClientInterceptor uses the FilterConfigs produced above to produce // an HTTP filter interceptor for clients. config will always be non-nil, // but override may be nil if no override config exists for the filter. It // is valid for Build to return a nil Interceptor and a nil error. In this // case, the RPC will not be intercepted by this filter. BuildClientInterceptor(config, override FilterConfig) (iresolver.ClientInterceptor, error) } // ServerInterceptorBuilder constructs a Server Interceptor. If this type is // implemented by a Filter, it is capable of working on a server. type ServerInterceptorBuilder interface { // BuildServerInterceptor uses the FilterConfigs produced above to produce // an HTTP filter interceptor for servers. config will always be non-nil, // but override may be nil if no override config exists for the filter. It // is valid for Build to return a nil Interceptor and a nil error. In this // case, the RPC will not be intercepted by this filter. BuildServerInterceptor(config, override FilterConfig) (iresolver.ServerInterceptor, error) } var ( // m is a map from scheme to filter. m = make(map[string]Filter) ) // Register registers the HTTP filter Builder to the filter map. b.TypeURLs() // will be used as the types for this filter. // // NOTE: this function must only be called during initialization time (i.e. in // an init() function), and is not thread-safe. If multiple filters are // registered with the same type URL, the one registered last will take effect. func Register(b Filter) { for _, u := range b.TypeURLs() { m[u] = b } } // UnregisterForTesting unregisters the HTTP Filter for testing purposes. func UnregisterForTesting(typeURL string) { delete(m, typeURL) } // Get returns the HTTPFilter registered with typeURL. // // If no filter is register with typeURL, nil will be returned. func Get(typeURL string) Filter { return m[typeURL] }