@@ -6,6 +6,7 @@ package requests
66import (
77 "bytes"
88 "encoding/json"
9+ "errors"
910 "fmt"
1011 "io"
1112 "net/http"
@@ -22,7 +23,7 @@ import (
2223
2324 "github.com/pb33f/libopenapi-validator/cache"
2425 "github.com/pb33f/libopenapi-validator/config"
25- "github.com/pb33f/libopenapi-validator/errors"
26+ liberrors "github.com/pb33f/libopenapi-validator/errors"
2627 "github.com/pb33f/libopenapi-validator/helpers"
2728 "github.com/pb33f/libopenapi-validator/schema_validation"
2829 "github.com/pb33f/libopenapi-validator/strict"
@@ -133,23 +134,23 @@ func readAndResetRequestBody(request *http.Request) []byte {
133134// ValidateRequestSchema will validate a http.Request pointer against a schema.
134135// If validation fails, it will return a list of validation errors as the second return value.
135136// The schema will be stored and reused from cache if available, otherwise it will be compiled on each call.
136- func ValidateRequestSchema (input * ValidateRequestSchemaInput ) (bool , []* errors .ValidationError ) {
137+ func ValidateRequestSchema (input * ValidateRequestSchemaInput ) (bool , []* liberrors .ValidationError ) {
137138 validationOptions := config .NewValidationOptions (input .Options ... )
138- var validationErrors []* errors .ValidationError
139+ var validationErrors []* liberrors .ValidationError
139140 var renderedSchema , jsonSchema []byte
140141 var referenceSchema string
141142 var compiledSchema * jsonschema.Schema
142143 var cachedNode * yaml.Node
143144
144145 if input .Schema == nil {
145- return false , []* errors .ValidationError {{
146+ return false , []* liberrors .ValidationError {{
146147 ValidationType : helpers .RequestBodyValidation ,
147148 ValidationSubType : helpers .Schema ,
148149 Message : "schema is nil" ,
149150 Reason : "The schema to validate against is nil" ,
150151 }}
151152 } else if input .Schema .GoLow () == nil {
152- return false , []* errors .ValidationError {{
153+ return false , []* liberrors .ValidationError {{
153154 ValidationType : helpers .RequestBodyValidation ,
154155 ValidationSubType : helpers .Schema ,
155156 Message : "schema cannot be rendered" ,
@@ -177,11 +178,11 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
177178
178179 // If rendering failed (e.g., circular reference), return the render error
179180 if renderErr != nil {
180- violation := & errors .SchemaValidationFailure {
181+ violation := & liberrors .SchemaValidationFailure {
181182 Reason : renderErr .Error (),
182183 ReferenceSchema : referenceSchema ,
183184 }
184- validationErrors = append (validationErrors , & errors .ValidationError {
185+ validationErrors = append (validationErrors , & liberrors .ValidationError {
185186 ValidationType : helpers .RequestBodyValidation ,
186187 ValidationSubType : helpers .Schema ,
187188 Message : fmt .Sprintf ("%s request body for '%s' failed schema rendering" ,
@@ -190,8 +191,8 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
190191 renderErr .Error ()),
191192 SpecLine : 1 ,
192193 SpecCol : 0 ,
193- SchemaValidationErrors : []* errors .SchemaValidationFailure {violation },
194- HowToFix : errors .HowToFixInvalidRenderedSchema ,
194+ SchemaValidationErrors : []* liberrors .SchemaValidationFailure {violation },
195+ HowToFix : liberrors .HowToFixInvalidRenderedSchema ,
195196 Context : referenceSchema ,
196197 })
197198 return false , validationErrors
@@ -208,7 +209,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
208209 input .Version ,
209210 )
210211 if err != nil {
211- validationErrors = append (validationErrors , & errors .ValidationError {
212+ validationErrors = append (validationErrors , & liberrors .ValidationError {
212213 ValidationType : helpers .RequestBodyValidation ,
213214 ValidationSubType : helpers .Schema ,
214215 Message : fmt .Sprintf ("%s request body for '%s' failed schema compilation" ,
@@ -245,15 +246,15 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
245246 err := json .Unmarshal (requestBody , & decodedObj )
246247 if err != nil {
247248 // cannot decode the request body, so it's not valid
248- validationErrors = append (validationErrors , & errors .ValidationError {
249+ validationErrors = append (validationErrors , & liberrors .ValidationError {
249250 ValidationType : helpers .RequestBodyValidation ,
250251 ValidationSubType : helpers .Schema ,
251252 Message : fmt .Sprintf ("%s request body for '%s' failed to validate schema" ,
252253 request .Method , request .URL .Path ),
253254 Reason : fmt .Sprintf ("The request body cannot be decoded: %s" , err .Error ()),
254255 SpecLine : 1 ,
255256 SpecCol : 0 ,
256- HowToFix : errors .HowToFixInvalidSchema ,
257+ HowToFix : liberrors .HowToFixInvalidSchema ,
257258 Context : schema ,
258259 })
259260 return false , validationErrors
@@ -281,15 +282,15 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
281282 }
282283 }
283284
284- validationErrors = append (validationErrors , & errors .ValidationError {
285+ validationErrors = append (validationErrors , & liberrors .ValidationError {
285286 ValidationType : helpers .RequestBodyValidation ,
286287 ValidationSubType : helpers .Schema ,
287288 Message : fmt .Sprintf ("%s request body is empty for '%s'" ,
288289 request .Method , request .URL .Path ),
289290 Reason : "The request body is empty but there is a schema defined" ,
290291 SpecLine : line ,
291292 SpecCol : col ,
292- HowToFix : errors .HowToFixInvalidSchema ,
293+ HowToFix : liberrors .HowToFixInvalidSchema ,
293294 Context : schema ,
294295 })
295296 return false , validationErrors
@@ -298,80 +299,81 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
298299 // validate the object against the schema
299300 scErrs := compiledSchema .Validate (decodedObj )
300301 if scErrs != nil {
301-
302- jk := scErrs .(* jsonschema.ValidationError )
303-
304- // flatten the validationErrors
305- schFlatErrs := jk .BasicOutput ().Errors
306- var schemaValidationErrors []* errors.SchemaValidationFailure
307-
308- // Use cached node if available, otherwise parse
309- renderedNode := cachedNode
310- if renderedNode == nil {
311- renderedNode = new (yaml.Node )
312- _ = yaml .Unmarshal (renderedSchema , renderedNode )
313- }
314- for q := range schFlatErrs {
315- er := schFlatErrs [q ]
316-
317- errMsg := er .Error .Kind .LocalizedString (message .NewPrinter (language.Tag {}))
318-
319- if er .KeywordLocation == "" || helpers .IgnoreRegex .MatchString (errMsg ) {
320- continue // ignore this error, it's useless tbh, utter noise.
302+ var jk * jsonschema.ValidationError
303+ var schemaValidationErrors []* liberrors.SchemaValidationFailure
304+
305+ if errors .As (scErrs , & jk ) {
306+ // flatten the validationErrors
307+ schFlatErrs := jk .BasicOutput ().Errors
308+
309+ // Use cached node if available, otherwise parse
310+ renderedNode := cachedNode
311+ if renderedNode == nil {
312+ renderedNode = new (yaml.Node )
313+ _ = yaml .Unmarshal (renderedSchema , renderedNode )
321314 }
322- if er .Error != nil {
315+ for q := range schFlatErrs {
316+ er := schFlatErrs [q ]
323317
324- // locate the violated property in the schema
325- var located * yaml.Node
326- if len (renderedNode .Content ) > 0 {
327- located = schema_validation .LocateSchemaPropertyNodeByJSONPath (renderedNode .Content [0 ], er .KeywordLocation )
328- }
318+ errMsg := er .Error .Kind .LocalizedString (message .NewPrinter (language.Tag {}))
329319
330- // extract the element specified by the instance
331- val := instanceLocationRegex .FindStringSubmatch (er .InstanceLocation )
332- var referenceObject string
320+ if er .KeywordLocation == "" || helpers .IgnoreRegex .MatchString (errMsg ) {
321+ continue // ignore this error, it's useless tbh, utter noise.
322+ }
323+ if er .Error != nil {
333324
334- if len (val ) > 0 {
335- referenceIndex , _ := strconv .Atoi (val [1 ])
336- if reflect .ValueOf (decodedObj ).Type ().Kind () == reflect .Slice {
337- found := decodedObj .([]any )[referenceIndex ]
338- recoded , _ := json .MarshalIndent (found , "" , " " )
339- referenceObject = string (recoded )
325+ // locate the violated property in the schema
326+ var located * yaml.Node
327+ if len (renderedNode .Content ) > 0 {
328+ located = schema_validation .LocateSchemaPropertyNodeByJSONPath (renderedNode .Content [0 ], er .KeywordLocation )
340329 }
341- }
342- if referenceObject == "" {
343- referenceObject = string (requestBody )
344- }
345330
346- errMsg := er .Error .Kind .LocalizedString (message .NewPrinter (language.Tag {}))
331+ // extract the element specified by the instance
332+ val := instanceLocationRegex .FindStringSubmatch (er .InstanceLocation )
333+ var referenceObject string
347334
348- violation := & errors.SchemaValidationFailure {
349- Reason : errMsg ,
350- FieldName : helpers .ExtractFieldNameFromStringLocation (er .InstanceLocation ),
351- FieldPath : helpers .ExtractJSONPathFromStringLocation (er .InstanceLocation ),
352- InstancePath : helpers .ConvertStringLocationToPathSegments (er .InstanceLocation ),
353- KeywordLocation : er .KeywordLocation ,
354- ReferenceSchema : referenceSchema ,
355- ReferenceObject : referenceObject ,
356- OriginalJsonSchemaError : jk ,
357- }
358- // if we have a location within the schema, add it to the error
359- if located != nil {
360-
361- line := located .Line
362- // if the located node is a map or an array, then the actual human interpretable
363- // line on which the violation occurred is the line of the key, not the value.
364- if located .Kind == yaml .MappingNode || located .Kind == yaml .SequenceNode {
365- if line > 0 {
366- line --
335+ if len (val ) > 0 {
336+ referenceIndex , _ := strconv .Atoi (val [1 ])
337+ if reflect .ValueOf (decodedObj ).Type ().Kind () == reflect .Slice {
338+ found := decodedObj .([]any )[referenceIndex ]
339+ recoded , _ := json .MarshalIndent (found , "" , " " )
340+ referenceObject = string (recoded )
367341 }
368342 }
343+ if referenceObject == "" {
344+ referenceObject = string (requestBody )
345+ }
369346
370- // location of the violation within the rendered schema.
371- violation .Line = line
372- violation .Column = located .Column
347+ errMsg := er .Error .Kind .LocalizedString (message .NewPrinter (language.Tag {}))
348+
349+ violation := & liberrors.SchemaValidationFailure {
350+ Reason : errMsg ,
351+ FieldName : helpers .ExtractFieldNameFromStringLocation (er .InstanceLocation ),
352+ FieldPath : helpers .ExtractJSONPathFromStringLocation (er .InstanceLocation ),
353+ InstancePath : helpers .ConvertStringLocationToPathSegments (er .InstanceLocation ),
354+ KeywordLocation : er .KeywordLocation ,
355+ ReferenceSchema : referenceSchema ,
356+ ReferenceObject : referenceObject ,
357+ OriginalJsonSchemaError : jk ,
358+ }
359+ // if we have a location within the schema, add it to the error
360+ if located != nil {
361+
362+ line := located .Line
363+ // if the located node is a map or an array, then the actual human interpretable
364+ // line on which the violation occurred is the line of the key, not the value.
365+ if located .Kind == yaml .MappingNode || located .Kind == yaml .SequenceNode {
366+ if line > 0 {
367+ line --
368+ }
369+ }
370+
371+ // location of the violation within the rendered schema.
372+ violation .Line = line
373+ violation .Column = located .Column
374+ }
375+ schemaValidationErrors = append (schemaValidationErrors , violation )
373376 }
374- schemaValidationErrors = append (schemaValidationErrors , violation )
375377 }
376378 }
377379
@@ -383,7 +385,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
383385 }
384386
385387 // add the error to the list
386- validationErrors = append (validationErrors , & errors .ValidationError {
388+ validationErrors = append (validationErrors , & liberrors .ValidationError {
387389 ValidationType : helpers .RequestBodyValidation ,
388390 ValidationSubType : helpers .Schema ,
389391 Message : fmt .Sprintf ("%s request body for '%s' failed to validate schema" ,
@@ -393,7 +395,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
393395 SpecLine : line ,
394396 SpecCol : col ,
395397 SchemaValidationErrors : schemaValidationErrors ,
396- HowToFix : errors .HowToFixInvalidSchema ,
398+ HowToFix : liberrors .HowToFixInvalidSchema ,
397399 Context : schema ,
398400 })
399401 }
@@ -418,14 +420,14 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
418420 switch undeclared .Type {
419421 case strict .TypeReadOnlyProperty :
420422 validationErrors = append (validationErrors ,
421- errors .ReadOnlyPropertyError (
423+ liberrors .ReadOnlyPropertyError (
422424 undeclared .Path , undeclared .Name , undeclared .Value ,
423425 request .URL .Path , request .Method ,
424426 undeclared .SpecLine , undeclared .SpecCol ,
425427 ))
426428 default :
427429 validationErrors = append (validationErrors ,
428- errors .UndeclaredPropertyError (
430+ liberrors .UndeclaredPropertyError (
429431 undeclared .Path ,
430432 undeclared .Name ,
431433 undeclared .Value ,
0 commit comments