Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
asoorm committed Feb 11, 2018
1 parent 8d19a03 commit 364d4d9
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 19 deletions.
10 changes: 6 additions & 4 deletions apidef/api_definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,13 @@ type MethodTransformMeta struct {
}

type ValidatePathMeta struct {
Path string `bson:"path" json:"path"`
Method string `bson:"method" json:"method"`
ValidateWith map[string]interface{} `json:"validate_with"`
Path string `bson:"path" json:"path"`
Method string `bson:"method" json:"method"`
Schema map[string]interface{} `json:"schema"`
// TODO: Implement multi schema support
SchemaVersion string
// Allows override of default 422 Unprocessible Entity response code for validation errors.
ValidationErrorResponseCode int `bson:"validation_error_response_code" json:"validation_error_response_code"`
ErrorResponseCode int `bson:"error_response_code" json:"error_response_code"`
}

type ExtendedPathsSet struct {
Expand Down
5 changes: 4 additions & 1 deletion handler_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ type ErrorHandler struct {

// HandleError is the actual error handler and will store the error details in analytics if analytics processing is enabled.
func (e *ErrorHandler) HandleError(w http.ResponseWriter, r *http.Request, errMsg string, errCode int) {

println(errMsg)

var templateExtension string
var contentType string

Expand Down Expand Up @@ -66,7 +69,7 @@ func (e *ErrorHandler) HandleError(w http.ResponseWriter, r *http.Request, errMs

// Need to return the correct error code!
w.WriteHeader(errCode)

println("writing header", errCode)
apiError := APIError{errMsg}
tmpl.Execute(w, &apiError)

Expand Down
7 changes: 7 additions & 0 deletions middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strconv"
"time"

"github.com/gin-gonic/gin/json"
"github.com/gocraft/health"
"github.com/justinas/alice"
newrelic "github.com/newrelic/go-agent"
Expand Down Expand Up @@ -80,9 +81,15 @@ func createMiddleware(mw TykMiddleware) func(http.Handler) http.Handler {
}
err, errCode := mw.ProcessRequest(w, r, mwConf)
if err != nil {

handler := ErrorHandler{mw.Base()}
handler.HandleError(w, r, err.Error(), errCode)

meta["error"] = err.Error()

by, _ := json.Marshal(meta)
log.Println(string(by))

job.TimingKv("exec_time", time.Since(startTime).Nanoseconds(), meta)
job.TimingKv(eventName+".exec_time", time.Since(startTime).Nanoseconds(), meta)
return
Expand Down
24 changes: 16 additions & 8 deletions mw_validate_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,35 +40,43 @@ func (k *ValidateJSON) ProcessRequest(w http.ResponseWriter, r *http.Request, _
}

vPathMeta := meta.(*apidef.ValidatePathMeta)
if vPathMeta.ValidateWith == nil {
if vPathMeta.Schema == nil {
return errors.New("no schemas to validate against"), http.StatusInternalServerError
}

if vPathMeta.SchemaVersion != "" && vPathMeta.SchemaVersion != "draft-v4" {
return errors.New("unsupported schema version"), http.StatusInternalServerError
}

rCopy := copyRequest(r)
bodyBytes, err := ioutil.ReadAll(rCopy.Body)
if err != nil {
return err, http.StatusBadRequest
}
defer rCopy.Body.Close()

schema := vPathMeta.ValidateWith
schema := vPathMeta.Schema

result, err := k.validate(bodyBytes, schema)
if err != nil {
return fmt.Errorf("JSON parsing error: %v", err), http.StatusBadRequest
}

if !result.Valid() {
errStr := "payload validation failed"
for _, desc := range result.Errors() {
errStr = fmt.Sprintf("%s, %s", errStr, desc)
errStr := ""
for i, desc := range result.Errors() {
if i == 0 {
errStr = desc.String()
} else {
errStr = fmt.Sprintf("%s; %s", errStr, desc)
}
}

if vPathMeta.ValidationErrorResponseCode == 0 {
vPathMeta.ValidationErrorResponseCode = http.StatusUnprocessableEntity
if vPathMeta.ErrorResponseCode == 0 {
vPathMeta.ErrorResponseCode = http.StatusUnprocessableEntity
}

return errors.New(errStr), vPathMeta.ValidationErrorResponseCode
return errors.New(errStr), vPathMeta.ErrorResponseCode
}

return nil, http.StatusOK
Expand Down
13 changes: 7 additions & 6 deletions mw_validate_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"encoding/json"
"net/http"
"testing"

"github.com/TykTechnologies/tyk/apidef"
Expand Down Expand Up @@ -37,7 +38,7 @@ func TestValidateJSONSchema(t *testing.T) {
{
"path": "/v",
"method": "POST",
"validate_with": `+testJsonSchema+`
"schema": `+testJsonSchema+`
}
]`), &v.ExtendedPaths.ValidateJSON)
})
Expand All @@ -46,10 +47,10 @@ func TestValidateJSONSchema(t *testing.T) {
})

ts.Run(t, []test.TestCase{
{Method: "POST", Path: "/without_validation", Data: "{not_valid}", Code: 200},
{Method: "POST", Path: "/v", Data: `{"age":23}`, BodyMatch: `firstName: firstName is required, lastName: lastName is required`, Code: 422},
{Method: "POST", Path: "/v", Data: `[]`, BodyMatch: `Expected: object, given: array`, Code: 422},
{Method: "POST", Path: "/v", Data: `not_json`, Code: 400},
{Method: "POST", Path: "/v", Data: `{"age":23, "firstName": "Harry", "lastName": "Potter"}`, Code: 200},
{Method: "POST", Path: "/without_validation", Data: "{not_valid}", Code: http.StatusOK},
{Method: "POST", Path: "/v", Data: `{"age":23}`, BodyMatch: `firstName: firstName is required; lastName: lastName is required`, Code: http.StatusUnprocessableEntity},
{Method: "POST", Path: "/v", Data: `[]`, BodyMatch: `Expected: object, given: array`, Code: http.StatusUnprocessableEntity},
{Method: "POST", Path: "/v", Data: `not_json`, Code: http.StatusBadRequest},
{Method: "POST", Path: "/v", Data: `{"age":23, "firstName": "Harry", "lastName": "Potter"}`, Code: http.StatusOK},
}...)
}

0 comments on commit 364d4d9

Please sign in to comment.