Skip to content

Commit

Permalink
Bugfix-773 show better error message on JSON decoding errors
Browse files Browse the repository at this point in the history
instead of dumping entire JSON, offset, line number and column numbers are displayed
  • Loading branch information
openmohan committed Apr 14, 2019
1 parent 3fc300c commit 8b295af
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
3 changes: 2 additions & 1 deletion js/modules/k6/http/response_test.go
Expand Up @@ -178,7 +178,8 @@ func TestResponse(t *testing.T) {

t.Run("Invalid", func(t *testing.T) {
_, err := common.RunString(rt, sr(`http.request("GET", "HTTPBIN_URL/html").json();`))
assert.EqualError(t, err, "GoError: invalid character '<' looking for beginning of value")
//nolint:lll
assert.EqualError(t, err, "GoError: cannot parse json due to an error at line 1, character 2 , error: invalid character '<' looking for beginning of value")
})
})
t.Run("JsonSelector", func(t *testing.T) {
Expand Down
43 changes: 41 additions & 2 deletions lib/netext/httpext/response.go
Expand Up @@ -24,9 +24,11 @@ import (
"context"
"crypto/tls"
"encoding/json"
"fmt"
"net/http"
"net/http/httputil"

"github.com/loadimpact/k6/js/common"
"github.com/loadimpact/k6/lib"
"github.com/loadimpact/k6/lib/netext"
"github.com/pkg/errors"
Expand Down Expand Up @@ -59,6 +61,17 @@ const (
ResponseTypeNone
)

type jsonError struct {
line int
character int
err error
}

func (j jsonError) Error() string {
errMessage := "cannot parse json due to an error at line"
return fmt.Sprintf("%s %d, character %d , error: %v", errMessage, j.line, j.character, j.err)
}

// ResponseTimings is a struct to put all timings for a given HTTP response/request
type ResponseTimings struct {
Duration float64 `json:"duration"`
Expand Down Expand Up @@ -141,7 +154,6 @@ func (res *Response) JSON(selector ...string) (interface{}, error) {
}

if hasSelector {

if !res.validatedJSON {
if !gjson.ValidBytes(body) {
return nil, nil
Expand All @@ -158,11 +170,38 @@ func (res *Response) JSON(selector ...string) (interface{}, error) {
}

if err := json.Unmarshal(body, &v); err != nil {
return nil, err
switch t := err.(type) {
case *json.SyntaxError:
err = checkErrorInJSON(body, int(t.Offset), err)
default:
break
}
common.Throw(common.GetRuntime(res.GetCtx()), err)
}
res.validatedJSON = true
res.cachedJSON = v
}
return res.cachedJSON, nil
}

func checkErrorInJSON(input []byte, offset int, err error) error {
lf := '\n'
str := string(input)

// Humans tend to count from 1.
line := 1
character := 0

for i, b := range str {
if b == lf {
line++
character = 0
}
character++
if i == offset {
break
}
}

return jsonError{line: line, character: character, err: err}
}

0 comments on commit 8b295af

Please sign in to comment.