From e8de77e8e65fd50d5350328f37524fc7ad4ee9f8 Mon Sep 17 00:00:00 2001 From: Melvin Laplanche Date: Sat, 17 Jan 2026 21:43:41 -0800 Subject: [PATCH 1/3] refactor: add more consts and use them --- errors/validation_error.go | 5 +- errors/validation_error_test.go | 17 ++--- helpers/constants.go | 76 +++++++++++---------- parameters/cookie_parameters.go | 2 +- parameters/header_parameters.go | 2 +- parameters/path_parameters.go | 4 +- parameters/query_parameters.go | 4 +- parameters/validate_security.go | 14 ++-- paths/paths.go | 8 +-- requests/validate_body.go | 4 +- responses/validate_body.go | 4 +- schema_validation/validate_document.go | 2 +- schema_validation/validate_document_test.go | 2 +- validator.go | 4 +- validator_test.go | 24 +++---- 15 files changed, 90 insertions(+), 82 deletions(-) diff --git a/errors/validation_error.go b/errors/validation_error.go index 4c590ae..ec273d6 100644 --- a/errors/validation_error.go +++ b/errors/validation_error.go @@ -6,6 +6,7 @@ package errors import ( "fmt" + "github.com/pb33f/libopenapi-validator/helpers" "github.com/santhosh-tekuri/jsonschema/v6" ) @@ -128,10 +129,10 @@ func (v *ValidationError) Error() string { // IsPathMissingError returns true if the error has a ValidationType of "path" and a ValidationSubType of "missing" func (v *ValidationError) IsPathMissingError() bool { - return v.ValidationType == "path" && v.ValidationSubType == "missing" + return v.ValidationType == helpers.PathValidation && v.ValidationSubType == helpers.ValidationMissing } // IsOperationMissingError returns true if the error has a ValidationType of "request" and a ValidationSubType of "missingOperation" func (v *ValidationError) IsOperationMissingError() bool { - return v.ValidationType == "path" && v.ValidationSubType == "missingOperation" + return v.ValidationType == helpers.PathValidation && v.ValidationSubType == helpers.ValidationMissingOperation } diff --git a/errors/validation_error_test.go b/errors/validation_error_test.go index 749dedf..f7e8ebd 100644 --- a/errors/validation_error_test.go +++ b/errors/validation_error_test.go @@ -7,6 +7,7 @@ import ( "fmt" "testing" + "github.com/pb33f/libopenapi-validator/helpers" "github.com/stretchr/testify/require" ) @@ -82,8 +83,8 @@ func TestValidationError_Error_WithSchemaValidationErrors_AndSpecLineColumn(t *t func TestValidationError_IsPathMissingError(t *testing.T) { // Test the IsPathMissingError method v := &ValidationError{ - ValidationType: "path", - ValidationSubType: "missing", + ValidationType: helpers.PathValidation, + ValidationSubType: helpers.ValidationMissing, } require.True(t, v.IsPathMissingError()) @@ -93,16 +94,16 @@ func TestValidationError_IsPathMissingError(t *testing.T) { require.False(t, v.IsPathMissingError()) // Test with different ValidationType - v.ValidationType = "request" - v.ValidationSubType = "missing" + v.ValidationType = helpers.RequestValidation + v.ValidationSubType = helpers.ValidationMissing require.False(t, v.IsPathMissingError()) } func TestValidationError_IsOperationMissingError(t *testing.T) { // Test the IsOperationMissingError method v := &ValidationError{ - ValidationType: "path", - ValidationSubType: "missingOperation", + ValidationType: helpers.PathValidation, + ValidationSubType: helpers.ValidationMissingOperation, } require.True(t, v.IsOperationMissingError()) @@ -112,7 +113,7 @@ func TestValidationError_IsOperationMissingError(t *testing.T) { require.False(t, v.IsOperationMissingError()) // Test with different ValidationType - v.ValidationType = "request" - v.ValidationSubType = "missingOperation" + v.ValidationType = helpers.RequestValidation + v.ValidationSubType = helpers.ValidationMissingOperation require.False(t, v.IsOperationMissingError()) } diff --git a/helpers/constants.go b/helpers/constants.go index 91c623f..1faecff 100644 --- a/helpers/constants.go +++ b/helpers/constants.go @@ -14,39 +14,45 @@ const ( Schema = "schema" ResponseBodyValidation = "response" RequestBodyContentType = "contentType" - RequestMissingOperation = "missingOperation" - ResponseBodyResponseCode = "statusCode" - SpaceDelimited = "spaceDelimited" - PipeDelimited = "pipeDelimited" - DefaultDelimited = "default" - MatrixStyle = "matrix" - LabelStyle = "label" - Pipe = "|" - Comma = "," - Space = " " - SemiColon = ";" - Asterisk = "*" - Period = "." - Equals = "=" - Integer = "integer" - Number = "number" - Slash = "/" - Object = "object" - String = "string" - Array = "array" - Boolean = "boolean" - DeepObject = "deepObject" - Header = "header" - Cookie = "cookie" - Path = "path" - Form = "form" - Query = "query" - JSONContentType = "application/json" - JSONType = "json" - ContentTypeHeader = "Content-Type" - AuthorizationHeader = "Authorization" - Charset = "charset" - Boundary = "boundary" - Preferred = "preferred" - FailSegment = "**&&FAIL&&**" + // Deprecated: use ValidationMissingOperation + RequestMissingOperation = "missingOperation" + PathValidation = "path" + ValidationMissing = "missing" + ValidationMissingOperation = "missingOperation" + ResponseBodyResponseCode = "statusCode" + SecurityValidation = "security" + DocumentValidation = "document" + SpaceDelimited = "spaceDelimited" + PipeDelimited = "pipeDelimited" + DefaultDelimited = "default" + MatrixStyle = "matrix" + LabelStyle = "label" + Pipe = "|" + Comma = "," + Space = " " + SemiColon = ";" + Asterisk = "*" + Period = "." + Equals = "=" + Integer = "integer" + Number = "number" + Slash = "/" + Object = "object" + String = "string" + Array = "array" + Boolean = "boolean" + DeepObject = "deepObject" + Header = "header" + Cookie = "cookie" + Path = "path" + Form = "form" + Query = "query" + JSONContentType = "application/json" + JSONType = "json" + ContentTypeHeader = "Content-Type" + AuthorizationHeader = "Authorization" + Charset = "charset" + Boundary = "boundary" + Preferred = "preferred" + FailSegment = "**&&FAIL&&**" ) diff --git a/parameters/cookie_parameters.go b/parameters/cookie_parameters.go index 1053caa..ecf2c96 100644 --- a/parameters/cookie_parameters.go +++ b/parameters/cookie_parameters.go @@ -31,7 +31,7 @@ func (v *paramValidator) ValidateCookieParamsWithPathItem(request *http.Request, if pathItem == nil { return false, []*errors.ValidationError{{ ValidationType: helpers.ParameterValidationPath, - ValidationSubType: "missing", + ValidationSubType: helpers.ValidationMissing, Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path), Reason: fmt.Sprintf("The %s request contains a path of '%s' "+ "however that path, or the %s method for that path does not exist in the specification", diff --git a/parameters/header_parameters.go b/parameters/header_parameters.go index 0dfbcc9..35438fd 100644 --- a/parameters/header_parameters.go +++ b/parameters/header_parameters.go @@ -32,7 +32,7 @@ func (v *paramValidator) ValidateHeaderParamsWithPathItem(request *http.Request, if pathItem == nil { return false, []*errors.ValidationError{{ ValidationType: helpers.ParameterValidationPath, - ValidationSubType: "missing", + ValidationSubType: helpers.ValidationMissing, Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path), Reason: fmt.Sprintf("The %s request contains a path of '%s' "+ "however that path, or the %s method for that path does not exist in the specification", diff --git a/parameters/path_parameters.go b/parameters/path_parameters.go index 31f7e3c..909b505 100644 --- a/parameters/path_parameters.go +++ b/parameters/path_parameters.go @@ -31,8 +31,8 @@ func (v *paramValidator) ValidatePathParams(request *http.Request) (bool, []*err func (v *paramValidator) ValidatePathParamsWithPathItem(request *http.Request, pathItem *v3.PathItem, pathValue string) (bool, []*errors.ValidationError) { if pathItem == nil { return false, []*errors.ValidationError{{ - ValidationType: helpers.ParameterValidationPath, - ValidationSubType: "missing", + ValidationType: helpers.PathValidation, + ValidationSubType: helpers.ValidationMissing, Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path), Reason: fmt.Sprintf("The %s request contains a path of '%s' "+ "however that path, or the %s method for that path does not exist in the specification", diff --git a/parameters/query_parameters.go b/parameters/query_parameters.go index 10111ac..f670f57 100644 --- a/parameters/query_parameters.go +++ b/parameters/query_parameters.go @@ -37,8 +37,8 @@ func (v *paramValidator) ValidateQueryParams(request *http.Request) (bool, []*er func (v *paramValidator) ValidateQueryParamsWithPathItem(request *http.Request, pathItem *v3.PathItem, pathValue string) (bool, []*errors.ValidationError) { if pathItem == nil { return false, []*errors.ValidationError{{ - ValidationType: helpers.ParameterValidationPath, - ValidationSubType: "missing", + ValidationType: helpers.PathValidation, + ValidationSubType: helpers.ValidationMissing, Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path), Reason: fmt.Sprintf("The %s request contains a path of '%s' "+ "however that path, or the %s method for that path does not exist in the specification", diff --git a/parameters/validate_security.go b/parameters/validate_security.go index 084f042..e5ce098 100644 --- a/parameters/validate_security.go +++ b/parameters/validate_security.go @@ -28,8 +28,8 @@ func (v *paramValidator) ValidateSecurity(request *http.Request) (bool, []*error func (v *paramValidator) ValidateSecurityWithPathItem(request *http.Request, pathItem *v3.PathItem, pathValue string) (bool, []*errors.ValidationError) { if pathItem == nil { return false, []*errors.ValidationError{{ - ValidationType: helpers.ParameterValidationPath, - ValidationSubType: "missing", + ValidationType: helpers.PathValidation, + ValidationSubType: helpers.ValidationMissing, Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path), Reason: fmt.Sprintf("The %s request contains a path of '%s' "+ "however that path, or the %s method for that path does not exist in the specification", @@ -71,7 +71,7 @@ func (v *paramValidator) ValidateSecurityWithPathItem(request *http.Request, pat Message: fmt.Sprintf("Security scheme '%s' is missing", secName), Reason: fmt.Sprintf("The security scheme '%s' is defined as being required, "+ "however it's missing from the components", secName), - ValidationType: "security", + ValidationType: helpers.SecurityValidation, SpecLine: sec.GoLow().Requirements.ValueNode.Line, SpecCol: sec.GoLow().Requirements.ValueNode.Column, HowToFix: "Add the missing security scheme to the components", @@ -131,7 +131,7 @@ func (v *paramValidator) validateHTTPSecurityScheme( { Message: fmt.Sprintf("Authorization header for '%s' scheme", secScheme.Scheme), Reason: "Authorization header was not found", - ValidationType: "security", + ValidationType: helpers.SecurityValidation, ValidationSubType: secScheme.Scheme, SpecLine: sec.GoLow().Requirements.ValueNode.Line, SpecCol: sec.GoLow().Requirements.ValueNode.Column, @@ -159,7 +159,7 @@ func (v *paramValidator) validateAPIKeySecurityScheme( { Message: fmt.Sprintf("API Key %s not found in header", secScheme.Name), Reason: "API Key not found in http header for security scheme 'apiKey' with type 'header'", - ValidationType: "security", + ValidationType: helpers.SecurityValidation, ValidationSubType: "apiKey", SpecLine: sec.GoLow().Requirements.ValueNode.Line, SpecCol: sec.GoLow().Requirements.ValueNode.Column, @@ -183,7 +183,7 @@ func (v *paramValidator) validateAPIKeySecurityScheme( { Message: fmt.Sprintf("API Key %s not found in query", secScheme.Name), Reason: "API Key not found in URL query for security scheme 'apiKey' with type 'query'", - ValidationType: "security", + ValidationType: helpers.SecurityValidation, ValidationSubType: "apiKey", SpecLine: sec.GoLow().Requirements.ValueNode.Line, SpecCol: sec.GoLow().Requirements.ValueNode.Column, @@ -207,7 +207,7 @@ func (v *paramValidator) validateAPIKeySecurityScheme( { Message: fmt.Sprintf("API Key %s not found in cookies", secScheme.Name), Reason: "API Key not found in http request cookies for security scheme 'apiKey' with type 'cookie'", - ValidationType: "security", + ValidationType: helpers.SecurityValidation, ValidationSubType: "apiKey", SpecLine: sec.GoLow().Requirements.ValueNode.Line, SpecCol: sec.GoLow().Requirements.ValueNode.Column, diff --git a/paths/paths.go b/paths/paths.go index 177f1de..d8e3806 100644 --- a/paths/paths.go +++ b/paths/paths.go @@ -70,8 +70,8 @@ func FindPath(request *http.Request, document *v3.Document, regexCache config.Re if len(candidates) == 0 { validationErrors := []*errors.ValidationError{ { - ValidationType: helpers.ParameterValidationPath, - ValidationSubType: "missing", + ValidationType: helpers.PathValidation, + ValidationSubType: helpers.ValidationMissing, Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path), Reason: fmt.Sprintf("The %s request contains a path of '%s' "+ "however that path, or the %s method for that path does not exist in the specification", @@ -93,8 +93,8 @@ func FindPath(request *http.Request, document *v3.Document, regexCache config.Re // path matches exist but none have the required method validationErrors := []*errors.ValidationError{{ - ValidationType: helpers.ParameterValidationPath, - ValidationSubType: "missingOperation", + ValidationType: helpers.PathValidation, + ValidationSubType: helpers.ValidationMissingOperation, Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path), Reason: fmt.Sprintf("The %s method for that path does not exist in the specification", request.Method), diff --git a/requests/validate_body.go b/requests/validate_body.go index 6e9c13a..e9aad70 100644 --- a/requests/validate_body.go +++ b/requests/validate_body.go @@ -27,8 +27,8 @@ func (v *requestBodyValidator) ValidateRequestBody(request *http.Request) (bool, func (v *requestBodyValidator) ValidateRequestBodyWithPathItem(request *http.Request, pathItem *v3.PathItem, pathValue string) (bool, []*errors.ValidationError) { if pathItem == nil { return false, []*errors.ValidationError{{ - ValidationType: helpers.ParameterValidationPath, - ValidationSubType: "missing", + ValidationType: helpers.PathValidation, + ValidationSubType: helpers.ValidationMissing, Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path), Reason: fmt.Sprintf("The %s request contains a path of '%s' "+ "however that path, or the %s method for that path does not exist in the specification", diff --git a/responses/validate_body.go b/responses/validate_body.go index 4d532d8..ae09b30 100644 --- a/responses/validate_body.go +++ b/responses/validate_body.go @@ -33,8 +33,8 @@ func (v *responseBodyValidator) ValidateResponseBody( func (v *responseBodyValidator) ValidateResponseBodyWithPathItem(request *http.Request, response *http.Response, pathItem *v3.PathItem, pathFound string) (bool, []*errors.ValidationError) { if pathItem == nil { return false, []*errors.ValidationError{{ - ValidationType: helpers.ParameterValidationPath, - ValidationSubType: "missing", + ValidationType: helpers.PathValidation, + ValidationSubType: helpers.ValidationMissing, Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path), Reason: fmt.Sprintf("The %s request contains a path of '%s' "+ "however that path, or the %s method for that path does not exist in the specification", diff --git a/schema_validation/validate_document.go b/schema_validation/validate_document.go index 7eb9b64..cf83a59 100644 --- a/schema_validation/validate_document.go +++ b/schema_validation/validate_document.go @@ -46,7 +46,7 @@ func ValidateOpenAPIDocument(doc libopenapi.Document, opts ...config.Option) (bo ReferenceSchema: loadedSchema, } validationErrors = append(validationErrors, &liberrors.ValidationError{ - ValidationType: "schema", + ValidationType: helpers.Schema, ValidationSubType: "compilation", Message: "OpenAPI document schema compilation failed", Reason: fmt.Sprintf("The OpenAPI schema failed to compile: %s", err.Error()), diff --git a/schema_validation/validate_document_test.go b/schema_validation/validate_document_test.go index eff930f..b3ce185 100644 --- a/schema_validation/validate_document_test.go +++ b/schema_validation/validate_document_test.go @@ -68,7 +68,7 @@ func validateOpenAPIDocumentWithMalformedSchema(loadedSchema string, decodedDocu ReferenceSchema: loadedSchema, } validationErrors = append(validationErrors, &liberrors.ValidationError{ - ValidationType: "schema", + ValidationType: helpers.Schema, ValidationSubType: "compilation", Message: "OpenAPI document schema compilation failed", Reason: fmt.Sprintf("The OpenAPI schema failed to compile: %s", err.Error()), diff --git a/validator.go b/validator.go index 29eec15..4a8e66e 100644 --- a/validator.go +++ b/validator.go @@ -124,8 +124,8 @@ func (v *validator) GetResponseBodyValidator() responses.ResponseBodyValidator { func (v *validator) ValidateDocument() (bool, []*errors.ValidationError) { if v.document == nil { return false, []*errors.ValidationError{{ - ValidationType: "document", - ValidationSubType: "missing", + ValidationType: helpers.DocumentValidation, + ValidationSubType: helpers.ValidationMissing, Message: "Document is not set", Reason: "The document cannot be validated as it is not set", SpecLine: 1, diff --git a/validator_test.go b/validator_test.go index 8e6e134..8893118 100644 --- a/validator_test.go +++ b/validator_test.go @@ -2400,25 +2400,25 @@ paths: func TestSortValidationErrors(t *testing.T) { // Create errors in random order errs := []*errors.ValidationError{ - {ValidationType: "security", Message: "API Key missing"}, - {ValidationType: "parameter", Message: "Path param invalid"}, - {ValidationType: "request", Message: "Body invalid"}, - {ValidationType: "parameter", Message: "Header missing"}, - {ValidationType: "security", Message: "Auth header missing"}, + {ValidationType: helpers.SecurityValidation, Message: "API Key missing"}, + {ValidationType: helpers.ParameterValidation, Message: "Path param invalid"}, + {ValidationType: helpers.RequestValidation, Message: "Body invalid"}, + {ValidationType: helpers.ParameterValidation, Message: "Header missing"}, + {ValidationType: helpers.SecurityValidation, Message: "Auth header missing"}, } sortValidationErrors(errs) // Verify sorted by validation type first, then by message - assert.Equal(t, "parameter", errs[0].ValidationType) + assert.Equal(t, helpers.ParameterValidation, errs[0].ValidationType) assert.Equal(t, "Header missing", errs[0].Message) - assert.Equal(t, "parameter", errs[1].ValidationType) + assert.Equal(t, helpers.ParameterValidation, errs[1].ValidationType) assert.Equal(t, "Path param invalid", errs[1].Message) - assert.Equal(t, "request", errs[2].ValidationType) + assert.Equal(t, helpers.RequestValidation, errs[2].ValidationType) assert.Equal(t, "Body invalid", errs[2].Message) - assert.Equal(t, "security", errs[3].ValidationType) + assert.Equal(t, helpers.SecurityValidation, errs[3].ValidationType) assert.Equal(t, "API Key missing", errs[3].Message) - assert.Equal(t, "security", errs[4].ValidationType) + assert.Equal(t, helpers.SecurityValidation, errs[4].ValidationType) assert.Equal(t, "Auth header missing", errs[4].Message) } @@ -2432,9 +2432,9 @@ func TestSortValidationErrors_Empty(t *testing.T) { // TestSortValidationErrors_SingleElement tests sorting single element slice func TestSortValidationErrors_SingleElement(t *testing.T) { errs := []*errors.ValidationError{ - {ValidationType: "parameter", Message: "Invalid value"}, + {ValidationType: helpers.ParameterValidation, Message: "Invalid value"}, } sortValidationErrors(errs) assert.Len(t, errs, 1) - assert.Equal(t, "parameter", errs[0].ValidationType) + assert.Equal(t, helpers.ParameterValidation, errs[0].ValidationType) } From 49b483c24522e8a3b79c0fac6d7fc4a99eaf0dfb Mon Sep 17 00:00:00 2001 From: Melvin Laplanche Date: Sat, 17 Jan 2026 22:54:56 -0800 Subject: [PATCH 2/3] fix linter: Stop using RequestMissingOperation --- errors/request_errors.go | 2 +- errors/request_errors_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/errors/request_errors.go b/errors/request_errors.go index 73c99fd..f53c2b8 100644 --- a/errors/request_errors.go +++ b/errors/request_errors.go @@ -41,7 +41,7 @@ func RequestContentTypeNotFound(op *v3.Operation, request *http.Request, specPat func OperationNotFound(pathItem *v3.PathItem, request *http.Request, method string, specPath string) *ValidationError { return &ValidationError{ ValidationType: helpers.RequestValidation, - ValidationSubType: helpers.RequestMissingOperation, + ValidationSubType: helpers.ValidationMissingOperation, Message: fmt.Sprintf("%s operation request content type '%s' does not exist", request.Method, method), Reason: fmt.Sprintf("The path was found, but there was no '%s' method found in the spec", request.Method), diff --git a/errors/request_errors_test.go b/errors/request_errors_test.go index da3a58d..47025a7 100644 --- a/errors/request_errors_test.go +++ b/errors/request_errors_test.go @@ -91,7 +91,7 @@ func TestOperationNotFound(t *testing.T) { // Validate the error require.NotNil(t, err) require.Equal(t, helpers.RequestValidation, err.ValidationType) - require.Equal(t, helpers.RequestMissingOperation, err.ValidationSubType) + require.Equal(t, helpers.ValidationMissingOperation, err.ValidationSubType) require.Contains(t, err.Message, "'PATCH' does not exist") require.Contains(t, err.Reason, "there was no 'PATCH' method found in the spec") require.Equal(t, 15, err.SpecLine) From 7f3f9076f27bcd0e0dbf28803b7b80a99c182f5f Mon Sep 17 00:00:00 2001 From: Melvin Laplanche Date: Sat, 17 Jan 2026 22:59:34 -0800 Subject: [PATCH 3/3] more ParameterValidationPath changes --- parameters/cookie_parameters.go | 2 +- parameters/header_parameters.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parameters/cookie_parameters.go b/parameters/cookie_parameters.go index ecf2c96..400b958 100644 --- a/parameters/cookie_parameters.go +++ b/parameters/cookie_parameters.go @@ -30,7 +30,7 @@ func (v *paramValidator) ValidateCookieParams(request *http.Request) (bool, []*e func (v *paramValidator) ValidateCookieParamsWithPathItem(request *http.Request, pathItem *v3.PathItem, pathValue string) (bool, []*errors.ValidationError) { if pathItem == nil { return false, []*errors.ValidationError{{ - ValidationType: helpers.ParameterValidationPath, + ValidationType: helpers.PathValidation, ValidationSubType: helpers.ValidationMissing, Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path), Reason: fmt.Sprintf("The %s request contains a path of '%s' "+ diff --git a/parameters/header_parameters.go b/parameters/header_parameters.go index 35438fd..b5dbd2b 100644 --- a/parameters/header_parameters.go +++ b/parameters/header_parameters.go @@ -31,7 +31,7 @@ func (v *paramValidator) ValidateHeaderParams(request *http.Request) (bool, []*e func (v *paramValidator) ValidateHeaderParamsWithPathItem(request *http.Request, pathItem *v3.PathItem, pathValue string) (bool, []*errors.ValidationError) { if pathItem == nil { return false, []*errors.ValidationError{{ - ValidationType: helpers.ParameterValidationPath, + ValidationType: helpers.PathValidation, ValidationSubType: helpers.ValidationMissing, Message: fmt.Sprintf("%s Path '%s' not found", request.Method, request.URL.Path), Reason: fmt.Sprintf("The %s request contains a path of '%s' "+