diff --git a/v2/pkg/operators/extractors/compile.go b/v2/pkg/operators/extractors/compile.go index e688c952..07306e20 100644 --- a/v2/pkg/operators/extractors/compile.go +++ b/v2/pkg/operators/extractors/compile.go @@ -46,5 +46,15 @@ func (e *Extractor) CompileExtractors() error { if e.Part == "" { e.Part = "body" } + + if e.CaseInsensitive { + if e.Type != "kval" { + return fmt.Errorf("case-insensitive flag is supported only for 'kval' extractors (not '%s')", e.Type) + } + for i := range e.KVal { + e.KVal[i] = strings.ToLower(e.KVal[i]) + } + } + return nil } diff --git a/v2/pkg/operators/extractors/extract.go b/v2/pkg/operators/extractors/extract.go index 72440c6e..e43ea145 100644 --- a/v2/pkg/operators/extractors/extract.go +++ b/v2/pkg/operators/extractors/extract.go @@ -34,8 +34,18 @@ func (e *Extractor) ExtractRegex(corpus string) map[string]struct{} { // ExtractKval extracts key value pairs from a data map func (e *Extractor) ExtractKval(data map[string]interface{}) map[string]struct{} { - results := make(map[string]struct{}) + if e.CaseInsensitive { + inputData := data + data = make(map[string]interface{}, len(inputData)) + for k, v := range inputData { + if s, ok := v.(string); ok { + v = strings.ToLower(s) + } + data[strings.ToLower(k)] = v + } + } + results := make(map[string]struct{}) for _, k := range e.KVal { item, ok := data[k] if !ok { diff --git a/v2/pkg/operators/extractors/extractors.go b/v2/pkg/operators/extractors/extractors.go index 5c126a27..d4b2bb3c 100644 --- a/v2/pkg/operators/extractors/extractors.go +++ b/v2/pkg/operators/extractors/extractors.go @@ -105,6 +105,13 @@ type Extractor struct { // Internal, when set to true will allow using the value extracted // in the next request for some protocols (like HTTP). Internal bool `yaml:"internal,omitempty" jsonschema:"title=mark extracted value for internal variable use,description=Internal when set to true will allow using the value extracted in the next request for some protocols"` + + // description: | + // CaseInsensitive enables case-insensitive extractions. Default is false. + // values: + // - false + // - true + CaseInsensitive bool `yaml:"case-insensitive,omitempty" jsonschema:"title=use case insensitive extract,description=use case insensitive extract"` } // ExtractorType is the type of the extractor specified diff --git a/v2/pkg/operators/matchers/compile.go b/v2/pkg/operators/matchers/compile.go index 09213e23..63b3edf5 100644 --- a/v2/pkg/operators/matchers/compile.go +++ b/v2/pkg/operators/matchers/compile.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "fmt" "regexp" + "strings" "github.com/Knetic/govaluate" @@ -60,5 +61,14 @@ func (m *Matcher) CompileMatchers() error { } else { m.condition = ORCondition } + + if m.CaseInsensitive { + if m.Type != "word" { + return fmt.Errorf("case-insensitive flag is supported only for 'word' matchers (not '%s')", m.Type) + } + for i := range m.Words { + m.Words[i] = strings.ToLower(m.Words[i]) + } + } return nil } diff --git a/v2/pkg/operators/matchers/match.go b/v2/pkg/operators/matchers/match.go index fff0055d..df71a144 100644 --- a/v2/pkg/operators/matchers/match.go +++ b/v2/pkg/operators/matchers/match.go @@ -42,6 +42,10 @@ func (m *Matcher) MatchSize(length int) bool { // MatchWords matches a word check against a corpus. func (m *Matcher) MatchWords(corpus string, dynamicValues map[string]interface{}) (bool, []string) { + if m.CaseInsensitive { + corpus = strings.ToLower(corpus) + } + var matchedWords []string // Iterate over all the words accepted as valid for i, word := range m.Words { diff --git a/v2/pkg/operators/matchers/matchers.go b/v2/pkg/operators/matchers/matchers.go index 88ee413e..594a6fc1 100644 --- a/v2/pkg/operators/matchers/matchers.go +++ b/v2/pkg/operators/matchers/matchers.go @@ -105,6 +105,12 @@ type Matcher struct { // values: // - "hex" Encoding string `yaml:"encoding,omitempty" jsonschema:"title=encoding for word field,description=Optional encoding for the word fields,enum=hex"` + // description: | + // CaseInsensitive enables case-insensitive matches. Default is false. + // values: + // - false + // - true + CaseInsensitive bool `yaml:"case-insensitive,omitempty" jsonschema:"title=use case insensitive match,description=use case insensitive match"` // cached data for the compiled matcher condition ConditionType