Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 13, 16:45 UTC
caddyhttp: Use new CEL APIs (fix #4915)
Hahaha this is the ultimate "I have no idea what I'm doing" commit but it compiles and the tests pass and I declare victory! ... probably broke something, should be tested more. It is nice that the protobuf dependency becomes indirect now.
Matthew Holt committed
Jul 28, 2022 at 14:50 UTC
ea8df6ff114299058593530d24fe244201525b9a
4 files changed
+43
-109
go.mod
+1
-1
@@ -33,7 +33,6 @@ require (
33
golang.org/x/net v0.0.0-20220630215102-69896b714898
34
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
35
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21
36
- google.golang.org/protobuf v1.28.0
36
gopkg.in/natefinch/lumberjack.v2 v2.0.0
37
gopkg.in/yaml.v3 v3.0.1
38
)
@@ -127,6 +126,7 @@ require (
126
golang.org/x/tools v0.1.7 // indirect
127
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
128
google.golang.org/grpc v1.46.0 // indirect
129
+ google.golang.org/protobuf v1.28.0 // indirect
130
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
131
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
132
howett.net/plist v1.0.0 // indirect
modules/caddyhttp/celmatcher.go
+29
-85
@@ -28,7 +28,6 @@ import (
28
"github.com/caddyserver/caddy/v2"
29
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
30
"github.com/google/cel-go/cel"
31
- "github.com/google/cel-go/checker/decls"
31
"github.com/google/cel-go/common"
32
"github.com/google/cel-go/common/operators"
33
"github.com/google/cel-go/common/types"
@@ -40,7 +39,6 @@ import (
39
"github.com/google/cel-go/parser"
40
"go.uber.org/zap"
41
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
43
- "google.golang.org/protobuf/proto"
42
)
43
44
func init() {
@@ -126,13 +124,12 @@ func (m *MatchExpression) Provision(ctx caddy.Context) error {
124
125
// create the CEL environment
126
env, err := cel.NewEnv(
129
- cel.Declarations(
130
- decls.NewVar("request", httpRequestObjectType),
131
- decls.NewFunction(placeholderFuncName,
132
- decls.NewOverload(placeholderFuncName+"_httpRequest_string",
133
- []*exprpb.Type{httpRequestObjectType, decls.String},
134
- decls.Any)),
135
- ),
127
+ cel.Function(placeholderFuncName, cel.SingletonBinaryImpl(m.caddyPlaceholderFunc), cel.Overload(
128
+ placeholderFuncName+"_httpRequest_string",
129
+ []*cel.Type{httpRequestObjectType, cel.StringType},
130
+ cel.AnyType,
131
+ )),
132
+ cel.Variable("request", httpRequestObjectType),
133
cel.CustomTypeAdapter(m.ta),
134
ext.Strings(),
135
matcherLib,
@@ -149,20 +146,12 @@ func (m *MatchExpression) Provision(ctx caddy.Context) error {
146
147
// request matching is a boolean operation, so we don't really know
148
// what to do if the expression returns a non-boolean type
152
- if !proto.Equal(checked.ResultType(), decls.Bool) {
153
- return fmt.Errorf("CEL request matcher expects return type of bool, not %s", checked.ResultType())
149
+ if checked.OutputType() != cel.BoolType {
150
+ return fmt.Errorf("CEL request matcher expects return type of bool, not %s", checked.OutputType())
151
}
152
153
// compile the "program"
157
- m.prg, err = env.Program(checked,
158
- cel.EvalOptions(cel.OptOptimize),
159
- cel.Functions(
160
- &functions.Overload{
161
- Operator: placeholderFuncName,
162
- Binary: m.caddyPlaceholderFunc,
163
- },
164
- ),
165
- )
154
+ m.prg, err = env.Program(checked, cel.EvalOptions(cel.OptOptimize))
155
if err != nil {
156
return fmt.Errorf("compiling CEL program: %s", err)
157
}
@@ -321,62 +310,46 @@ type CELLibraryProducer interface {
310
// limited set of function signatures. For strong type validation you may need
311
// to provide a custom macro which does a more detailed analysis of the CEL
312
// literal provided to the macro as an argument.
324
-func CELMatcherImpl(macroName, funcName string, matcherDataTypes []*exprpb.Type, fac CELMatcherFactory) (cel.Library, error) {
325
- requestType := decls.NewObjectType("http.Request")
313
+func CELMatcherImpl(macroName, funcName string, matcherDataTypes []*cel.Type, fac CELMatcherFactory) (cel.Library, error) {
314
+ requestType := cel.ObjectType("http.Request")
315
var macro parser.Macro
316
switch len(matcherDataTypes) {
317
case 1:
318
matcherDataType := matcherDataTypes[0]
330
- if isCELStringListType(matcherDataType) {
319
+ switch matcherDataType.String() {
320
+ case "list(string)":
321
macro = parser.NewGlobalVarArgMacro(macroName, celMatcherStringListMacroExpander(funcName))
332
- } else if isCELStringType(matcherDataType) {
322
+ case cel.StringType.String():
323
macro = parser.NewGlobalMacro(macroName, 1, celMatcherStringMacroExpander(funcName))
334
- } else if isCELJSONType(matcherDataType) {
324
+ case CELTypeJSON.String():
325
macro = parser.NewGlobalMacro(macroName, 1, celMatcherJSONMacroExpander(funcName))
336
- } else {
337
- return nil, fmt.Errorf("unsupported matcher data type: %s", cel.FormatType(matcherDataType))
326
+ default:
327
+ return nil, fmt.Errorf("unsupported matcher data type: %s", matcherDataType)
328
}
329
case 2:
340
- if isCELStringType(matcherDataTypes[0]) && isCELStringType(matcherDataTypes[1]) {
330
+ if matcherDataTypes[0] == cel.StringType && matcherDataTypes[1] == cel.StringType {
331
macro = parser.NewGlobalMacro(macroName, 2, celMatcherStringListMacroExpander(funcName))
342
- matcherDataTypes = []*exprpb.Type{CelTypeListString}
332
+ matcherDataTypes = []*cel.Type{cel.ListType(cel.StringType)}
333
} else {
344
- return nil, fmt.Errorf(
345
- "unsupported matcher data type: %s, %s",
346
- cel.FormatType(matcherDataTypes[0]), cel.FormatType(matcherDataTypes[1]),
347
- )
334
+ return nil, fmt.Errorf("unsupported matcher data type: %s, %s", matcherDataTypes[0], matcherDataTypes[1])
335
}
336
case 3:
350
- if isCELStringType(matcherDataTypes[0]) && isCELStringType(matcherDataTypes[1]) && isCELStringType(matcherDataTypes[2]) {
337
+ if matcherDataTypes[0] == cel.StringType && matcherDataTypes[1] == cel.StringType && matcherDataTypes[2] == cel.StringType {
338
macro = parser.NewGlobalMacro(macroName, 3, celMatcherStringListMacroExpander(funcName))
352
- matcherDataTypes = []*exprpb.Type{CelTypeListString}
339
+ matcherDataTypes = []*cel.Type{cel.ListType(cel.StringType)}
340
} else {
354
- return nil, fmt.Errorf(
355
- "unsupported matcher data type: %s, %s, %s",
356
- cel.FormatType(matcherDataTypes[0]), cel.FormatType(matcherDataTypes[1]), cel.FormatType(matcherDataTypes[2]),
357
- )
341
+ return nil, fmt.Errorf("unsupported matcher data type: %s, %s, %s", matcherDataTypes[0], matcherDataTypes[1], matcherDataTypes[2])
342
}
343
}
344
envOptions := []cel.EnvOption{
345
cel.Macros(macro),
362
- cel.Declarations(
363
- decls.NewFunction(funcName,
364
- decls.NewOverload(
365
- funcName,
366
- append([]*exprpb.Type{requestType}, matcherDataTypes...),
367
- decls.Bool,
368
- ),
369
- ),
370
- ),
346
+ cel.Function(funcName,
347
+ cel.Overload(funcName, append([]*cel.Type{requestType}, matcherDataTypes...), cel.BoolType),
348
+
349
+ cel.SingletonBinaryImpl(CELMatcherRuntimeFunction(funcName, fac))),
350
}
351
programOptions := []cel.ProgramOption{
352
cel.CustomDecorator(CELMatcherDecorator(funcName, fac)),
374
- cel.Functions(
375
- &functions.Overload{
376
- Operator: funcName,
377
- Binary: CELMatcherRuntimeFunction(funcName, fac),
378
- },
379
- ),
353
}
354
return NewMatcherCELLibrary(envOptions, programOptions), nil
355
}
@@ -610,25 +583,6 @@ func CELValueToMapStrList(data ref.Val) (map[string][]string, error) {
583
return mapStrListStr, nil
584
}
585
613
-// isCELJSONType returns whether the type corresponds to JSON input.
614
-func isCELJSONType(t *exprpb.Type) bool {
615
- switch t.GetTypeKind().(type) {
616
- case *exprpb.Type_MapType_:
617
- mapType := t.GetMapType()
618
- return isCELStringType(mapType.GetKeyType()) && mapType.GetValueType().GetDyn() != nil
619
- }
620
- return false
621
-}
622
-
623
-// isCELStringType returns whether the type corresponds to a string.
624
-func isCELStringType(t *exprpb.Type) bool {
625
- switch t.GetTypeKind().(type) {
626
- case *exprpb.Type_Primitive:
627
- return t.GetPrimitive() == exprpb.Type_STRING
628
- }
629
- return false
630
-}
631
-
586
// isCELStringExpr indicates whether the expression is a supported string expression
587
func isCELStringExpr(e *exprpb.Expr) bool {
588
return isCELStringLiteral(e) || isCELCaddyPlaceholderCall(e) || isCELConcatCall(e)
@@ -681,15 +635,6 @@ func isCELConcatCall(e *exprpb.Expr) bool {
635
return false
636
}
637
684
-// isCELStringListType returns whether the type corresponds to a list of strings.
685
-func isCELStringListType(t *exprpb.Type) bool {
686
- switch t.GetTypeKind().(type) {
687
- case *exprpb.Type_ListType_:
688
- return isCELStringType(t.GetListType().GetElemType())
689
- }
690
- return false
691
-}
692
-
638
// isCELStringListLiteral returns whether the expression resolves to a list literal
639
// containing only string constants or a placeholder call.
640
func isCELStringListLiteral(e *exprpb.Expr) bool {
@@ -713,11 +658,10 @@ var (
658
placeholderRegexp = regexp.MustCompile(`{([a-zA-Z][\w.-]+)}`)
659
placeholderExpansion = `caddyPlaceholder(request, "${1}")`
660
716
- CelTypeListString = decls.NewListType(decls.String)
717
- CelTypeJson = decls.NewMapType(decls.String, decls.Dyn)
661
+ CELTypeJSON = cel.MapType(cel.StringType, cel.DynType)
662
)
663
720
-var httpRequestObjectType = decls.NewObjectType("http.Request")
664
+var httpRequestObjectType = cel.ObjectType("http.Request")
665
666
// The name of the CEL function which accesses Replacer values.
667
const placeholderFuncName = "caddyPlaceholder"
modules/caddyhttp/fileserver/matcher.go
+2
-10
@@ -27,7 +27,6 @@ import (
27
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
28
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
29
"github.com/google/cel-go/cel"
30
- "github.com/google/cel-go/checker/decls"
30
"github.com/google/cel-go/common"
31
"github.com/google/cel-go/common/operators"
32
"github.com/google/cel-go/common/types/ref"
@@ -153,17 +152,10 @@ func (m *MatchFile) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
152
// Example:
153
// expression file({'root': '/srv', 'try_files': [{http.request.uri.path}, '/index.php'], 'try_policy': 'first_exist', 'split_path': ['.php']})
154
func (MatchFile) CELLibrary(ctx caddy.Context) (cel.Library, error) {
156
- requestType := decls.NewObjectType("http.Request")
155
+ requestType := cel.ObjectType("http.Request")
156
envOptions := []cel.EnvOption{
157
cel.Macros(parser.NewGlobalVarArgMacro("file", celFileMatcherMacroExpander())),
159
- cel.Declarations(
160
- decls.NewFunction("file",
161
- decls.NewOverload("file_request_map",
162
- []*exprpb.Type{requestType, caddyhttp.CelTypeJson},
163
- decls.Bool,
164
- ),
165
- ),
166
- ),
158
+ cel.Function("file", cel.Overload("file_request_map", []*cel.Type{requestType, caddyhttp.CELTypeJSON}, cel.BoolType)),
159
}
160
161
matcherFactory := func(data ref.Val) (caddyhttp.RequestMatcher, error) {
modules/caddyhttp/matchers.go
+11
-13
@@ -33,11 +33,9 @@ import (
33
"github.com/caddyserver/caddy/v2"
34
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
35
"github.com/google/cel-go/cel"
36
- "github.com/google/cel-go/checker/decls"
36
"github.com/google/cel-go/common/types"
37
"github.com/google/cel-go/common/types/ref"
38
"go.uber.org/zap"
40
- exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
39
)
40
41
type (
@@ -310,7 +308,7 @@ func (MatchHost) CELLibrary(ctx caddy.Context) (cel.Library, error) {
308
return CELMatcherImpl(
309
"host",
310
"host_match_request_list",
313
- []*exprpb.Type{CelTypeListString},
311
+ []*cel.Type{cel.ListType(cel.StringType)},
312
func(data ref.Val) (RequestMatcher, error) {
313
refStringList := reflect.TypeOf([]string{})
314
strList, err := data.ConvertToNative(refStringList)
@@ -441,7 +439,7 @@ func (MatchPath) CELLibrary(ctx caddy.Context) (cel.Library, error) {
439
// name of the function that the macro will be rewritten to call.
440
"path_match_request_list",
441
// internal data type of the MatchPath value.
444
- []*exprpb.Type{CelTypeListString},
442
+ []*cel.Type{cel.ListType(cel.StringType)},
443
// function to convert a constant list of strings to a MatchPath instance.
444
func(data ref.Val) (RequestMatcher, error) {
445
refStringList := reflect.TypeOf([]string{})
@@ -509,7 +507,7 @@ func (MatchPathRE) CELLibrary(ctx caddy.Context) (cel.Library, error) {
507
unnamedPattern, err := CELMatcherImpl(
508
"path_regexp",
509
"path_regexp_request_string",
512
- []*exprpb.Type{decls.String},
510
+ []*cel.Type{cel.StringType},
511
func(data ref.Val) (RequestMatcher, error) {
512
pattern := data.(types.String)
513
matcher := MatchPathRE{MatchRegexp{Pattern: string(pattern)}}
@@ -523,7 +521,7 @@ func (MatchPathRE) CELLibrary(ctx caddy.Context) (cel.Library, error) {
521
namedPattern, err := CELMatcherImpl(
522
"path_regexp",
523
"path_regexp_request_string_string",
526
- []*exprpb.Type{decls.String, decls.String},
524
+ []*cel.Type{cel.StringType, cel.StringType},
525
func(data ref.Val) (RequestMatcher, error) {
526
refStringList := reflect.TypeOf([]string{})
527
params, err := data.ConvertToNative(refStringList)
@@ -582,7 +580,7 @@ func (MatchMethod) CELLibrary(_ caddy.Context) (cel.Library, error) {
580
return CELMatcherImpl(
581
"method",
582
"method_request_list",
585
- []*exprpb.Type{CelTypeListString},
583
+ []*cel.Type{cel.ListType(cel.StringType)},
584
func(data ref.Val) (RequestMatcher, error) {
585
refStringList := reflect.TypeOf([]string{})
586
strList, err := data.ConvertToNative(refStringList)
@@ -668,7 +666,7 @@ func (MatchQuery) CELLibrary(_ caddy.Context) (cel.Library, error) {
666
return CELMatcherImpl(
667
"query",
668
"query_matcher_request_map",
671
- []*exprpb.Type{CelTypeJson},
669
+ []*cel.Type{CELTypeJSON},
670
func(data ref.Val) (RequestMatcher, error) {
671
mapStrListStr, err := CELValueToMapStrList(data)
672
if err != nil {
@@ -744,7 +742,7 @@ func (MatchHeader) CELLibrary(_ caddy.Context) (cel.Library, error) {
742
return CELMatcherImpl(
743
"header",
744
"header_matcher_request_map",
747
- []*exprpb.Type{CelTypeJson},
745
+ []*cel.Type{CELTypeJSON},
746
func(data ref.Val) (RequestMatcher, error) {
747
mapStrListStr, err := CELValueToMapStrList(data)
748
if err != nil {
@@ -901,7 +899,7 @@ func (MatchHeaderRE) CELLibrary(ctx caddy.Context) (cel.Library, error) {
899
unnamedPattern, err := CELMatcherImpl(
900
"header_regexp",
901
"header_regexp_request_string_string",
904
- []*exprpb.Type{decls.String, decls.String},
902
+ []*cel.Type{cel.StringType, cel.StringType},
903
func(data ref.Val) (RequestMatcher, error) {
904
refStringList := reflect.TypeOf([]string{})
905
params, err := data.ConvertToNative(refStringList)
@@ -921,7 +919,7 @@ func (MatchHeaderRE) CELLibrary(ctx caddy.Context) (cel.Library, error) {
919
namedPattern, err := CELMatcherImpl(
920
"header_regexp",
921
"header_regexp_request_string_string_string",
924
- []*exprpb.Type{decls.String, decls.String, decls.String},
922
+ []*cel.Type{cel.StringType, cel.StringType, cel.StringType},
923
func(data ref.Val) (RequestMatcher, error) {
924
refStringList := reflect.TypeOf([]string{})
925
params, err := data.ConvertToNative(refStringList)
@@ -985,7 +983,7 @@ func (MatchProtocol) CELLibrary(_ caddy.Context) (cel.Library, error) {
983
return CELMatcherImpl(
984
"protocol",
985
"protocol_request_string",
988
- []*exprpb.Type{decls.String},
986
+ []*cel.Type{cel.StringType},
987
func(data ref.Val) (RequestMatcher, error) {
988
protocolStr, ok := data.(types.String)
989
if !ok {
@@ -1107,7 +1105,7 @@ func (MatchRemoteIP) CELLibrary(ctx caddy.Context) (cel.Library, error) {
1105
// name of the function that the macro will be rewritten to call.
1106
"remote_ip_match_request_list",
1107
// internal data type of the MatchPath value.
1110
- []*exprpb.Type{CelTypeListString},
1108
+ []*cel.Type{cel.ListType(cel.StringType)},
1109
// function to convert a constant list of strings to a MatchPath instance.
1110
func(data ref.Val) (RequestMatcher, error) {
1111
refStringList := reflect.TypeOf([]string{})