MM-10232, MM-10259: Improve error handling from invalid json (#8668)

* MM-10232: improve error handling from malformed slash command responses

Switch to json.Unmarshal, which doesn't obscure JSON parse failures like
json.Decode. The latter is primarily designed for streams of JSON, not
necessarily unmarshalling just a single object.

* rework HumanizedJsonError to expose Line and Character discretely

* MM-10259: pinpoint line and character where json config error occurs

* tweak HumanizeJsonError to accept err first
This commit is contained in:
Jesse Hallam
2018-04-26 11:19:25 -04:00
committed by GitHub
parent d3f09b54e2
commit 6d50d836f5
12 changed files with 487 additions and 109 deletions

56
utils/jsonutils/json.go Normal file
View File

@@ -0,0 +1,56 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package jsonutils
import (
"bytes"
"encoding/json"
"github.com/pkg/errors"
)
type HumanizedJsonError struct {
Err error
Line int
Character int
}
func (e *HumanizedJsonError) Error() string {
return e.Err.Error()
}
// HumanizeJsonError extracts error offsets and annotates the error with useful context
func HumanizeJsonError(err error, data []byte) error {
if syntaxError, ok := err.(*json.SyntaxError); ok {
return NewHumanizedJsonError(syntaxError, data, syntaxError.Offset)
} else if unmarshalError, ok := err.(*json.UnmarshalTypeError); ok {
return NewHumanizedJsonError(unmarshalError, data, unmarshalError.Offset)
} else {
return err
}
}
func NewHumanizedJsonError(err error, data []byte, offset int64) *HumanizedJsonError {
if err == nil {
return nil
}
if offset < 0 || offset > int64(len(data)) {
return &HumanizedJsonError{
Err: errors.Wrapf(err, "invalid offset %d", offset),
}
}
lineSep := []byte{'\n'}
line := bytes.Count(data[:offset], lineSep) + 1
lastLineOffset := bytes.LastIndex(data[:offset], lineSep)
character := int(offset) - (lastLineOffset + 1) + 1
return &HumanizedJsonError{
Line: line,
Character: character,
Err: errors.Wrapf(err, "parsing error at line %d, character %d", line, character),
}
}