forked from TykTechnologies/tyk
-
Notifications
You must be signed in to change notification settings - Fork 0
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 TykTechnologies#1163 Based on TykTechnologies#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": { "title": "Person", "type": "object", "properties": { "firstName": { "type": "string" }, "lastName": { "type": "string" }, "age": { "description": "Age in years", "type": "integer", "minimum": 0 } }, "required": ["firstName", "lastName"] } }] } } } }, ``` 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
e0a0edb
commit d94e7df
Showing
7 changed files
with
333 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,85 @@ | ||
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) | ||
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.