fn: json excess data check should ignore whitespace (#830)

* fn: json excess data check should ignore whitespace

* fn: adjustments and test case
This commit is contained in:
Tolga Ceylan
2018-03-09 11:59:30 -08:00
committed by GitHub
parent 4b37342ad4
commit afeb8e6f6a
2 changed files with 25 additions and 9 deletions

View File

@@ -8,6 +8,7 @@ import (
"io" "io"
"net/http" "net/http"
"sync" "sync"
"unicode"
"go.opencensus.io/trace" "go.opencensus.io/trace"
@@ -149,10 +150,19 @@ func (h *JSONProtocol) Dispatch(ctx context.Context, ci CallInfo, w io.Writer) e
func (h *JSONProtocol) isExcessData(err error, decoder *json.Decoder) error { func (h *JSONProtocol) isExcessData(err error, decoder *json.Decoder) error {
if err == nil { if err == nil {
// Now check for excess output, if this is the case, we can be certain that the next request will fail. // Now check for excess output, if this is the case, we can be certain that the next request will fail.
tmp, ok := decoder.Buffered().(*bytes.Reader) reader, ok := decoder.Buffered().(*bytes.Reader)
if ok && tmp.Len() > 0 { if ok && reader.Len() > 0 {
// Let's check if extra data is whitespace, which is valid/ignored in json
for {
r, _, err := reader.ReadRune()
if err == io.EOF {
break
}
if !unicode.IsSpace(r) {
return ErrExcessData return ErrExcessData
} }
} }
}
}
return err return err
} }

View File

@@ -186,6 +186,7 @@ func TestRouteRunnerIOPipes(t *testing.T) {
// sleep between logs and with debug enabled, fn-test-utils will log header/footer below: // sleep between logs and with debug enabled, fn-test-utils will log header/footer below:
immediateGarbage := `{"isDebug": true, "postOutGarbage": "YOGURT_YOGURT_YOGURT", "postSleepTime": 0}` immediateGarbage := `{"isDebug": true, "postOutGarbage": "YOGURT_YOGURT_YOGURT", "postSleepTime": 0}`
immediateJsonValidGarbage := `{"isDebug": true, "postOutGarbage": "\r", "postSleepTime": 0}`
delayedGarbage := `{"isDebug": true, "postOutGarbage": "YOGURT_YOGURT_YOGURT", "postSleepTime": 1000}` delayedGarbage := `{"isDebug": true, "postOutGarbage": "YOGURT_YOGURT_YOGURT", "postSleepTime": 1000}`
ok := `{"isDebug": true}` ok := `{"isDebug": true}`
@@ -203,6 +204,9 @@ func TestRouteRunnerIOPipes(t *testing.T) {
// //
// JSON WORLD // JSON WORLD
// //
// this should go through.
{"/r/zoo/json/", immediateJsonValidGarbage, "GET", http.StatusOK, "", nil, 0},
// CASE I: immediate garbage: likely to be in the json decoder buffer after json resp parsing // CASE I: immediate garbage: likely to be in the json decoder buffer after json resp parsing
{"/r/zoo/json/", immediateGarbage, "GET", http.StatusOK, "", nil, 0}, {"/r/zoo/json/", immediateGarbage, "GET", http.StatusOK, "", nil, 0},
@@ -275,20 +279,22 @@ func TestRouteRunnerIOPipes(t *testing.T) {
t.Logf("Test %d: dockerId: %v", i, containerIds[i]) t.Logf("Test %d: dockerId: %v", i, containerIds[i])
time.Sleep(test.sleepAmount) time.Sleep(test.sleepAmount)
} }
jsonIds := containerIds[0:4]
jsonIds := containerIds[0:5]
// now cross check JSON container ids: // now cross check JSON container ids:
if jsonIds[0] != jsonIds[1] && if jsonIds[1] != jsonIds[2] &&
jsonIds[2] == "N/A" && jsonIds[0] == jsonIds[1] &&
jsonIds[1] != jsonIds[2] && jsonIds[3] == "N/A" &&
jsonIds[2] != jsonIds[3] { jsonIds[2] != jsonIds[3] &&
jsonIds[3] != jsonIds[4] {
t.Logf("json container ids are OK, ids=%v", jsonIds) t.Logf("json container ids are OK, ids=%v", jsonIds)
} else { } else {
isFailure = true isFailure = true
t.Errorf("json container ids are not OK, ids=%v", jsonIds) t.Errorf("json container ids are not OK, ids=%v", jsonIds)
} }
httpids := containerIds[4:] httpids := containerIds[5:]
// now cross check HTTP container ids: // now cross check HTTP container ids:
if httpids[0] == httpids[1] && if httpids[0] == httpids[1] &&