Skip to content

Commit 59d4921

Browse files
authored
Merge pull request #5 from pb33f/0.0.2
v0.0.2
2 parents e86a2da + 804f143 commit 59d4921

14 files changed

+1723
-1316
lines changed

errors/parameter_errors.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"github.com/pb33f/libopenapi-validator/helpers"
66
"github.com/pb33f/libopenapi/datamodel/high/base"
77
"github.com/pb33f/libopenapi/datamodel/high/v3"
8-
"gopkg.in/yaml.v3"
98
"net/url"
109
"strings"
1110
)
@@ -76,40 +75,40 @@ func InvalidDeepObject(param *v3.Parameter, qp *helpers.QueryParam) *ValidationE
7675

7776
func QueryParameterMissing(param *v3.Parameter) *ValidationError {
7877
return &ValidationError{
79-
Message: fmt.Sprintf("Query parameter '%s' is missing", param.Name),
78+
ValidationType: helpers.ParameterValidation,
79+
ValidationSubType: helpers.ParameterValidationQuery,
80+
Message: fmt.Sprintf("Query parameter '%s' is missing", param.Name),
8081
Reason: fmt.Sprintf("The query parameter '%s' is defined as being required, "+
8182
"however it's missing from the requests", param.Name),
8283
SpecLine: param.GoLow().Required.KeyNode.Line,
8384
SpecCol: param.GoLow().Required.KeyNode.Column,
85+
HowToFix: HowToFixMissingValue,
8486
}
8587
}
8688

8789
func HeaderParameterMissing(param *v3.Parameter) *ValidationError {
8890
return &ValidationError{
89-
Message: fmt.Sprintf("Header parameter '%s' is missing", param.Name),
91+
ValidationType: helpers.ParameterValidation,
92+
ValidationSubType: helpers.ParameterValidationHeader,
93+
Message: fmt.Sprintf("Header parameter '%s' is missing", param.Name),
9094
Reason: fmt.Sprintf("The header parameter '%s' is defined as being required, "+
9195
"however it's missing from the requests", param.Name),
9296
SpecLine: param.GoLow().Required.KeyNode.Line,
9397
SpecCol: param.GoLow().Required.KeyNode.Column,
94-
}
95-
}
96-
97-
func HeaderParameterNotDefined(paramName string, kn *yaml.Node) *ValidationError {
98-
return &ValidationError{
99-
Message: fmt.Sprintf("Header parameter '%s' is not defined", paramName),
100-
Reason: fmt.Sprintf("The header parameter '%s' is not defined as part of the specification for the operation", paramName),
101-
SpecLine: kn.Line,
102-
SpecCol: kn.Column,
98+
HowToFix: HowToFixMissingValue,
10399
}
104100
}
105101

106102
func HeaderParameterCannotBeDecoded(param *v3.Parameter, val string) *ValidationError {
107103
return &ValidationError{
108-
Message: fmt.Sprintf("Header parameter '%s' cannot be decoded", param.Name),
104+
ValidationType: helpers.ParameterValidation,
105+
ValidationSubType: helpers.ParameterValidationHeader,
106+
Message: fmt.Sprintf("Header parameter '%s' cannot be decoded", param.Name),
109107
Reason: fmt.Sprintf("The header parameter '%s' cannot be "+
110108
"extracted into an object, '%s' is malformed", param.Name, val),
111109
SpecLine: param.GoLow().Schema.Value.Schema().Type.KeyNode.Line,
112110
SpecCol: param.GoLow().Schema.Value.Schema().Type.KeyNode.Line,
111+
HowToFix: HowToFixInvalidEncoding,
113112
}
114113
}
115114

errors/parameters_howtofix.go

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,24 @@
44
package errors
55

66
const (
7-
HowToFixReservedValues string = "parameter values need to URL Encoded to ensure reserved " +
8-
"values are correctly encoded, for example: '%s'"
9-
HowToFixParamInvalidNumber string = "Convert the value '%s' into a number"
10-
HowToFixParamInvalidString string = "Convert the value '%s' into a string (cannot start with a number, or be a floating point)"
11-
HowToFixParamInvalidBoolean string = "Convert the value '%s' into a true/false value"
12-
HowToFixParamInvalidEnum string = "Instead of '%s', use one of the allowed values: '%s'"
13-
HowToFixParamInvalidFormEncode string = "Use a form style encoding for parameter values, for example: '%s'"
14-
HowToFixInvalidSchema string = "Ensure that the object being submitted, matches the schema correctly"
15-
HowToFixParamInvalidSpaceDelimitedObjectExplode string = "When using 'explode' with space delimited parameters, " +
16-
"they should be separated by spaces. For example: '%s'"
17-
HowToFixParamInvalidPipeDelimitedObjectExplode string = "When using 'explode' with pipe delimited parameters, " +
18-
"they should be separated by pipes '|'. For example: '%s'"
19-
HowToFixParamInvalidDeepObjectMultipleValues string = "There can only be a single value per property name, " +
20-
"deepObject parameters should contain the property key in square brackets next to the parameter name. For example: '%s'"
21-
HowToFixInvalidJSON string = "The JSON submitted is invalid, please check the syntax"
22-
HowToFixDecodingError = "The object can't be decoded, so make sure it's being encoded correctly according to the spec."
23-
HowToFixInvalidContentType = "The content type is invalid, Use one of the %d supported types for this operation: %s"
24-
HowToFixInvalidResponseCode = "The service is responding with a code that is not defined in the spec, fix the service!"
7+
HowToFixReservedValues string = "parameter values need to URL Encoded to ensure reserved " +
8+
"values are correctly encoded, for example: '%s'"
9+
HowToFixParamInvalidNumber string = "Convert the value '%s' into a number"
10+
HowToFixParamInvalidString string = "Convert the value '%s' into a string (cannot start with a number, or be a floating point)"
11+
HowToFixParamInvalidBoolean string = "Convert the value '%s' into a true/false value"
12+
HowToFixParamInvalidEnum string = "Instead of '%s', use one of the allowed values: '%s'"
13+
HowToFixParamInvalidFormEncode string = "Use a form style encoding for parameter values, for example: '%s'"
14+
HowToFixInvalidSchema string = "Ensure that the object being submitted, matches the schema correctly"
15+
HowToFixParamInvalidSpaceDelimitedObjectExplode string = "When using 'explode' with space delimited parameters, " +
16+
"they should be separated by spaces. For example: '%s'"
17+
HowToFixParamInvalidPipeDelimitedObjectExplode string = "When using 'explode' with pipe delimited parameters, " +
18+
"they should be separated by pipes '|'. For example: '%s'"
19+
HowToFixParamInvalidDeepObjectMultipleValues string = "There can only be a single value per property name, " +
20+
"deepObject parameters should contain the property key in square brackets next to the parameter name. For example: '%s'"
21+
HowToFixInvalidJSON string = "The JSON submitted is invalid, please check the syntax"
22+
HowToFixDecodingError = "The object can't be decoded, so make sure it's being encoded correctly according to the spec."
23+
HowToFixInvalidContentType = "The content type is invalid, Use one of the %d supported types for this operation: %s"
24+
HowToFixInvalidResponseCode = "The service is responding with a code that is not defined in the spec, fix the service!"
25+
HowToFixInvalidEncoding = "Ensure the correct encoding has been used on the object"
26+
HowToFixMissingValue = "Ensure the value has been set"
2527
)

errors/validation_error.go

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,78 +4,83 @@
44
package errors
55

66
import (
7-
"fmt"
8-
"github.com/santhosh-tekuri/jsonschema/v5"
7+
"fmt"
8+
"github.com/santhosh-tekuri/jsonschema/v5"
99
)
1010

1111
// SchemaValidationFailure is a wrapper around the jsonschema.ValidationError object, to provide a more
1212
// user-friendly way to break down what went wrong.
1313
type SchemaValidationFailure struct {
14-
// Reason is a human-readable message describing the reason for the error.
15-
Reason string `json:"reason,omitempty" yaml:"reason,omitempty"`
14+
// Reason is a human-readable message describing the reason for the error.
15+
Reason string `json:"reason,omitempty" yaml:"reason,omitempty"`
1616

17-
// Location is the XPath-like location of the validation failure
18-
Location string `json:"location,omitempty" yaml:"location,omitempty"`
17+
// Location is the XPath-like location of the validation failure
18+
Location string `json:"location,omitempty" yaml:"location,omitempty"`
1919

20-
// Line is the line number where the violation occurred. This may a local line number
21-
// if the validation is a schema (only schemas are validated locally, so the line number will be relative to
22-
// the Context object held by the ValidationError object).
23-
Line int `json:"line,omitempty" yaml:"line,omitempty"`
20+
// Line is the line number where the violation occurred. This may a local line number
21+
// if the validation is a schema (only schemas are validated locally, so the line number will be relative to
22+
// the Context object held by the ValidationError object).
23+
Line int `json:"line,omitempty" yaml:"line,omitempty"`
2424

25-
// Column is the column number where the violation occurred. This may a local column number
26-
// if the validation is a schema (only schemas are validated locally, so the column number will be relative to
27-
// the Context object held by the ValidationError object).
28-
Column int `json:"column,omitempty" yaml:"column,omitempty"`
25+
// Column is the column number where the violation occurred. This may a local column number
26+
// if the validation is a schema (only schemas are validated locally, so the column number will be relative to
27+
// the Context object held by the ValidationError object).
28+
Column int `json:"column,omitempty" yaml:"column,omitempty"`
2929

30-
// The original error object, which is a jsonschema.ValidationError object.
31-
OriginalError *jsonschema.ValidationError `json:"-" yaml:"-"`
30+
// The original error object, which is a jsonschema.ValidationError object.
31+
OriginalError *jsonschema.ValidationError `json:"-" yaml:"-"`
3232
}
3333

3434
// Error returns a string representation of the error
3535
func (s *SchemaValidationFailure) Error() string {
36-
return fmt.Sprintf("Reason: %s, Location: %s", s.Reason, s.Location)
36+
return fmt.Sprintf("Reason: %s, Location: %s", s.Reason, s.Location)
3737
}
3838

3939
// ValidationError is a struct that contains all the information about a validation error.
4040
type ValidationError struct {
4141

42-
// Message is a human-readable message describing the error.
43-
Message string `json:"message" yaml:"message"`
42+
// Message is a human-readable message describing the error.
43+
Message string `json:"message" yaml:"message"`
4444

45-
// Reason is a human-readable message describing the reason for the error.
46-
Reason string `json:"reason" yaml:"reason"`
45+
// Reason is a human-readable message describing the reason for the error.
46+
Reason string `json:"reason" yaml:"reason"`
4747

48-
// ValidationType is a string that describes the type of validation that failed.
49-
ValidationType string `json:"validationType" yaml:"validationType"`
48+
// ValidationType is a string that describes the type of validation that failed.
49+
ValidationType string `json:"validationType" yaml:"validationType"`
5050

51-
// ValidationSubType is a string that describes the subtype of validation that failed.
52-
ValidationSubType string `json:"validationSubType" yaml:"validationSubType"`
51+
// ValidationSubType is a string that describes the subtype of validation that failed.
52+
ValidationSubType string `json:"validationSubType" yaml:"validationSubType"`
5353

54-
// SpecLine is the line number in the spec where the error occurred.
55-
SpecLine int `json:"specLine" yaml:"specLine"`
54+
// SpecLine is the line number in the spec where the error occurred.
55+
SpecLine int `json:"specLine" yaml:"specLine"`
5656

57-
// SpecCol is the column number in the spec where the error occurred.
58-
SpecCol int `json:"specColumn" yaml:"specColumn"`
57+
// SpecCol is the column number in the spec where the error occurred.
58+
SpecCol int `json:"specColumn" yaml:"specColumn"`
5959

60-
// HowToFix is a human-readable message describing how to fix the error.
61-
HowToFix string `json:"howToFix" yaml:"howToFix"`
60+
// HowToFix is a human-readable message describing how to fix the error.
61+
HowToFix string `json:"howToFix" yaml:"howToFix"`
6262

63-
// SchemaValidationErrors is a slice of SchemaValidationFailure objects that describe the validation errors
64-
// This is only populated whe the validation type is against a schema.
65-
SchemaValidationErrors []*SchemaValidationFailure `json:"validationErrors,omitempty" yaml:"validationErrors,omitempty"`
63+
// SchemaValidationErrors is a slice of SchemaValidationFailure objects that describe the validation errors
64+
// This is only populated whe the validation type is against a schema.
65+
SchemaValidationErrors []*SchemaValidationFailure `json:"validationErrors,omitempty" yaml:"validationErrors,omitempty"`
6666

67-
// Context is the object that the validation error occurred on. This is usually a pointer to a schema
68-
// or a parameter object.
69-
Context interface{} `json:"-" yaml:"-"`
67+
// Context is the object that the validation error occurred on. This is usually a pointer to a schema
68+
// or a parameter object.
69+
Context interface{} `json:"-" yaml:"-"`
7070
}
7171

7272
// Error returns a string representation of the error
7373
func (v *ValidationError) Error() string {
74-
if v.SchemaValidationErrors != nil {
75-
return fmt.Sprintf("Error: %s, Reason: %s, Validation Errors: %s, Line: %d, Column: %d",
76-
v.Message, v.Reason, v.SchemaValidationErrors, v.SpecLine, v.SpecCol)
77-
} else {
78-
return fmt.Sprintf("Error: %s, Reason: %s, Line: %d, Column: %d",
79-
v.Message, v.Reason, v.SpecLine, v.SpecCol)
80-
}
74+
if v.SchemaValidationErrors != nil {
75+
return fmt.Sprintf("Error: %s, Reason: %s, Validation Errors: %s, Line: %d, Column: %d",
76+
v.Message, v.Reason, v.SchemaValidationErrors, v.SpecLine, v.SpecCol)
77+
} else {
78+
return fmt.Sprintf("Error: %s, Reason: %s, Line: %d, Column: %d",
79+
v.Message, v.Reason, v.SpecLine, v.SpecCol)
80+
}
81+
}
82+
83+
// IsPathMissingError returns true if the error has a ValidationType of "path" and a ValidationSubType of "missing"
84+
func (v *ValidationError) IsPathMissingError() bool {
85+
return v.ValidationType == "path" && v.ValidationSubType == "missing"
8186
}

requests/request_body.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package requests
55

66
import (
77
"github.com/pb33f/libopenapi-validator/errors"
8+
"github.com/pb33f/libopenapi/datamodel/high/base"
89
"github.com/pb33f/libopenapi/datamodel/high/v3"
910
"net/http"
1011
)
@@ -28,17 +29,24 @@ type RequestBodyValidator interface {
2829

2930
// NewRequestBodyValidator will create a new RequestBodyValidator from an OpenAPI 3+ document
3031
func NewRequestBodyValidator(document *v3.Document) RequestBodyValidator {
31-
return &requestBodyValidator{document: document}
32+
return &requestBodyValidator{document: document, schemaCache: make(map[[32]byte]*schemaCache)}
3233
}
3334

3435
func (v *requestBodyValidator) SetPathItem(path *v3.PathItem, pathValue string) {
3536
v.pathItem = path
3637
v.pathValue = pathValue
3738
}
3839

40+
type schemaCache struct {
41+
schema *base.Schema
42+
renderedInline []byte
43+
renderedJSON []byte
44+
}
45+
3946
type requestBodyValidator struct {
40-
document *v3.Document
41-
pathItem *v3.PathItem
42-
pathValue string
43-
errors []*errors.ValidationError
47+
document *v3.Document
48+
pathItem *v3.PathItem
49+
pathValue string
50+
errors []*errors.ValidationError
51+
schemaCache map[[32]byte]*schemaCache
4452
}

0 commit comments

Comments
 (0)