2020-04-04 00:16:27 +05:30
|
|
|
package matchers
|
|
|
|
|
|
|
|
|
|
import (
|
2020-04-21 20:50:35 +02:00
|
|
|
"encoding/hex"
|
2020-04-04 00:16:27 +05:30
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
2020-12-24 01:41:32 +05:30
|
|
|
// Match matches a generic data response again a given matcher
|
|
|
|
|
func (m *Matcher) Match(data map[string]interface{}) bool {
|
|
|
|
|
part, ok := data[m.Part]
|
|
|
|
|
if !ok {
|
|
|
|
|
return false
|
2020-04-04 00:16:27 +05:30
|
|
|
}
|
2020-12-24 01:41:32 +05:30
|
|
|
partString := part.(string)
|
2020-08-25 23:24:31 +02:00
|
|
|
|
2020-04-22 22:45:02 +02:00
|
|
|
switch m.matcherType {
|
2020-12-21 15:51:43 +05:30
|
|
|
case StatusMatcher:
|
2020-12-24 01:41:32 +05:30
|
|
|
statusCode, ok := data["status_code"]
|
|
|
|
|
if !ok {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return m.isNegative(m.matchStatusCode(statusCode.(int)))
|
2020-04-22 22:45:02 +02:00
|
|
|
case SizeMatcher:
|
2020-12-24 01:41:32 +05:30
|
|
|
return m.isNegative(m.matchSizeCode(len(partString)))
|
2020-04-22 22:45:02 +02:00
|
|
|
case WordsMatcher:
|
2020-12-24 01:41:32 +05:30
|
|
|
return m.isNegative(m.matchWords(partString))
|
2020-04-22 22:45:02 +02:00
|
|
|
case RegexMatcher:
|
2020-12-24 01:41:32 +05:30
|
|
|
return m.isNegative(m.matchRegex(partString))
|
2020-04-22 22:45:02 +02:00
|
|
|
case BinaryMatcher:
|
2020-12-24 01:41:32 +05:30
|
|
|
return m.isNegative(m.matchBinary(partString))
|
2020-04-26 23:32:58 +02:00
|
|
|
case DSLMatcher:
|
2020-12-24 01:41:32 +05:30
|
|
|
return m.isNegative(m.matchDSL(data))
|
2020-04-22 22:45:02 +02:00
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 00:16:27 +05:30
|
|
|
// matchStatusCode matches a status code check against an HTTP Response
|
|
|
|
|
func (m *Matcher) matchStatusCode(statusCode int) bool {
|
|
|
|
|
// Iterate over all the status codes accepted as valid
|
2020-04-04 00:32:03 +05:30
|
|
|
//
|
|
|
|
|
// Status codes don't support AND conditions.
|
2020-04-04 00:16:27 +05:30
|
|
|
for _, status := range m.Status {
|
|
|
|
|
// Continue if the status codes don't match
|
|
|
|
|
if statusCode != status {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2020-04-04 00:32:03 +05:30
|
|
|
// Return on the first match.
|
|
|
|
|
return true
|
2020-04-04 00:16:27 +05:30
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// matchStatusCode matches a size check against an HTTP Response
|
|
|
|
|
func (m *Matcher) matchSizeCode(length int) bool {
|
|
|
|
|
// Iterate over all the sizes accepted as valid
|
2020-04-04 00:32:03 +05:30
|
|
|
//
|
|
|
|
|
// Sizes codes don't support AND conditions.
|
2020-04-04 00:16:27 +05:30
|
|
|
for _, size := range m.Size {
|
|
|
|
|
// Continue if the size doesn't match
|
|
|
|
|
if length != size {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2020-04-04 00:32:03 +05:30
|
|
|
// Return on the first match.
|
|
|
|
|
return true
|
2020-04-04 00:16:27 +05:30
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// matchWords matches a word check against an HTTP Response/Headers.
|
|
|
|
|
func (m *Matcher) matchWords(corpus string) bool {
|
|
|
|
|
// Iterate over all the words accepted as valid
|
2020-04-04 00:32:03 +05:30
|
|
|
for i, word := range m.Words {
|
2020-04-04 00:16:27 +05:30
|
|
|
// Continue if the word doesn't match
|
2020-08-25 23:24:31 +02:00
|
|
|
if !strings.Contains(corpus, word) {
|
2020-04-04 00:16:27 +05:30
|
|
|
// If we are in an AND request and a match failed,
|
|
|
|
|
// return false as the AND condition fails on any single mismatch.
|
|
|
|
|
if m.condition == ANDCondition {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
// Continue with the flow since its an OR Condition.
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the condition was an OR, return on the first match.
|
|
|
|
|
if m.condition == ORCondition {
|
|
|
|
|
return true
|
|
|
|
|
}
|
2020-04-04 00:32:03 +05:30
|
|
|
|
|
|
|
|
// If we are at the end of the words, return with true
|
|
|
|
|
if len(m.Words)-1 == i {
|
|
|
|
|
return true
|
|
|
|
|
}
|
2020-04-04 00:16:27 +05:30
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// matchRegex matches a regex check against an HTTP Response/Headers.
|
|
|
|
|
func (m *Matcher) matchRegex(corpus string) bool {
|
|
|
|
|
// Iterate over all the regexes accepted as valid
|
2020-04-04 00:32:03 +05:30
|
|
|
for i, regex := range m.regexCompiled {
|
2020-04-04 00:16:27 +05:30
|
|
|
// Continue if the regex doesn't match
|
|
|
|
|
if !regex.MatchString(corpus) {
|
|
|
|
|
// If we are in an AND request and a match failed,
|
|
|
|
|
// return false as the AND condition fails on any single mismatch.
|
|
|
|
|
if m.condition == ANDCondition {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
// Continue with the flow since its an OR Condition.
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the condition was an OR, return on the first match.
|
|
|
|
|
if m.condition == ORCondition {
|
|
|
|
|
return true
|
|
|
|
|
}
|
2020-04-04 00:32:03 +05:30
|
|
|
|
|
|
|
|
// If we are at the end of the regex, return with true
|
|
|
|
|
if len(m.regexCompiled)-1 == i {
|
|
|
|
|
return true
|
|
|
|
|
}
|
2020-04-04 00:16:27 +05:30
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
2020-04-21 20:50:35 +02:00
|
|
|
|
|
|
|
|
// matchWords matches a word check against an HTTP Response/Headers.
|
|
|
|
|
func (m *Matcher) matchBinary(corpus string) bool {
|
|
|
|
|
// Iterate over all the words accepted as valid
|
|
|
|
|
for i, binary := range m.Binary {
|
|
|
|
|
// Continue if the word doesn't match
|
|
|
|
|
hexa, _ := hex.DecodeString(binary)
|
|
|
|
|
if !strings.Contains(corpus, string(hexa)) {
|
|
|
|
|
// If we are in an AND request and a match failed,
|
|
|
|
|
// return false as the AND condition fails on any single mismatch.
|
|
|
|
|
if m.condition == ANDCondition {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
// Continue with the flow since its an OR Condition.
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the condition was an OR, return on the first match.
|
|
|
|
|
if m.condition == ORCondition {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we are at the end of the words, return with true
|
|
|
|
|
if len(m.Binary)-1 == i {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
2020-04-26 23:32:58 +02:00
|
|
|
|
|
|
|
|
// matchDSL matches on a generic map result
|
|
|
|
|
func (m *Matcher) matchDSL(mp map[string]interface{}) bool {
|
2020-11-25 18:27:14 +01:00
|
|
|
// Iterate over all the expressions accepted as valid
|
2020-04-26 23:32:58 +02:00
|
|
|
for i, expression := range m.dslCompiled {
|
|
|
|
|
result, err := expression.Evaluate(mp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2020-08-25 23:24:31 +02:00
|
|
|
|
2020-04-26 23:32:58 +02:00
|
|
|
var bResult bool
|
|
|
|
|
bResult, ok := result.(bool)
|
|
|
|
|
|
|
|
|
|
// Continue if the regex doesn't match
|
|
|
|
|
if !ok || !bResult {
|
|
|
|
|
// If we are in an AND request and a match failed,
|
|
|
|
|
// return false as the AND condition fails on any single mismatch.
|
|
|
|
|
if m.condition == ANDCondition {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
// Continue with the flow since its an OR Condition.
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the condition was an OR, return on the first match.
|
|
|
|
|
if m.condition == ORCondition {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we are at the end of the dsl, return with true
|
|
|
|
|
if len(m.dslCompiled)-1 == i {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|