-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds JSON Schema validation to the gateway
Fixes #1163 Based on #1180 Adds a new JSON Validation middleware that can be configured as follows: ``` "version_data": { "not_versioned": true, "versions": { "default": { "name": "default", "use_extended_paths": true, "extended_paths": { "validate_json": [{ "method": "POST", "path": "me", "validate_with": "BASE64 ENCODED SCHEMA" }] } } } }, ``` The schema must be a draft v4 JSON Schema spec. The gateway will attempt to validate the inbound request against it, if fields are failing the validation process, a detailed error response is provided for the user to fix their payload. This will require a new Dashboard UI to handle input. make Base64 Schema readable in tests removing base64 as not necessary using make for known length slice
- Loading branch information
1 parent
5eb0a31
commit 4ede633
Showing
7 changed files
with
334 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
|
||
"github.com/xeipuuv/gojsonschema" | ||
|
||
"github.com/TykTechnologies/tyk/apidef" | ||
) | ||
|
||
type ValidateJSON struct { | ||
BaseMiddleware | ||
schemaLoader gojsonschema.JSONLoader | ||
} | ||
|
||
func (k *ValidateJSON) Name() string { | ||
return "ValidateJSON" | ||
} | ||
|
||
func (k *ValidateJSON) EnabledForSpec() bool { | ||
for _, v := range k.Spec.VersionData.Versions { | ||
if len(v.ExtendedPaths.ValidateJSON) > 0 { | ||
return true | ||
} | ||
} | ||
|
||
return false | ||
} | ||
|
||
// ProcessRequest will run any checks on the request on the way through the system, return an error to have the chain fail | ||
func (k *ValidateJSON) ProcessRequest(w http.ResponseWriter, r *http.Request, _ interface{}) (error, int) { | ||
|
||
_, versionPaths, _, _ := k.Spec.Version(r) | ||
found, meta := k.Spec.CheckSpecMatchesStatus(r, versionPaths, ValidateJSONRequest) | ||
if !found { | ||
return nil, http.StatusOK | ||
} | ||
|
||
vPathMeta := meta.(*apidef.ValidatePathMeta) | ||
fmt.Printf("%T: %+v\n", vPathMeta.ValidateWith, vPathMeta.ValidateWith) | ||
if vPathMeta.ValidateWith == nil { | ||
return errors.New("no schemas to validate against"), http.StatusInternalServerError | ||
} | ||
|
||
rCopy := copyRequest(r) | ||
bodyBytes, err := ioutil.ReadAll(rCopy.Body) | ||
if err != nil { | ||
return err, http.StatusInternalServerError | ||
} | ||
defer rCopy.Body.Close() | ||
|
||
schema := vPathMeta.ValidateWith | ||
|
||
result, err := k.validate(bodyBytes, schema) | ||
if err != nil { | ||
return err, http.StatusInternalServerError | ||
} | ||
|
||
if !result.Valid() { | ||
errStr := "payload validation failed" | ||
for _, desc := range result.Errors() { | ||
errStr = fmt.Sprintf("%s, %s", errStr, desc) | ||
} | ||
|
||
if vPathMeta.ValidationErrorResponseCode == 0 { | ||
vPathMeta.ValidationErrorResponseCode = http.StatusUnprocessableEntity | ||
} | ||
|
||
return errors.New(errStr), vPathMeta.ValidationErrorResponseCode | ||
} | ||
|
||
return nil, http.StatusOK | ||
} | ||
|
||
func (k *ValidateJSON) validate(input []byte, schema map[string]interface{}) (*gojsonschema.Result, error) { | ||
inputLoader := gojsonschema.NewBytesLoader(input) | ||
|
||
if k.schemaLoader == nil { | ||
k.schemaLoader = gojsonschema.NewGoLoader(schema) | ||
} | ||
|
||
return gojsonschema.Validate(k.schemaLoader, inputLoader) | ||
} |
Oops, something went wrong.