1/* 2 * 3 * Copyright 2021 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19// Package httpfilter contains the HTTPFilter interface and a registry for 20// storing and retrieving their implementations. 21package httpfilter 22 23import ( 24 "github.com/golang/protobuf/proto" 25 iresolver "google.golang.org/grpc/internal/resolver" 26) 27 28// FilterConfig represents an opaque data structure holding configuration for a 29// filter. Embed this interface to implement it. 30type FilterConfig interface { 31 isFilterConfig() 32} 33 34// Filter defines the parsing functionality of an HTTP filter. A Filter may 35// optionally implement either ClientInterceptorBuilder or 36// ServerInterceptorBuilder or both, indicating it is capable of working on the 37// client side or server side or both, respectively. 38type Filter interface { 39 // TypeURLs are the proto message types supported by this filter. A filter 40 // will be registered by each of its supported message types. 41 TypeURLs() []string 42 // ParseFilterConfig parses the provided configuration proto.Message from 43 // the LDS configuration of this filter. This may be an anypb.Any or a 44 // udpa.type.v1.TypedStruct for filters that do not accept a custom type. 45 // The resulting FilterConfig will later be passed to Build. 46 ParseFilterConfig(proto.Message) (FilterConfig, error) 47 // ParseFilterConfigOverride parses the provided override configuration 48 // proto.Message from the RDS override configuration of this filter. This 49 // may be an anypb.Any or a udpa.type.v1.TypedStruct for filters that do 50 // not accept a custom type. The resulting FilterConfig will later be 51 // passed to Build. 52 ParseFilterConfigOverride(proto.Message) (FilterConfig, error) 53 // IsTerminal returns whether this Filter is terminal or not (i.e. it must 54 // be last filter in the filter chain). 55 IsTerminal() bool 56} 57 58// ClientInterceptorBuilder constructs a Client Interceptor. If this type is 59// implemented by a Filter, it is capable of working on a client. 60type ClientInterceptorBuilder interface { 61 // BuildClientInterceptor uses the FilterConfigs produced above to produce 62 // an HTTP filter interceptor for clients. config will always be non-nil, 63 // but override may be nil if no override config exists for the filter. It 64 // is valid for Build to return a nil Interceptor and a nil error. In this 65 // case, the RPC will not be intercepted by this filter. 66 BuildClientInterceptor(config, override FilterConfig) (iresolver.ClientInterceptor, error) 67} 68 69// ServerInterceptorBuilder constructs a Server Interceptor. If this type is 70// implemented by a Filter, it is capable of working on a server. 71type ServerInterceptorBuilder interface { 72 // BuildServerInterceptor uses the FilterConfigs produced above to produce 73 // an HTTP filter interceptor for servers. config will always be non-nil, 74 // but override may be nil if no override config exists for the filter. It 75 // is valid for Build to return a nil Interceptor and a nil error. In this 76 // case, the RPC will not be intercepted by this filter. 77 BuildServerInterceptor(config, override FilterConfig) (iresolver.ServerInterceptor, error) 78} 79 80var ( 81 // m is a map from scheme to filter. 82 m = make(map[string]Filter) 83) 84 85// Register registers the HTTP filter Builder to the filter map. b.TypeURLs() 86// will be used as the types for this filter. 87// 88// NOTE: this function must only be called during initialization time (i.e. in 89// an init() function), and is not thread-safe. If multiple filters are 90// registered with the same type URL, the one registered last will take effect. 91func Register(b Filter) { 92 for _, u := range b.TypeURLs() { 93 m[u] = b 94 } 95} 96 97// UnregisterForTesting unregisters the HTTP Filter for testing purposes. 98func UnregisterForTesting(typeURL string) { 99 delete(m, typeURL) 100} 101 102// Get returns the HTTPFilter registered with typeURL. 103// 104// If no filter is register with typeURL, nil will be returned. 105func Get(typeURL string) Filter { 106 return m[typeURL] 107} 108