From aa9822854d12a954f9b6fe857eb073466e1d3626 Mon Sep 17 00:00:00 2001 From: David Stotijn Date: Thu, 31 Mar 2022 15:12:54 +0200 Subject: [PATCH] Rename `search` package to `filter` package --- .golangci.yml | 2 +- pkg/api/resolvers.go | 22 +-- pkg/db/badger/proj_test.go | 4 +- pkg/{search => filter}/ast.go | 12 +- pkg/filter/ast_test.go | 212 ++++++++++++++++++++++++++ pkg/{search => filter}/http.go | 12 +- pkg/{search => filter}/lexer.go | 2 +- pkg/{search => filter}/lexer_test.go | 2 +- pkg/{search => filter}/parser.go | 6 +- pkg/{search => filter}/parser_test.go | 4 +- pkg/proj/proj.go | 10 +- pkg/proxy/intercept/filter.go | 94 ++++++------ pkg/proxy/intercept/intercept.go | 10 +- pkg/proxy/intercept/settings.go | 6 +- pkg/reqlog/reqlog.go | 4 +- pkg/reqlog/search.go | 50 +++--- pkg/reqlog/search_test.go | 4 +- pkg/search/ast_test.go | 212 -------------------------- pkg/sender/search.go | 50 +++--- pkg/sender/search_test.go | 4 +- pkg/sender/sender.go | 4 +- 21 files changed, 364 insertions(+), 362 deletions(-) rename pkg/{search => filter}/ast.go (71%) create mode 100644 pkg/filter/ast_test.go rename pkg/{search => filter}/http.go (83%) rename pkg/{search => filter}/lexer.go (99%) rename pkg/{search => filter}/lexer_test.go (99%) rename pkg/{search => filter}/parser.go (97%) rename pkg/{search => filter}/parser_test.go (98%) delete mode 100644 pkg/search/ast_test.go diff --git a/.golangci.yml b/.golangci.yml index cf598a5..f3c0e06 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -35,7 +35,7 @@ linters-settings: godot: capital: true ireturn: - allow: "error,empty,anon,stdlib,.*(or|er)$,github.com/99designs/gqlgen/graphql.Marshaler,github.com/dstotijn/hetty/pkg/api.QueryResolver,github.com/dstotijn/hetty/pkg/search.Expression" + allow: "error,empty,anon,stdlib,.*(or|er)$,github.com/99designs/gqlgen/graphql.Marshaler,github.com/dstotijn/hetty/pkg/api.QueryResolver,github.com/dstotijn/hetty/pkg/filter.Expression" issues: exclude-rules: diff --git a/pkg/api/resolvers.go b/pkg/api/resolvers.go index 3802205..f0421cd 100644 --- a/pkg/api/resolvers.go +++ b/pkg/api/resolvers.go @@ -18,12 +18,12 @@ import ( "github.com/oklog/ulid" "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/dstotijn/hetty/pkg/filter" "github.com/dstotijn/hetty/pkg/proj" "github.com/dstotijn/hetty/pkg/proxy" "github.com/dstotijn/hetty/pkg/proxy/intercept" "github.com/dstotijn/hetty/pkg/reqlog" "github.com/dstotijn/hetty/pkg/scope" - "github.com/dstotijn/hetty/pkg/search" "github.com/dstotijn/hetty/pkg/sender" ) @@ -639,7 +639,7 @@ func (r *mutationResolver) UpdateInterceptSettings( } if input.RequestFilter != nil && *input.RequestFilter != "" { - expr, err := search.ParseQuery(*input.RequestFilter) + expr, err := filter.ParseQuery(*input.RequestFilter) if err != nil { return nil, fmt.Errorf("could not parse request filter: %w", err) } @@ -648,7 +648,7 @@ func (r *mutationResolver) UpdateInterceptSettings( } if input.ResponseFilter != nil && *input.ResponseFilter != "" { - expr, err := search.ParseQuery(*input.ResponseFilter) + expr, err := filter.ParseQuery(*input.ResponseFilter) if err != nil { return nil, fmt.Errorf("could not parse response filter: %w", err) } @@ -916,43 +916,43 @@ func scopeToScopeRules(rules []scope.Rule) []ScopeRule { return scopeRules } -func findRequestsFilterFromInput(input *HTTPRequestLogFilterInput) (filter reqlog.FindRequestsFilter, err error) { +func findRequestsFilterFromInput(input *HTTPRequestLogFilterInput) (findFilter reqlog.FindRequestsFilter, err error) { if input == nil { return } if input.OnlyInScope != nil { - filter.OnlyInScope = *input.OnlyInScope + findFilter.OnlyInScope = *input.OnlyInScope } if input.SearchExpression != nil && *input.SearchExpression != "" { - expr, err := search.ParseQuery(*input.SearchExpression) + expr, err := filter.ParseQuery(*input.SearchExpression) if err != nil { return reqlog.FindRequestsFilter{}, fmt.Errorf("could not parse search query: %w", err) } - filter.SearchExpr = expr + findFilter.SearchExpr = expr } return } -func findSenderRequestsFilterFromInput(input *SenderRequestFilterInput) (filter sender.FindRequestsFilter, err error) { +func findSenderRequestsFilterFromInput(input *SenderRequestFilterInput) (findFilter sender.FindRequestsFilter, err error) { if input == nil { return } if input.OnlyInScope != nil { - filter.OnlyInScope = *input.OnlyInScope + findFilter.OnlyInScope = *input.OnlyInScope } if input.SearchExpression != nil && *input.SearchExpression != "" { - expr, err := search.ParseQuery(*input.SearchExpression) + expr, err := filter.ParseQuery(*input.SearchExpression) if err != nil { return sender.FindRequestsFilter{}, fmt.Errorf("could not parse search query: %w", err) } - filter.SearchExpr = expr + findFilter.SearchExpr = expr } return diff --git a/pkg/db/badger/proj_test.go b/pkg/db/badger/proj_test.go index 9e83b2a..7918723 100644 --- a/pkg/db/badger/proj_test.go +++ b/pkg/db/badger/proj_test.go @@ -15,9 +15,9 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/oklog/ulid" + "github.com/dstotijn/hetty/pkg/filter" "github.com/dstotijn/hetty/pkg/proj" "github.com/dstotijn/hetty/pkg/scope" - "github.com/dstotijn/hetty/pkg/search" ) //nolint:gosec @@ -45,7 +45,7 @@ func TestUpsertProject(t *testing.T) { database := DatabaseFromBadgerDB(badgerDB) defer database.Close() - searchExpr, err := search.ParseQuery("foo AND bar OR NOT baz") + searchExpr, err := filter.ParseQuery("foo AND bar OR NOT baz") if err != nil { t.Fatalf("unexpected error (expected: nil, got: %v)", err) } diff --git a/pkg/search/ast.go b/pkg/filter/ast.go similarity index 71% rename from pkg/search/ast.go rename to pkg/filter/ast.go index 0e0d048..bde4c97 100644 --- a/pkg/search/ast.go +++ b/pkg/filter/ast.go @@ -1,4 +1,4 @@ -package search +package filter import ( "encoding/gob" @@ -78,8 +78,10 @@ func (rl *RegexpLiteral) UnmarshalBinary(data []byte) error { } func init() { - gob.Register(PrefixExpression{}) - gob.Register(InfixExpression{}) - gob.Register(StringLiteral{}) - gob.Register(RegexpLiteral{}) + // The `filter` package was previously named `search`. + // We use the legacy names for backwards compatibility with existing database data. + gob.RegisterName("github.com/dstotijn/hetty/pkg/search.PrefixExpression", PrefixExpression{}) + gob.RegisterName("github.com/dstotijn/hetty/pkg/search.InfixExpression", InfixExpression{}) + gob.RegisterName("github.com/dstotijn/hetty/pkg/search.StringLiteral", StringLiteral{}) + gob.RegisterName("github.com/dstotijn/hetty/pkg/search.RegexpLiteral", RegexpLiteral{}) } diff --git a/pkg/filter/ast_test.go b/pkg/filter/ast_test.go new file mode 100644 index 0000000..dd7a2cb --- /dev/null +++ b/pkg/filter/ast_test.go @@ -0,0 +1,212 @@ +package filter_test + +import ( + "regexp" + "testing" + + "github.com/dstotijn/hetty/pkg/filter" +) + +func TestExpressionString(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + expression filter.Expression + expected string + }{ + { + name: "string literal expression", + expression: filter.StringLiteral{Value: "foobar"}, + expected: `"foobar"`, + }, + { + name: "boolean expression with equal operator", + expression: filter.InfixExpression{ + Operator: filter.TokOpEq, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.StringLiteral{Value: "bar"}, + }, + expected: `("foo" = "bar")`, + }, + { + name: "boolean expression with not equal operator", + expression: filter.InfixExpression{ + Operator: filter.TokOpNotEq, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.StringLiteral{Value: "bar"}, + }, + expected: `("foo" != "bar")`, + }, + { + name: "boolean expression with greater than operator", + expression: filter.InfixExpression{ + Operator: filter.TokOpGt, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.StringLiteral{Value: "bar"}, + }, + expected: `("foo" > "bar")`, + }, + { + name: "boolean expression with less than operator", + expression: filter.InfixExpression{ + Operator: filter.TokOpLt, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.StringLiteral{Value: "bar"}, + }, + expected: `("foo" < "bar")`, + }, + { + name: "boolean expression with greater than or equal operator", + expression: filter.InfixExpression{ + Operator: filter.TokOpGtEq, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.StringLiteral{Value: "bar"}, + }, + expected: `("foo" >= "bar")`, + }, + { + name: "boolean expression with less than or equal operator", + expression: filter.InfixExpression{ + Operator: filter.TokOpLtEq, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.StringLiteral{Value: "bar"}, + }, + expected: `("foo" <= "bar")`, + }, + { + name: "boolean expression with regular expression operator", + expression: filter.InfixExpression{ + Operator: filter.TokOpRe, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.RegexpLiteral{regexp.MustCompile("bar")}, + }, + expected: `("foo" =~ "bar")`, + }, + { + name: "boolean expression with not regular expression operator", + expression: filter.InfixExpression{ + Operator: filter.TokOpNotRe, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.RegexpLiteral{regexp.MustCompile("bar")}, + }, + expected: `("foo" !~ "bar")`, + }, + { + name: "boolean expression with AND, OR and NOT operators", + expression: filter.InfixExpression{ + Operator: filter.TokOpAnd, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.InfixExpression{ + Operator: filter.TokOpOr, + Left: filter.StringLiteral{Value: "bar"}, + Right: filter.PrefixExpression{ + Operator: filter.TokOpNot, + Right: filter.StringLiteral{Value: "baz"}, + }, + }, + }, + expected: `("foo" AND ("bar" OR (NOT "baz")))`, + }, + { + name: "boolean expression with nested group", + expression: filter.InfixExpression{ + Operator: filter.TokOpOr, + Left: filter.InfixExpression{ + Operator: filter.TokOpAnd, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.StringLiteral{Value: "bar"}, + }, + Right: filter.PrefixExpression{ + Operator: filter.TokOpNot, + Right: filter.StringLiteral{Value: "baz"}, + }, + }, + expected: `(("foo" AND "bar") OR (NOT "baz"))`, + }, + { + name: "implicit boolean expression with string literal operands", + expression: filter.InfixExpression{ + Operator: filter.TokOpAnd, + Left: filter.InfixExpression{ + Operator: filter.TokOpAnd, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.StringLiteral{Value: "bar"}, + }, + Right: filter.StringLiteral{Value: "baz"}, + }, + expected: `(("foo" AND "bar") AND "baz")`, + }, + { + name: "implicit boolean expression nested in group", + expression: filter.InfixExpression{ + Operator: filter.TokOpAnd, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.StringLiteral{Value: "bar"}, + }, + expected: `("foo" AND "bar")`, + }, + { + name: "implicit and explicit boolean expression with string literal operands", + expression: filter.InfixExpression{ + Operator: filter.TokOpAnd, + Left: filter.InfixExpression{ + Operator: filter.TokOpAnd, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.InfixExpression{ + Operator: filter.TokOpOr, + Left: filter.StringLiteral{Value: "bar"}, + Right: filter.StringLiteral{Value: "baz"}, + }, + }, + Right: filter.StringLiteral{Value: "yolo"}, + }, + expected: `(("foo" AND ("bar" OR "baz")) AND "yolo")`, + }, + { + name: "implicit boolean expression with comparison operands", + expression: filter.InfixExpression{ + Operator: filter.TokOpAnd, + Left: filter.InfixExpression{ + Operator: filter.TokOpEq, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.StringLiteral{Value: "bar"}, + }, + Right: filter.InfixExpression{ + Operator: filter.TokOpRe, + Left: filter.StringLiteral{Value: "baz"}, + Right: filter.RegexpLiteral{regexp.MustCompile("yolo")}, + }, + }, + expected: `(("foo" = "bar") AND ("baz" =~ "yolo"))`, + }, + { + name: "eq operator takes precedence over boolean ops", + expression: filter.InfixExpression{ + Operator: filter.TokOpOr, + Left: filter.InfixExpression{ + Operator: filter.TokOpEq, + Left: filter.StringLiteral{Value: "foo"}, + Right: filter.StringLiteral{Value: "bar"}, + }, + Right: filter.InfixExpression{ + Operator: filter.TokOpEq, + Left: filter.StringLiteral{Value: "baz"}, + Right: filter.StringLiteral{Value: "yolo"}, + }, + }, + expected: `(("foo" = "bar") OR ("baz" = "yolo"))`, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + got := tt.expression.String() + if tt.expected != got { + t.Errorf("expected: %v, got: %v", tt.expected, got) + } + }) + } +} diff --git a/pkg/search/http.go b/pkg/filter/http.go similarity index 83% rename from pkg/search/http.go rename to pkg/filter/http.go index 9f7e85a..4a88012 100644 --- a/pkg/search/http.go +++ b/pkg/filter/http.go @@ -1,4 +1,4 @@ -package search +package filter import ( "errors" @@ -15,7 +15,7 @@ func MatchHTTPHeaders(op TokenType, expr Expression, headers http.Header) (bool, case TokOpEq: strLiteral, ok := expr.(StringLiteral) if !ok { - return false, errors.New("search: expression must be a string literal") + return false, errors.New("filter: expression must be a string literal") } // Return `true` if at least one header (: ) is equal to the string literal. @@ -31,7 +31,7 @@ func MatchHTTPHeaders(op TokenType, expr Expression, headers http.Header) (bool, case TokOpNotEq: strLiteral, ok := expr.(StringLiteral) if !ok { - return false, errors.New("search: expression must be a string literal") + return false, errors.New("filter: expression must be a string literal") } // Return `true` if none of the headers (: ) are equal to the string literal. @@ -47,7 +47,7 @@ func MatchHTTPHeaders(op TokenType, expr Expression, headers http.Header) (bool, case TokOpRe: re, ok := expr.(RegexpLiteral) if !ok { - return false, errors.New("search: expression must be a regular expression") + return false, errors.New("filter: expression must be a regular expression") } // Return `true` if at least one header (: ) matches the regular expression. @@ -63,7 +63,7 @@ func MatchHTTPHeaders(op TokenType, expr Expression, headers http.Header) (bool, case TokOpNotRe: re, ok := expr.(RegexpLiteral) if !ok { - return false, errors.New("search: expression must be a regular expression") + return false, errors.New("filter: expression must be a regular expression") } // Return `true` if none of the headers (: ) match the regular expression. @@ -77,6 +77,6 @@ func MatchHTTPHeaders(op TokenType, expr Expression, headers http.Header) (bool, return true, nil default: - return false, fmt.Errorf("search: unsupported operator %q", op.String()) + return false, fmt.Errorf("filter: unsupported operator %q", op.String()) } } diff --git a/pkg/search/lexer.go b/pkg/filter/lexer.go similarity index 99% rename from pkg/search/lexer.go rename to pkg/filter/lexer.go index 4eb0c48..2756e76 100644 --- a/pkg/search/lexer.go +++ b/pkg/filter/lexer.go @@ -1,4 +1,4 @@ -package search +package filter import ( "fmt" diff --git a/pkg/search/lexer_test.go b/pkg/filter/lexer_test.go similarity index 99% rename from pkg/search/lexer_test.go rename to pkg/filter/lexer_test.go index c51217a..871126a 100644 --- a/pkg/search/lexer_test.go +++ b/pkg/filter/lexer_test.go @@ -1,4 +1,4 @@ -package search +package filter import "testing" diff --git a/pkg/search/parser.go b/pkg/filter/parser.go similarity index 97% rename from pkg/search/parser.go rename to pkg/filter/parser.go index 85a5bd3..89c1d97 100644 --- a/pkg/search/parser.go +++ b/pkg/filter/parser.go @@ -1,4 +1,4 @@ -package search +package filter import ( "fmt" @@ -88,7 +88,7 @@ func ParseQuery(input string) (expr Expression, err error) { p.nextToken() if p.curTokenIs(TokEOF) { - return nil, fmt.Errorf("search: unexpected EOF") + return nil, fmt.Errorf("filter: unexpected EOF") } for !p.curTokenIs(TokEOF) { @@ -96,7 +96,7 @@ func ParseQuery(input string) (expr Expression, err error) { switch { case err != nil: - return nil, fmt.Errorf("search: could not parse expression: %w", err) + return nil, fmt.Errorf("filter: could not parse expression: %w", err) case expr == nil: expr = right default: diff --git a/pkg/search/parser_test.go b/pkg/filter/parser_test.go similarity index 98% rename from pkg/search/parser_test.go rename to pkg/filter/parser_test.go index 6b538ad..0a16569 100644 --- a/pkg/search/parser_test.go +++ b/pkg/filter/parser_test.go @@ -1,4 +1,4 @@ -package search +package filter import ( "errors" @@ -20,7 +20,7 @@ func TestParseQuery(t *testing.T) { name: "empty query", input: "", expectedExpression: nil, - expectedError: errors.New("search: unexpected EOF"), + expectedError: errors.New("filter: unexpected EOF"), }, { name: "string literal expression", diff --git a/pkg/proj/proj.go b/pkg/proj/proj.go index e86a930..66654ad 100644 --- a/pkg/proj/proj.go +++ b/pkg/proj/proj.go @@ -11,10 +11,10 @@ import ( "github.com/oklog/ulid" + "github.com/dstotijn/hetty/pkg/filter" "github.com/dstotijn/hetty/pkg/proxy/intercept" "github.com/dstotijn/hetty/pkg/reqlog" "github.com/dstotijn/hetty/pkg/scope" - "github.com/dstotijn/hetty/pkg/search" "github.com/dstotijn/hetty/pkg/sender" ) @@ -59,17 +59,17 @@ type Settings struct { // Request log settings ReqLogBypassOutOfScope bool ReqLogOnlyFindInScope bool - ReqLogSearchExpr search.Expression + ReqLogSearchExpr filter.Expression // Intercept settings InterceptRequests bool InterceptResponses bool - InterceptRequestFilter search.Expression - InterceptResponseFilter search.Expression + InterceptRequestFilter filter.Expression + InterceptResponseFilter filter.Expression // Sender settings SenderOnlyFindInScope bool - SenderSearchExpr search.Expression + SenderSearchExpr filter.Expression // Scope settings ScopeRules []scope.Rule diff --git a/pkg/proxy/intercept/filter.go b/pkg/proxy/intercept/filter.go index 983ff8a..4ba868b 100644 --- a/pkg/proxy/intercept/filter.go +++ b/pkg/proxy/intercept/filter.go @@ -10,8 +10,8 @@ import ( "strconv" "strings" + "github.com/dstotijn/hetty/pkg/filter" "github.com/dstotijn/hetty/pkg/scope" - "github.com/dstotijn/hetty/pkg/search" ) //nolint:unparam @@ -68,22 +68,22 @@ var resFilterKeyFns = map[string]func(res *http.Response) (string, error){ } // MatchRequestFilter returns true if an HTTP request matches the request filter expression. -func MatchRequestFilter(req *http.Request, expr search.Expression) (bool, error) { +func MatchRequestFilter(req *http.Request, expr filter.Expression) (bool, error) { switch e := expr.(type) { - case search.PrefixExpression: + case filter.PrefixExpression: return matchReqPrefixExpr(req, e) - case search.InfixExpression: + case filter.InfixExpression: return matchReqInfixExpr(req, e) - case search.StringLiteral: + case filter.StringLiteral: return matchReqStringLiteral(req, e) default: return false, fmt.Errorf("expression type (%T) not supported", expr) } } -func matchReqPrefixExpr(req *http.Request, expr search.PrefixExpression) (bool, error) { +func matchReqPrefixExpr(req *http.Request, expr filter.PrefixExpression) (bool, error) { switch expr.Operator { - case search.TokOpNot: + case filter.TokOpNot: match, err := MatchRequestFilter(req, expr.Right) if err != nil { return false, err @@ -95,9 +95,9 @@ func matchReqPrefixExpr(req *http.Request, expr search.PrefixExpression) (bool, } } -func matchReqInfixExpr(req *http.Request, expr search.InfixExpression) (bool, error) { +func matchReqInfixExpr(req *http.Request, expr filter.InfixExpression) (bool, error) { switch expr.Operator { - case search.TokOpAnd: + case filter.TokOpAnd: left, err := MatchRequestFilter(req, expr.Left) if err != nil { return false, err @@ -109,7 +109,7 @@ func matchReqInfixExpr(req *http.Request, expr search.InfixExpression) (bool, er } return left && right, nil - case search.TokOpOr: + case filter.TokOpOr: left, err := MatchRequestFilter(req, expr.Left) if err != nil { return false, err @@ -123,7 +123,7 @@ func matchReqInfixExpr(req *http.Request, expr search.InfixExpression) (bool, er return left || right, nil } - left, ok := expr.Left.(search.StringLiteral) + left, ok := expr.Left.(filter.StringLiteral) if !ok { return false, errors.New("left operand must be a string literal") } @@ -134,7 +134,7 @@ func matchReqInfixExpr(req *http.Request, expr search.InfixExpression) (bool, er } if leftVal == "headers" { - match, err := search.MatchHTTPHeaders(expr.Operator, expr.Right, req.Header) + match, err := filter.MatchHTTPHeaders(expr.Operator, expr.Right, req.Header) if err != nil { return false, fmt.Errorf("failed to match request HTTP headers: %w", err) } @@ -142,21 +142,21 @@ func matchReqInfixExpr(req *http.Request, expr search.InfixExpression) (bool, er return match, nil } - if expr.Operator == search.TokOpRe || expr.Operator == search.TokOpNotRe { - right, ok := expr.Right.(search.RegexpLiteral) + if expr.Operator == filter.TokOpRe || expr.Operator == filter.TokOpNotRe { + right, ok := expr.Right.(filter.RegexpLiteral) if !ok { return false, errors.New("right operand must be a regular expression") } switch expr.Operator { - case search.TokOpRe: + case filter.TokOpRe: return right.MatchString(leftVal), nil - case search.TokOpNotRe: + case filter.TokOpNotRe: return !right.MatchString(leftVal), nil } } - right, ok := expr.Right.(search.StringLiteral) + right, ok := expr.Right.(filter.StringLiteral) if !ok { return false, errors.New("right operand must be a string literal") } @@ -167,20 +167,20 @@ func matchReqInfixExpr(req *http.Request, expr search.InfixExpression) (bool, er } switch expr.Operator { - case search.TokOpEq: + case filter.TokOpEq: return leftVal == rightVal, nil - case search.TokOpNotEq: + case filter.TokOpNotEq: return leftVal != rightVal, nil - case search.TokOpGt: + case filter.TokOpGt: // TODO(?) attempt to parse as int. return leftVal > rightVal, nil - case search.TokOpLt: + case filter.TokOpLt: // TODO(?) attempt to parse as int. return leftVal < rightVal, nil - case search.TokOpGtEq: + case filter.TokOpGtEq: // TODO(?) attempt to parse as int. return leftVal >= rightVal, nil - case search.TokOpLtEq: + case filter.TokOpLtEq: // TODO(?) attempt to parse as int. return leftVal <= rightVal, nil default: @@ -197,7 +197,7 @@ func getMappedStringLiteralFromReq(req *http.Request, s string) (string, error) return s, nil } -func matchReqStringLiteral(req *http.Request, strLiteral search.StringLiteral) (bool, error) { +func matchReqStringLiteral(req *http.Request, strLiteral filter.StringLiteral) (bool, error) { for _, fn := range reqFilterKeyFns { value, err := fn(req) if err != nil { @@ -268,22 +268,22 @@ func MatchRequestScope(req *http.Request, s *scope.Scope) (bool, error) { } // MatchResponseFilter returns true if an HTTP response matches the response filter expression. -func MatchResponseFilter(res *http.Response, expr search.Expression) (bool, error) { +func MatchResponseFilter(res *http.Response, expr filter.Expression) (bool, error) { switch e := expr.(type) { - case search.PrefixExpression: + case filter.PrefixExpression: return matchResPrefixExpr(res, e) - case search.InfixExpression: + case filter.InfixExpression: return matchResInfixExpr(res, e) - case search.StringLiteral: + case filter.StringLiteral: return matchResStringLiteral(res, e) default: return false, fmt.Errorf("expression type (%T) not supported", expr) } } -func matchResPrefixExpr(res *http.Response, expr search.PrefixExpression) (bool, error) { +func matchResPrefixExpr(res *http.Response, expr filter.PrefixExpression) (bool, error) { switch expr.Operator { - case search.TokOpNot: + case filter.TokOpNot: match, err := MatchResponseFilter(res, expr.Right) if err != nil { return false, err @@ -295,9 +295,9 @@ func matchResPrefixExpr(res *http.Response, expr search.PrefixExpression) (bool, } } -func matchResInfixExpr(res *http.Response, expr search.InfixExpression) (bool, error) { +func matchResInfixExpr(res *http.Response, expr filter.InfixExpression) (bool, error) { switch expr.Operator { - case search.TokOpAnd: + case filter.TokOpAnd: left, err := MatchResponseFilter(res, expr.Left) if err != nil { return false, err @@ -309,7 +309,7 @@ func matchResInfixExpr(res *http.Response, expr search.InfixExpression) (bool, e } return left && right, nil - case search.TokOpOr: + case filter.TokOpOr: left, err := MatchResponseFilter(res, expr.Left) if err != nil { return false, err @@ -323,7 +323,7 @@ func matchResInfixExpr(res *http.Response, expr search.InfixExpression) (bool, e return left || right, nil } - left, ok := expr.Left.(search.StringLiteral) + left, ok := expr.Left.(filter.StringLiteral) if !ok { return false, errors.New("left operand must be a string literal") } @@ -334,7 +334,7 @@ func matchResInfixExpr(res *http.Response, expr search.InfixExpression) (bool, e } if leftVal == "headers" { - match, err := search.MatchHTTPHeaders(expr.Operator, expr.Right, res.Header) + match, err := filter.MatchHTTPHeaders(expr.Operator, expr.Right, res.Header) if err != nil { return false, fmt.Errorf("failed to match request HTTP headers: %w", err) } @@ -342,21 +342,21 @@ func matchResInfixExpr(res *http.Response, expr search.InfixExpression) (bool, e return match, nil } - if expr.Operator == search.TokOpRe || expr.Operator == search.TokOpNotRe { - right, ok := expr.Right.(search.RegexpLiteral) + if expr.Operator == filter.TokOpRe || expr.Operator == filter.TokOpNotRe { + right, ok := expr.Right.(filter.RegexpLiteral) if !ok { return false, errors.New("right operand must be a regular expression") } switch expr.Operator { - case search.TokOpRe: + case filter.TokOpRe: return right.MatchString(leftVal), nil - case search.TokOpNotRe: + case filter.TokOpNotRe: return !right.MatchString(leftVal), nil } } - right, ok := expr.Right.(search.StringLiteral) + right, ok := expr.Right.(filter.StringLiteral) if !ok { return false, errors.New("right operand must be a string literal") } @@ -367,20 +367,20 @@ func matchResInfixExpr(res *http.Response, expr search.InfixExpression) (bool, e } switch expr.Operator { - case search.TokOpEq: + case filter.TokOpEq: return leftVal == rightVal, nil - case search.TokOpNotEq: + case filter.TokOpNotEq: return leftVal != rightVal, nil - case search.TokOpGt: + case filter.TokOpGt: // TODO(?) attempt to parse as int. return leftVal > rightVal, nil - case search.TokOpLt: + case filter.TokOpLt: // TODO(?) attempt to parse as int. return leftVal < rightVal, nil - case search.TokOpGtEq: + case filter.TokOpGtEq: // TODO(?) attempt to parse as int. return leftVal >= rightVal, nil - case search.TokOpLtEq: + case filter.TokOpLtEq: // TODO(?) attempt to parse as int. return leftVal <= rightVal, nil default: @@ -397,7 +397,7 @@ func getMappedStringLiteralFromRes(res *http.Response, s string) (string, error) return s, nil } -func matchResStringLiteral(res *http.Response, strLiteral search.StringLiteral) (bool, error) { +func matchResStringLiteral(res *http.Response, strLiteral filter.StringLiteral) (bool, error) { for _, fn := range resFilterKeyFns { value, err := fn(res) if err != nil { diff --git a/pkg/proxy/intercept/intercept.go b/pkg/proxy/intercept/intercept.go index caf2f99..3dd4ce6 100644 --- a/pkg/proxy/intercept/intercept.go +++ b/pkg/proxy/intercept/intercept.go @@ -10,9 +10,9 @@ import ( "github.com/oklog/ulid" + "github.com/dstotijn/hetty/pkg/filter" "github.com/dstotijn/hetty/pkg/log" "github.com/dstotijn/hetty/pkg/proxy" - "github.com/dstotijn/hetty/pkg/search" ) var ( @@ -56,16 +56,16 @@ type Service struct { requestsEnabled bool responsesEnabled bool - reqFilter search.Expression - resFilter search.Expression + reqFilter filter.Expression + resFilter filter.Expression } type Config struct { Logger log.Logger RequestsEnabled bool ResponsesEnabled bool - RequestFilter search.Expression - ResponseFilter search.Expression + RequestFilter filter.Expression + ResponseFilter filter.Expression } // RequestIDs implements sort.Interface. diff --git a/pkg/proxy/intercept/settings.go b/pkg/proxy/intercept/settings.go index 15bc154..77c30b7 100644 --- a/pkg/proxy/intercept/settings.go +++ b/pkg/proxy/intercept/settings.go @@ -1,10 +1,10 @@ package intercept -import "github.com/dstotijn/hetty/pkg/search" +import "github.com/dstotijn/hetty/pkg/filter" type Settings struct { RequestsEnabled bool ResponsesEnabled bool - RequestFilter search.Expression - ResponseFilter search.Expression + RequestFilter filter.Expression + ResponseFilter filter.Expression } diff --git a/pkg/reqlog/reqlog.go b/pkg/reqlog/reqlog.go index a348cb6..53d6047 100644 --- a/pkg/reqlog/reqlog.go +++ b/pkg/reqlog/reqlog.go @@ -12,10 +12,10 @@ import ( "github.com/oklog/ulid" + "github.com/dstotijn/hetty/pkg/filter" "github.com/dstotijn/hetty/pkg/log" "github.com/dstotijn/hetty/pkg/proxy" "github.com/dstotijn/hetty/pkg/scope" - "github.com/dstotijn/hetty/pkg/search" ) type contextKey int @@ -77,7 +77,7 @@ type service struct { type FindRequestsFilter struct { ProjectID ulid.ULID OnlyInScope bool - SearchExpr search.Expression + SearchExpr filter.Expression } type Config struct { diff --git a/pkg/reqlog/search.go b/pkg/reqlog/search.go index 673909f..5165382 100644 --- a/pkg/reqlog/search.go +++ b/pkg/reqlog/search.go @@ -8,8 +8,8 @@ import ( "github.com/oklog/ulid" + "github.com/dstotijn/hetty/pkg/filter" "github.com/dstotijn/hetty/pkg/scope" - "github.com/dstotijn/hetty/pkg/search" ) var reqLogSearchKeyFns = map[string]func(rl RequestLog) string{ @@ -36,22 +36,22 @@ var ResLogSearchKeyFns = map[string]func(rl ResponseLog) string{ // TODO: Request and response headers search key functions. // Matches returns true if the supplied search expression evaluates to true. -func (reqLog RequestLog) Matches(expr search.Expression) (bool, error) { +func (reqLog RequestLog) Matches(expr filter.Expression) (bool, error) { switch e := expr.(type) { - case search.PrefixExpression: + case filter.PrefixExpression: return reqLog.matchPrefixExpr(e) - case search.InfixExpression: + case filter.InfixExpression: return reqLog.matchInfixExpr(e) - case search.StringLiteral: + case filter.StringLiteral: return reqLog.matchStringLiteral(e) default: return false, fmt.Errorf("expression type (%T) not supported", expr) } } -func (reqLog RequestLog) matchPrefixExpr(expr search.PrefixExpression) (bool, error) { +func (reqLog RequestLog) matchPrefixExpr(expr filter.PrefixExpression) (bool, error) { switch expr.Operator { - case search.TokOpNot: + case filter.TokOpNot: match, err := reqLog.Matches(expr.Right) if err != nil { return false, err @@ -63,9 +63,9 @@ func (reqLog RequestLog) matchPrefixExpr(expr search.PrefixExpression) (bool, er } } -func (reqLog RequestLog) matchInfixExpr(expr search.InfixExpression) (bool, error) { +func (reqLog RequestLog) matchInfixExpr(expr filter.InfixExpression) (bool, error) { switch expr.Operator { - case search.TokOpAnd: + case filter.TokOpAnd: left, err := reqLog.Matches(expr.Left) if err != nil { return false, err @@ -77,7 +77,7 @@ func (reqLog RequestLog) matchInfixExpr(expr search.InfixExpression) (bool, erro } return left && right, nil - case search.TokOpOr: + case filter.TokOpOr: left, err := reqLog.Matches(expr.Left) if err != nil { return false, err @@ -91,7 +91,7 @@ func (reqLog RequestLog) matchInfixExpr(expr search.InfixExpression) (bool, erro return left || right, nil } - left, ok := expr.Left.(search.StringLiteral) + left, ok := expr.Left.(filter.StringLiteral) if !ok { return false, errors.New("left operand must be a string literal") } @@ -99,7 +99,7 @@ func (reqLog RequestLog) matchInfixExpr(expr search.InfixExpression) (bool, erro leftVal := reqLog.getMappedStringLiteral(left.Value) if leftVal == "req.headers" { - match, err := search.MatchHTTPHeaders(expr.Operator, expr.Right, reqLog.Header) + match, err := filter.MatchHTTPHeaders(expr.Operator, expr.Right, reqLog.Header) if err != nil { return false, fmt.Errorf("failed to match request HTTP headers: %w", err) } @@ -108,7 +108,7 @@ func (reqLog RequestLog) matchInfixExpr(expr search.InfixExpression) (bool, erro } if leftVal == "res.headers" && reqLog.Response != nil { - match, err := search.MatchHTTPHeaders(expr.Operator, expr.Right, reqLog.Response.Header) + match, err := filter.MatchHTTPHeaders(expr.Operator, expr.Right, reqLog.Response.Header) if err != nil { return false, fmt.Errorf("failed to match response HTTP headers: %w", err) } @@ -116,21 +116,21 @@ func (reqLog RequestLog) matchInfixExpr(expr search.InfixExpression) (bool, erro return match, nil } - if expr.Operator == search.TokOpRe || expr.Operator == search.TokOpNotRe { - right, ok := expr.Right.(search.RegexpLiteral) + if expr.Operator == filter.TokOpRe || expr.Operator == filter.TokOpNotRe { + right, ok := expr.Right.(filter.RegexpLiteral) if !ok { return false, errors.New("right operand must be a regular expression") } switch expr.Operator { - case search.TokOpRe: + case filter.TokOpRe: return right.MatchString(leftVal), nil - case search.TokOpNotRe: + case filter.TokOpNotRe: return !right.MatchString(leftVal), nil } } - right, ok := expr.Right.(search.StringLiteral) + right, ok := expr.Right.(filter.StringLiteral) if !ok { return false, errors.New("right operand must be a string literal") } @@ -138,20 +138,20 @@ func (reqLog RequestLog) matchInfixExpr(expr search.InfixExpression) (bool, erro rightVal := reqLog.getMappedStringLiteral(right.Value) switch expr.Operator { - case search.TokOpEq: + case filter.TokOpEq: return leftVal == rightVal, nil - case search.TokOpNotEq: + case filter.TokOpNotEq: return leftVal != rightVal, nil - case search.TokOpGt: + case filter.TokOpGt: // TODO(?) attempt to parse as int. return leftVal > rightVal, nil - case search.TokOpLt: + case filter.TokOpLt: // TODO(?) attempt to parse as int. return leftVal < rightVal, nil - case search.TokOpGtEq: + case filter.TokOpGtEq: // TODO(?) attempt to parse as int. return leftVal >= rightVal, nil - case search.TokOpLtEq: + case filter.TokOpLtEq: // TODO(?) attempt to parse as int. return leftVal <= rightVal, nil default: @@ -180,7 +180,7 @@ func (reqLog RequestLog) getMappedStringLiteral(s string) string { return s } -func (reqLog RequestLog) matchStringLiteral(strLiteral search.StringLiteral) (bool, error) { +func (reqLog RequestLog) matchStringLiteral(strLiteral filter.StringLiteral) (bool, error) { for _, fn := range reqLogSearchKeyFns { if strings.Contains( strings.ToLower(fn(reqLog)), diff --git a/pkg/reqlog/search_test.go b/pkg/reqlog/search_test.go index a781c50..ae14c9f 100644 --- a/pkg/reqlog/search_test.go +++ b/pkg/reqlog/search_test.go @@ -3,8 +3,8 @@ package reqlog_test import ( "testing" + "github.com/dstotijn/hetty/pkg/filter" "github.com/dstotijn/hetty/pkg/reqlog" - "github.com/dstotijn/hetty/pkg/search" ) func TestRequestLogMatch(t *testing.T) { @@ -176,7 +176,7 @@ func TestRequestLogMatch(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - searchExpr, err := search.ParseQuery(tt.query) + searchExpr, err := filter.ParseQuery(tt.query) assertError(t, nil, err) got, err := tt.requestLog.Matches(searchExpr) diff --git a/pkg/search/ast_test.go b/pkg/search/ast_test.go deleted file mode 100644 index e81cdd8..0000000 --- a/pkg/search/ast_test.go +++ /dev/null @@ -1,212 +0,0 @@ -package search_test - -import ( - "regexp" - "testing" - - "github.com/dstotijn/hetty/pkg/search" -) - -func TestExpressionString(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - expression search.Expression - expected string - }{ - { - name: "string literal expression", - expression: search.StringLiteral{Value: "foobar"}, - expected: `"foobar"`, - }, - { - name: "boolean expression with equal operator", - expression: search.InfixExpression{ - Operator: search.TokOpEq, - Left: search.StringLiteral{Value: "foo"}, - Right: search.StringLiteral{Value: "bar"}, - }, - expected: `("foo" = "bar")`, - }, - { - name: "boolean expression with not equal operator", - expression: search.InfixExpression{ - Operator: search.TokOpNotEq, - Left: search.StringLiteral{Value: "foo"}, - Right: search.StringLiteral{Value: "bar"}, - }, - expected: `("foo" != "bar")`, - }, - { - name: "boolean expression with greater than operator", - expression: search.InfixExpression{ - Operator: search.TokOpGt, - Left: search.StringLiteral{Value: "foo"}, - Right: search.StringLiteral{Value: "bar"}, - }, - expected: `("foo" > "bar")`, - }, - { - name: "boolean expression with less than operator", - expression: search.InfixExpression{ - Operator: search.TokOpLt, - Left: search.StringLiteral{Value: "foo"}, - Right: search.StringLiteral{Value: "bar"}, - }, - expected: `("foo" < "bar")`, - }, - { - name: "boolean expression with greater than or equal operator", - expression: search.InfixExpression{ - Operator: search.TokOpGtEq, - Left: search.StringLiteral{Value: "foo"}, - Right: search.StringLiteral{Value: "bar"}, - }, - expected: `("foo" >= "bar")`, - }, - { - name: "boolean expression with less than or equal operator", - expression: search.InfixExpression{ - Operator: search.TokOpLtEq, - Left: search.StringLiteral{Value: "foo"}, - Right: search.StringLiteral{Value: "bar"}, - }, - expected: `("foo" <= "bar")`, - }, - { - name: "boolean expression with regular expression operator", - expression: search.InfixExpression{ - Operator: search.TokOpRe, - Left: search.StringLiteral{Value: "foo"}, - Right: search.RegexpLiteral{regexp.MustCompile("bar")}, - }, - expected: `("foo" =~ "bar")`, - }, - { - name: "boolean expression with not regular expression operator", - expression: search.InfixExpression{ - Operator: search.TokOpNotRe, - Left: search.StringLiteral{Value: "foo"}, - Right: search.RegexpLiteral{regexp.MustCompile("bar")}, - }, - expected: `("foo" !~ "bar")`, - }, - { - name: "boolean expression with AND, OR and NOT operators", - expression: search.InfixExpression{ - Operator: search.TokOpAnd, - Left: search.StringLiteral{Value: "foo"}, - Right: search.InfixExpression{ - Operator: search.TokOpOr, - Left: search.StringLiteral{Value: "bar"}, - Right: search.PrefixExpression{ - Operator: search.TokOpNot, - Right: search.StringLiteral{Value: "baz"}, - }, - }, - }, - expected: `("foo" AND ("bar" OR (NOT "baz")))`, - }, - { - name: "boolean expression with nested group", - expression: search.InfixExpression{ - Operator: search.TokOpOr, - Left: search.InfixExpression{ - Operator: search.TokOpAnd, - Left: search.StringLiteral{Value: "foo"}, - Right: search.StringLiteral{Value: "bar"}, - }, - Right: search.PrefixExpression{ - Operator: search.TokOpNot, - Right: search.StringLiteral{Value: "baz"}, - }, - }, - expected: `(("foo" AND "bar") OR (NOT "baz"))`, - }, - { - name: "implicit boolean expression with string literal operands", - expression: search.InfixExpression{ - Operator: search.TokOpAnd, - Left: search.InfixExpression{ - Operator: search.TokOpAnd, - Left: search.StringLiteral{Value: "foo"}, - Right: search.StringLiteral{Value: "bar"}, - }, - Right: search.StringLiteral{Value: "baz"}, - }, - expected: `(("foo" AND "bar") AND "baz")`, - }, - { - name: "implicit boolean expression nested in group", - expression: search.InfixExpression{ - Operator: search.TokOpAnd, - Left: search.StringLiteral{Value: "foo"}, - Right: search.StringLiteral{Value: "bar"}, - }, - expected: `("foo" AND "bar")`, - }, - { - name: "implicit and explicit boolean expression with string literal operands", - expression: search.InfixExpression{ - Operator: search.TokOpAnd, - Left: search.InfixExpression{ - Operator: search.TokOpAnd, - Left: search.StringLiteral{Value: "foo"}, - Right: search.InfixExpression{ - Operator: search.TokOpOr, - Left: search.StringLiteral{Value: "bar"}, - Right: search.StringLiteral{Value: "baz"}, - }, - }, - Right: search.StringLiteral{Value: "yolo"}, - }, - expected: `(("foo" AND ("bar" OR "baz")) AND "yolo")`, - }, - { - name: "implicit boolean expression with comparison operands", - expression: search.InfixExpression{ - Operator: search.TokOpAnd, - Left: search.InfixExpression{ - Operator: search.TokOpEq, - Left: search.StringLiteral{Value: "foo"}, - Right: search.StringLiteral{Value: "bar"}, - }, - Right: search.InfixExpression{ - Operator: search.TokOpRe, - Left: search.StringLiteral{Value: "baz"}, - Right: search.RegexpLiteral{regexp.MustCompile("yolo")}, - }, - }, - expected: `(("foo" = "bar") AND ("baz" =~ "yolo"))`, - }, - { - name: "eq operator takes precedence over boolean ops", - expression: search.InfixExpression{ - Operator: search.TokOpOr, - Left: search.InfixExpression{ - Operator: search.TokOpEq, - Left: search.StringLiteral{Value: "foo"}, - Right: search.StringLiteral{Value: "bar"}, - }, - Right: search.InfixExpression{ - Operator: search.TokOpEq, - Left: search.StringLiteral{Value: "baz"}, - Right: search.StringLiteral{Value: "yolo"}, - }, - }, - expected: `(("foo" = "bar") OR ("baz" = "yolo"))`, - }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - got := tt.expression.String() - if tt.expected != got { - t.Errorf("expected: %v, got: %v", tt.expected, got) - } - }) - } -} diff --git a/pkg/sender/search.go b/pkg/sender/search.go index ac79f9d..3538d7e 100644 --- a/pkg/sender/search.go +++ b/pkg/sender/search.go @@ -7,9 +7,9 @@ import ( "github.com/oklog/ulid" + "github.com/dstotijn/hetty/pkg/filter" "github.com/dstotijn/hetty/pkg/reqlog" "github.com/dstotijn/hetty/pkg/scope" - "github.com/dstotijn/hetty/pkg/search" ) var senderReqSearchKeyFns = map[string]func(req Request) string{ @@ -29,22 +29,22 @@ var senderReqSearchKeyFns = map[string]func(req Request) string{ // TODO: Request and response headers search key functions. // Matches returns true if the supplied search expression evaluates to true. -func (req Request) Matches(expr search.Expression) (bool, error) { +func (req Request) Matches(expr filter.Expression) (bool, error) { switch e := expr.(type) { - case search.PrefixExpression: + case filter.PrefixExpression: return req.matchPrefixExpr(e) - case search.InfixExpression: + case filter.InfixExpression: return req.matchInfixExpr(e) - case search.StringLiteral: + case filter.StringLiteral: return req.matchStringLiteral(e) default: return false, fmt.Errorf("expression type (%T) not supported", expr) } } -func (req Request) matchPrefixExpr(expr search.PrefixExpression) (bool, error) { +func (req Request) matchPrefixExpr(expr filter.PrefixExpression) (bool, error) { switch expr.Operator { - case search.TokOpNot: + case filter.TokOpNot: match, err := req.Matches(expr.Right) if err != nil { return false, err @@ -56,9 +56,9 @@ func (req Request) matchPrefixExpr(expr search.PrefixExpression) (bool, error) { } } -func (req Request) matchInfixExpr(expr search.InfixExpression) (bool, error) { +func (req Request) matchInfixExpr(expr filter.InfixExpression) (bool, error) { switch expr.Operator { - case search.TokOpAnd: + case filter.TokOpAnd: left, err := req.Matches(expr.Left) if err != nil { return false, err @@ -70,7 +70,7 @@ func (req Request) matchInfixExpr(expr search.InfixExpression) (bool, error) { } return left && right, nil - case search.TokOpOr: + case filter.TokOpOr: left, err := req.Matches(expr.Left) if err != nil { return false, err @@ -84,7 +84,7 @@ func (req Request) matchInfixExpr(expr search.InfixExpression) (bool, error) { return left || right, nil } - left, ok := expr.Left.(search.StringLiteral) + left, ok := expr.Left.(filter.StringLiteral) if !ok { return false, errors.New("left operand must be a string literal") } @@ -92,7 +92,7 @@ func (req Request) matchInfixExpr(expr search.InfixExpression) (bool, error) { leftVal := req.getMappedStringLiteral(left.Value) if leftVal == "req.headers" { - match, err := search.MatchHTTPHeaders(expr.Operator, expr.Right, req.Header) + match, err := filter.MatchHTTPHeaders(expr.Operator, expr.Right, req.Header) if err != nil { return false, fmt.Errorf("failed to match request HTTP headers: %w", err) } @@ -101,7 +101,7 @@ func (req Request) matchInfixExpr(expr search.InfixExpression) (bool, error) { } if leftVal == "res.headers" && req.Response != nil { - match, err := search.MatchHTTPHeaders(expr.Operator, expr.Right, req.Response.Header) + match, err := filter.MatchHTTPHeaders(expr.Operator, expr.Right, req.Response.Header) if err != nil { return false, fmt.Errorf("failed to match response HTTP headers: %w", err) } @@ -109,21 +109,21 @@ func (req Request) matchInfixExpr(expr search.InfixExpression) (bool, error) { return match, nil } - if expr.Operator == search.TokOpRe || expr.Operator == search.TokOpNotRe { - right, ok := expr.Right.(search.RegexpLiteral) + if expr.Operator == filter.TokOpRe || expr.Operator == filter.TokOpNotRe { + right, ok := expr.Right.(filter.RegexpLiteral) if !ok { return false, errors.New("right operand must be a regular expression") } switch expr.Operator { - case search.TokOpRe: + case filter.TokOpRe: return right.MatchString(leftVal), nil - case search.TokOpNotRe: + case filter.TokOpNotRe: return !right.MatchString(leftVal), nil } } - right, ok := expr.Right.(search.StringLiteral) + right, ok := expr.Right.(filter.StringLiteral) if !ok { return false, errors.New("right operand must be a string literal") } @@ -131,20 +131,20 @@ func (req Request) matchInfixExpr(expr search.InfixExpression) (bool, error) { rightVal := req.getMappedStringLiteral(right.Value) switch expr.Operator { - case search.TokOpEq: + case filter.TokOpEq: return leftVal == rightVal, nil - case search.TokOpNotEq: + case filter.TokOpNotEq: return leftVal != rightVal, nil - case search.TokOpGt: + case filter.TokOpGt: // TODO(?) attempt to parse as int. return leftVal > rightVal, nil - case search.TokOpLt: + case filter.TokOpLt: // TODO(?) attempt to parse as int. return leftVal < rightVal, nil - case search.TokOpGtEq: + case filter.TokOpGtEq: // TODO(?) attempt to parse as int. return leftVal >= rightVal, nil - case search.TokOpLtEq: + case filter.TokOpLtEq: // TODO(?) attempt to parse as int. return leftVal <= rightVal, nil default: @@ -173,7 +173,7 @@ func (req Request) getMappedStringLiteral(s string) string { return s } -func (req Request) matchStringLiteral(strLiteral search.StringLiteral) (bool, error) { +func (req Request) matchStringLiteral(strLiteral filter.StringLiteral) (bool, error) { for _, fn := range senderReqSearchKeyFns { if strings.Contains( strings.ToLower(fn(req)), diff --git a/pkg/sender/search_test.go b/pkg/sender/search_test.go index 646186c..d1e179f 100644 --- a/pkg/sender/search_test.go +++ b/pkg/sender/search_test.go @@ -3,8 +3,8 @@ package sender_test import ( "testing" + "github.com/dstotijn/hetty/pkg/filter" "github.com/dstotijn/hetty/pkg/reqlog" - "github.com/dstotijn/hetty/pkg/search" "github.com/dstotijn/hetty/pkg/sender" ) @@ -177,7 +177,7 @@ func TestRequestLogMatch(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - searchExpr, err := search.ParseQuery(tt.query) + searchExpr, err := filter.ParseQuery(tt.query) assertError(t, nil, err) got, err := tt.senderReq.Matches(searchExpr) diff --git a/pkg/sender/sender.go b/pkg/sender/sender.go index 8fb246f..68e7cd5 100644 --- a/pkg/sender/sender.go +++ b/pkg/sender/sender.go @@ -12,9 +12,9 @@ import ( "github.com/oklog/ulid" + "github.com/dstotijn/hetty/pkg/filter" "github.com/dstotijn/hetty/pkg/reqlog" "github.com/dstotijn/hetty/pkg/scope" - "github.com/dstotijn/hetty/pkg/search" ) //nolint:gosec @@ -54,7 +54,7 @@ type service struct { type FindRequestsFilter struct { ProjectID ulid.ULID OnlyInScope bool - SearchExpr search.Expression + SearchExpr filter.Expression } type Config struct {