github.com/Tyktechnologies/tyk@v2.9.5+incompatible/gateway/mw_validate_json.go (about) 1 package gateway 2 3 import ( 4 "errors" 5 "fmt" 6 "io/ioutil" 7 "net/http" 8 9 "github.com/TykTechnologies/gojsonschema" 10 "github.com/TykTechnologies/tyk/apidef" 11 ) 12 13 type ValidateJSON struct { 14 BaseMiddleware 15 } 16 17 func (k *ValidateJSON) Name() string { 18 return "ValidateJSON" 19 } 20 21 func (k *ValidateJSON) EnabledForSpec() bool { 22 for _, v := range k.Spec.VersionData.Versions { 23 if len(v.ExtendedPaths.ValidateJSON) > 0 { 24 return true 25 } 26 } 27 28 return false 29 } 30 31 // ProcessRequest will run any checks on the request on the way through the system, return an error to have the chain fail 32 func (k *ValidateJSON) ProcessRequest(w http.ResponseWriter, r *http.Request, _ interface{}) (error, int) { 33 34 _, versionPaths, _, _ := k.Spec.Version(r) 35 found, meta := k.Spec.CheckSpecMatchesStatus(r, versionPaths, ValidateJSONRequest) 36 if !found { 37 return nil, http.StatusOK 38 } 39 40 vPathMeta := meta.(*apidef.ValidatePathMeta) 41 if vPathMeta.Schema == nil { 42 return errors.New("no schemas to validate against"), http.StatusInternalServerError 43 } 44 45 if val, exists := vPathMeta.Schema["$schema"]; exists { 46 if val != "http://json-schema.org/draft-04/schema#" { 47 return errors.New("unsupported schema, unable to validate"), http.StatusInternalServerError 48 } 49 } 50 51 // Load input body into gojsonschema 52 bodyBytes, err := ioutil.ReadAll(r.Body) 53 if err != nil { 54 return err, http.StatusBadRequest 55 } 56 defer r.Body.Close() 57 inputLoader := gojsonschema.NewBytesLoader(bodyBytes) 58 59 // Perform validation 60 result, err := gojsonschema.Validate(vPathMeta.SchemaCache, inputLoader) 61 if err != nil { 62 return fmt.Errorf("JSON parsing error: %v", err), http.StatusBadRequest 63 } 64 65 // Handle Failure 66 if !result.Valid() { 67 if vPathMeta.ErrorResponseCode == 0 { 68 vPathMeta.ErrorResponseCode = http.StatusUnprocessableEntity 69 } 70 71 return k.formatError(result.Errors()), vPathMeta.ErrorResponseCode 72 } 73 74 // Handle Success 75 return nil, http.StatusOK 76 } 77 78 func (k *ValidateJSON) formatError(schemaErrors []gojsonschema.ResultError) error { 79 errStr := "" 80 for i, desc := range schemaErrors { 81 if i == 0 { 82 errStr = desc.String() 83 } else { 84 errStr = errStr + "; " + desc.String() 85 } 86 } 87 88 return errors.New(errStr) 89 }