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 router implements the Envoy Router HTTP filter.
20package router
21
22import (
23	"fmt"
24
25	"github.com/golang/protobuf/proto"
26	"github.com/golang/protobuf/ptypes"
27	iresolver "google.golang.org/grpc/internal/resolver"
28	"google.golang.org/grpc/xds/internal/httpfilter"
29	"google.golang.org/protobuf/types/known/anypb"
30
31	pb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3"
32)
33
34// TypeURL is the message type for the Router configuration.
35const TypeURL = "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router"
36
37func init() {
38	httpfilter.Register(builder{})
39}
40
41// IsRouterFilter returns true iff a HTTP filter is a Router filter.
42func IsRouterFilter(b httpfilter.Filter) bool {
43	_, ok := b.(builder)
44	return ok
45}
46
47type builder struct {
48}
49
50func (builder) TypeURLs() []string { return []string{TypeURL} }
51
52func (builder) ParseFilterConfig(cfg proto.Message) (httpfilter.FilterConfig, error) {
53	// The gRPC router filter does not currently use any fields from the
54	// config.  Verify type only.
55	if cfg == nil {
56		return nil, fmt.Errorf("router: nil configuration message provided")
57	}
58	any, ok := cfg.(*anypb.Any)
59	if !ok {
60		return nil, fmt.Errorf("router: error parsing config %v: unknown type %T", cfg, cfg)
61	}
62	msg := new(pb.Router)
63	if err := ptypes.UnmarshalAny(any, msg); err != nil {
64		return nil, fmt.Errorf("router: error parsing config %v: %v", cfg, err)
65	}
66	return config{}, nil
67}
68
69func (builder) ParseFilterConfigOverride(override proto.Message) (httpfilter.FilterConfig, error) {
70	if override != nil {
71		return nil, fmt.Errorf("router: unexpected config override specified: %v", override)
72	}
73	return config{}, nil
74}
75
76var (
77	_ httpfilter.ClientInterceptorBuilder = builder{}
78	_ httpfilter.ServerInterceptorBuilder = builder{}
79)
80
81func (builder) BuildClientInterceptor(cfg, override httpfilter.FilterConfig) (iresolver.ClientInterceptor, error) {
82	if _, ok := cfg.(config); !ok {
83		return nil, fmt.Errorf("router: incorrect config type provided (%T): %v", cfg, cfg)
84	}
85	if override != nil {
86		return nil, fmt.Errorf("router: unexpected override configuration specified: %v", override)
87	}
88	// The gRPC router is implemented within the xds resolver's config
89	// selector, not as a separate plugin.  So we return a nil HTTPFilter,
90	// which will not be invoked.
91	return nil, nil
92}
93
94func (builder) BuildServerInterceptor(cfg, override httpfilter.FilterConfig) (iresolver.ServerInterceptor, error) {
95	if _, ok := cfg.(config); !ok {
96		return nil, fmt.Errorf("router: incorrect config type provided (%T): %v", cfg, cfg)
97	}
98	if override != nil {
99		return nil, fmt.Errorf("router: unexpected override configuration specified: %v", override)
100	}
101	// The gRPC router is currently unimplemented on the server side. So we
102	// return a nil HTTPFilter, which will not be invoked.
103	return nil, nil
104}
105
106// The gRPC router filter does not currently support any configuration.  Verify
107// type only.
108type config struct {
109	httpfilter.FilterConfig
110}
111