-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Expand file tree
/
Copy pathrequest.go
More file actions
98 lines (83 loc) · 2.97 KB
/
Copy pathrequest.go
File metadata and controls
98 lines (83 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package routingconnector // import "github.com/open-telemetry/opentelemetry-collector-contrib/connector/routingconnector"
import (
"context"
"errors"
"regexp"
"slices"
"strings"
"go.opentelemetry.io/collector/client"
"google.golang.org/grpc/metadata"
)
// This file defines an extremely simple request condition grammar. The goal is to provide a similar feel to OTTL,
// but it's not clear that anything more than a simple comparison is needed. We can expand this grammar in the
// future if needed. For now, it expects the condition to be in exactly the format:
// 'request["<name>"] <comparator> <value>' where <comparator> is either '==' or '!='.
var (
requestFieldRegex = regexp.MustCompile(`request\[".*"\]`)
valueFieldRegex = regexp.MustCompile(`".*"`)
comparatorRegex = regexp.MustCompile(`==|!=`)
)
type requestCondition struct {
compareFunc func(string) bool
attributeName string
}
func parseRequestCondition(condition string) (*requestCondition, error) {
if condition == "" {
return nil, errors.New("condition is empty")
}
comparators := comparatorRegex.FindAllString(condition, 2)
switch {
case len(comparators) == 0:
return nil, errors.New("condition does not contain a valid comparator")
case len(comparators) > 1:
return nil, errors.New("condition contains multiple comparators")
}
parts := strings.Split(condition, comparators[0])
if len(parts) < 2 {
return nil, errors.New("condition does not contain a valid comparator")
}
if len(parts) > 2 {
return nil, errors.New("condition contains multiple comparators")
}
parts[0] = strings.TrimSpace(parts[0])
parts[1] = strings.TrimSpace(parts[1])
if !requestFieldRegex.MatchString(parts[0]) {
return nil, errors.New(`condition must have format 'request["<name>"] <comparator> <value>'`)
}
if !valueFieldRegex.MatchString(parts[1]) {
return nil, errors.New(`condition must have format 'request["<name>"] <comparator> "<value>"'`)
}
valueWithoutQuotes := strings.TrimSuffix(strings.TrimPrefix(parts[1], `"`), `"`)
compareFunc := func(value string) bool {
return value == valueWithoutQuotes
}
if comparators[0] == "!=" {
compareFunc = func(value string) bool {
return value != valueWithoutQuotes
}
}
return &requestCondition{
attributeName: strings.TrimSuffix(strings.TrimPrefix(parts[0], `request["`), `"]`),
compareFunc: compareFunc,
}, nil
}
func (rc *requestCondition) matchRequest(ctx context.Context) bool {
return rc.matchGRPC(ctx) || rc.matchHTTP(ctx)
}
func (rc *requestCondition) matchGRPC(ctx context.Context) bool {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return false
}
values, ok := md[strings.ToLower(rc.attributeName)]
if !ok {
return false
}
return slices.ContainsFunc(values, rc.compareFunc)
}
func (rc *requestCondition) matchHTTP(ctx context.Context) bool {
values := client.FromContext(ctx).Metadata.Get(rc.attributeName)
return slices.ContainsFunc(values, rc.compareFunc)
}