Merge pull request #104 from xucong053/main

feat: support text/html extraction with regex
This commit is contained in:
debugtalk
2022-02-22 15:17:32 +08:00
committed by GitHub
2 changed files with 75 additions and 2 deletions

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"regexp"
"strings" "strings"
"testing" "testing"
@@ -85,6 +86,18 @@ type responseObject struct {
validationResults []*validationResult validationResults []*validationResult
} }
const textExtractorSubRegexp string = `(.*)`
func (v *responseObject) extractField(value string) interface{} {
var result interface{}
if strings.Contains(value, textExtractorSubRegexp) {
result = v.searchRegexp(value)
} else {
result = v.searchJmespath(value)
}
return result
}
func (v *responseObject) Extract(extractors map[string]string) map[string]interface{} { func (v *responseObject) Extract(extractors map[string]string) map[string]interface{} {
if extractors == nil { if extractors == nil {
return nil return nil
@@ -92,7 +105,7 @@ func (v *responseObject) Extract(extractors map[string]string) map[string]interf
extractMapping := make(map[string]interface{}) extractMapping := make(map[string]interface{})
for key, value := range extractors { for key, value := range extractors {
extractedValue := v.searchJmespath(value) extractedValue := v.extractField(value)
log.Info().Str("from", value).Interface("value", extractedValue).Msg("extract value") log.Info().Str("from", value).Interface("value", extractedValue).Msg("extract value")
log.Info().Str("variable", key).Interface("value", extractedValue).Msg("set variable") log.Info().Str("variable", key).Interface("value", extractedValue).Msg("set variable")
extractMapping[key] = extractedValue extractMapping[key] = extractedValue
@@ -113,7 +126,8 @@ func (v *responseObject) Validate(validators []Validator, variablesMapping map[s
return err return err
} }
} else { } else {
checkValue = v.searchJmespath(checkItem) // regExp or jmesPath
checkValue = v.extractField(checkItem)
} }
// get assert method // get assert method
@@ -179,3 +193,27 @@ func (v *responseObject) searchJmespath(expr string) interface{} {
} }
return checkValue return checkValue
} }
func (v *responseObject) searchRegexp(expr string) interface{} {
respMap, ok := v.respObjMeta.(map[string]interface{})
if !ok {
log.Error().Interface("resp", v.respObjMeta).Msg("convert respObjMeta to map failed")
return expr
}
bodyStr, ok := respMap["body"].(string)
if !ok {
log.Error().Interface("resp", respMap).Msg("convert body to string failed")
return expr
}
regexpCompile, err := regexp.Compile(expr)
if err != nil {
log.Error().Str("expr", expr).Err(err).Msg("compile expr failed")
return expr
}
match := regexpCompile.FindStringSubmatch(bodyStr)
if match != nil || len(match) > 1 {
return match[1] //return first matched result in parentheses
}
log.Error().Str("expr", expr).Msg("search regexp failed")
return expr
}

35
response_test.go Normal file
View File

@@ -0,0 +1,35 @@
package hrp
import (
"io"
"net/http"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSearchRegexp(t *testing.T) {
testText := `hrp aims to be a one-stop solution for HTTP(S) testing, covering API testing, load testing and digital experience monitoring (DEM).`
testData := []struct {
raw string
expected string
}{
{"covering (.*) testing,", "API"},
{" (.*) to", "aims"},
{"^(.*) aims", "hrp"},
{".* (.*?)$", "(DEM)."},
}
// new response object
resp := http.Response{}
resp.Body = io.NopCloser(strings.NewReader(testText))
respObj, err := newResponseObject(t, newParser(), &resp)
if err != nil {
t.Fail()
}
for _, data := range testData {
if !assert.Equal(t, data.expected, respObj.searchRegexp(data.raw)) {
t.Fail()
}
}
}