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}
54
55// ClientInterceptorBuilder constructs a Client Interceptor.  If this type is
56// implemented by a Filter, it is capable of working on a client.
57type ClientInterceptorBuilder interface {
58	// BuildClientInterceptor uses the FilterConfigs produced above to produce
59	// an HTTP filter interceptor for clients.  config will always be non-nil,
60	// but override may be nil if no override config exists for the filter.  It
61	// is valid for Build to return a nil Interceptor and a nil error.  In this
62	// case, the RPC will not be intercepted by this filter.
63	BuildClientInterceptor(config, override FilterConfig) (iresolver.ClientInterceptor, error)
64}
65
66// ServerInterceptorBuilder constructs a Server Interceptor.  If this type is
67// implemented by a Filter, it is capable of working on a server.
68type ServerInterceptorBuilder interface {
69	// BuildServerInterceptor uses the FilterConfigs produced above to produce
70	// an HTTP filter interceptor for servers.  config will always be non-nil,
71	// but override may be nil if no override config exists for the filter.  It
72	// is valid for Build to return a nil Interceptor and a nil error.  In this
73	// case, the RPC will not be intercepted by this filter.
74	BuildServerInterceptor(config, override FilterConfig) (iresolver.ServerInterceptor, error)
75}
76
77var (
78	// m is a map from scheme to filter.
79	m = make(map[string]Filter)
80)
81
82// Register registers the HTTP filter Builder to the filter map. b.TypeURLs()
83// will be used as the types for this filter.
84//
85// NOTE: this function must only be called during initialization time (i.e. in
86// an init() function), and is not thread-safe. If multiple filters are
87// registered with the same type URL, the one registered last will take effect.
88func Register(b Filter) {
89	for _, u := range b.TypeURLs() {
90		m[u] = b
91	}
92}
93
94// Get returns the HTTPFilter registered with typeURL.
95//
96// If no filter is register with typeURL, nil will be returned.
97func Get(typeURL string) Filter {
98	return m[typeURL]
99}
100