diff options
author | Francis Lavoie <[email protected]> | 2024-03-03 05:14:38 -0500 |
---|---|---|
committer | Francis Lavoie <[email protected]> | 2024-04-17 11:57:30 -0400 |
commit | 9b757ce862fcaf5535c07ef67c233dfc358316ef (patch) | |
tree | 438d1313ea339d19e554b64b34052ea8361f0b12 /modules/caddyhttp | |
parent | 244ef288a9fb81366c65976a14d2d5642e9ed24e (diff) | |
download | caddy-9b757ce862fcaf5535c07ef67c233dfc358316ef.tar.gz caddy-9b757ce862fcaf5535c07ef67c233dfc358316ef.zip |
Pass down matcher name through expression matcher
Diffstat (limited to 'modules/caddyhttp')
-rw-r--r-- | modules/caddyhttp/celmatcher.go | 47 | ||||
-rw-r--r-- | modules/caddyhttp/celmatcher_test.go | 8 | ||||
-rw-r--r-- | modules/caddyhttp/fileserver/matcher_test.go | 4 | ||||
-rw-r--r-- | modules/caddyhttp/matchers.go | 28 |
4 files changed, 77 insertions, 10 deletions
diff --git a/modules/caddyhttp/celmatcher.go b/modules/caddyhttp/celmatcher.go index e1f15e869..d4016478e 100644 --- a/modules/caddyhttp/celmatcher.go +++ b/modules/caddyhttp/celmatcher.go @@ -62,7 +62,12 @@ type MatchExpression struct { // The CEL expression to evaluate. Any Caddy placeholders // will be expanded and situated into proper CEL function // calls before evaluating. - Expr string + Expr string `json:"expr,omitempty"` + + // Name is an optional name for this matcher. + // This is used to populate the name for regexp + // matchers that appear in the expression. + Name string `json:"name,omitempty"` expandedExpr string prg cel.Program @@ -81,12 +86,36 @@ func (MatchExpression) CaddyModule() caddy.ModuleInfo { // MarshalJSON marshals m's expression. func (m MatchExpression) MarshalJSON() ([]byte, error) { - return json.Marshal(m.Expr) + // if the name is empty, then we can marshal just the expression string + if m.Name == "" { + return json.Marshal(m.Expr) + } + // otherwise, we need to marshal the full object, using an + // anonymous struct to avoid infinite recursion + return json.Marshal(struct { + Expr string `json:"expr"` + Name string `json:"name"` + }{ + Expr: m.Expr, + Name: m.Name, + }) } // UnmarshalJSON unmarshals m's expression. func (m *MatchExpression) UnmarshalJSON(data []byte) error { - return json.Unmarshal(data, &m.Expr) + // if the data is a string, then it's just the expression + if data[0] == '"' { + return json.Unmarshal(data, &m.Expr) + } + // otherwise, it's a full object, so unmarshal it, + // using an temp map to avoid infinite recursion + var tmpJson map[string]any + err := json.Unmarshal(data, &tmpJson) + *m = MatchExpression{ + Expr: tmpJson["expr"].(string), + Name: tmpJson["name"].(string), + } + return err } // Provision sets ups m. @@ -109,6 +138,11 @@ func (m *MatchExpression) Provision(ctx caddy.Context) error { matcherLibProducers = append(matcherLibProducers, p) } } + + // add the matcher name to the context so that the matcher name + // can be used by regexp matchers being provisioned + ctx = ctx.WithValue(MatcherNameCtxKey, m.Name) + // Assemble the compilation and program options from the different library // producers into a single cel.Library implementation. matcherEnvOpts := []cel.EnvOption{} @@ -197,6 +231,11 @@ func (m *MatchExpression) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { // quoted string; commonly quotes are used in Caddyfile to // define the expression m.Expr = d.Val() + + // use the named matcher's name, to fill regexp + // matchers names by default + m.Name = d.GetContextString(caddyfile.MatcherNameCtxKey) + return nil } @@ -673,6 +712,8 @@ var httpRequestObjectType = cel.ObjectType("http.Request") // The name of the CEL function which accesses Replacer values. const placeholderFuncName = "caddyPlaceholder" +const MatcherNameCtxKey = "matcher_name" + // Interface guards var ( _ caddy.Provisioner = (*MatchExpression)(nil) diff --git a/modules/caddyhttp/celmatcher_test.go b/modules/caddyhttp/celmatcher_test.go index e67b87c77..25fdcf45e 100644 --- a/modules/caddyhttp/celmatcher_test.go +++ b/modules/caddyhttp/celmatcher_test.go @@ -380,7 +380,9 @@ func TestMatchExpressionMatch(t *testing.T) { for _, tst := range matcherTests { tc := tst t.Run(tc.name, func(t *testing.T) { - err := tc.expression.Provision(caddy.Context{}) + caddyCtx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()}) + defer cancel() + err := tc.expression.Provision(caddyCtx) if err != nil { if !tc.wantErr { t.Errorf("MatchExpression.Provision() error = %v, wantErr %v", err, tc.wantErr) @@ -482,7 +484,9 @@ func TestMatchExpressionProvision(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := tt.expression.Provision(caddy.Context{}); (err != nil) != tt.wantErr { + ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()}) + defer cancel() + if err := tt.expression.Provision(ctx); (err != nil) != tt.wantErr { t.Errorf("MatchExpression.Provision() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/modules/caddyhttp/fileserver/matcher_test.go b/modules/caddyhttp/fileserver/matcher_test.go index 5ffb63b6a..527c16bd1 100644 --- a/modules/caddyhttp/fileserver/matcher_test.go +++ b/modules/caddyhttp/fileserver/matcher_test.go @@ -360,7 +360,9 @@ func TestMatchExpressionMatch(t *testing.T) { for _, tst := range expressionTests { tc := tst t.Run(tc.name, func(t *testing.T) { - err := tc.expression.Provision(caddy.Context{}) + caddyCtx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()}) + defer cancel() + err := tc.expression.Provision(caddyCtx) if err != nil { if !tc.wantErr { t.Errorf("MatchExpression.Provision() error = %v, wantErr %v", err, tc.wantErr) diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go index 8aca605ec..23dc6e8a8 100644 --- a/modules/caddyhttp/matchers.go +++ b/modules/caddyhttp/matchers.go @@ -675,7 +675,10 @@ func (MatchPathRE) CELLibrary(ctx caddy.Context) (cel.Library, error) { []*cel.Type{cel.StringType}, func(data ref.Val) (RequestMatcher, error) { pattern := data.(types.String) - matcher := MatchPathRE{MatchRegexp{Pattern: string(pattern)}} + matcher := MatchPathRE{MatchRegexp{ + Name: ctx.Value(MatcherNameCtxKey).(string), + Pattern: string(pattern), + }} err := matcher.Provision(ctx) return matcher, err }, @@ -694,7 +697,14 @@ func (MatchPathRE) CELLibrary(ctx caddy.Context) (cel.Library, error) { return nil, err } strParams := params.([]string) - matcher := MatchPathRE{MatchRegexp{Name: strParams[0], Pattern: strParams[1]}} + name := strParams[0] + if name == "" { + name = ctx.Value(MatcherNameCtxKey).(string) + } + matcher := MatchPathRE{MatchRegexp{ + Name: name, + Pattern: strParams[1], + }} err = matcher.Provision(ctx) return matcher, err }, @@ -1104,7 +1114,10 @@ func (MatchHeaderRE) CELLibrary(ctx caddy.Context) (cel.Library, error) { } strParams := params.([]string) matcher := MatchHeaderRE{} - matcher[strParams[0]] = &MatchRegexp{Pattern: strParams[1], Name: ""} + matcher[strParams[0]] = &MatchRegexp{ + Pattern: strParams[1], + Name: ctx.Value(MatcherNameCtxKey).(string), + } err = matcher.Provision(ctx) return matcher, err }, @@ -1123,8 +1136,15 @@ func (MatchHeaderRE) CELLibrary(ctx caddy.Context) (cel.Library, error) { return nil, err } strParams := params.([]string) + name := strParams[0] + if name == "" { + name = ctx.Value(MatcherNameCtxKey).(string) + } matcher := MatchHeaderRE{} - matcher[strParams[1]] = &MatchRegexp{Pattern: strParams[2], Name: strParams[0]} + matcher[strParams[1]] = &MatchRegexp{ + Pattern: strParams[2], + Name: name, + } err = matcher.Provision(ctx) return matcher, err }, |