Documentation
¶
Overview ¶
Package validator provides OpenAPI Specification (OAS) validation functionality.
This package validates OpenAPI specifications across multiple versions against their respective specification requirements. It performs structural validation, format checking, and semantic analysis to ensure API specifications are correct and conformant.
Supported Versions ¶
The validator supports all official OpenAPI Specification releases:
- OAS 2.0 (Swagger): https://spec.openapis.org/oas/v2.0.html
- OAS 3.0.x (3.0.0 through 3.0.4): https://spec.openapis.org/oas/v3.0.0.html
- OAS 3.1.x (3.1.0 through 3.1.2): https://spec.openapis.org/oas/v3.1.0.html
- OAS 3.2.0: https://spec.openapis.org/oas/v3.2.0.html
All schema definitions are validated against JSON Schema Specification Draft 2020-12: https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html
Release candidate versions (e.g., 3.0.0-rc0) are detected but not officially supported.
Features ¶
- Multi-version support: Validates OAS 2.0 through OAS 3.2.0
- Structural validation: Ensures required fields are present and properly formatted
- Format validation: Validates URLs, emails, media types, HTTP status codes
- Semantic validation: Checks operation ID uniqueness, path parameter consistency
- Schema validation: Validates JSON schemas including type constraints and nested structures
- Security validation: Validates security schemes and requirements
- Best practice warnings: Optional recommendations for better API design
- Strict mode: Additional validation beyond specification requirements
Validation Levels ¶
The validator provides two severity levels for issues:
- SeverityError: Specification violations that make the document invalid
- SeverityWarning: Best practice violations or recommendations (optional)
Warnings can be suppressed by setting IncludeWarnings to false. Strict mode can be enabled to perform additional validation beyond spec requirements.
Validation Rules ¶
The validator checks numerous aspects of OpenAPI documents:
Info Object:
- Required fields: title, version
- Format: Valid URLs for contact/license, valid email format
Paths:
- Path patterns must start with "/"
- Path templates must be well-formed (no empty braces, nested braces, etc.)
- Path parameters must be declared and match template variables
Operations:
- Operation IDs must be unique across the entire document
- HTTP status codes must be valid (100-599 or wildcard patterns like "2XX")
- Media types must follow RFC 2045/2046 format
- Request bodies must have at least one media type (OAS 3.x)
Parameters:
- Path parameters must have required: true
- Body parameters must have a schema (OAS 2.0)
- Non-body parameters must have a type (OAS 2.0)
- Parameters must have either schema or content (OAS 3.x)
Schemas:
- Array schemas must have 'items' defined
- minLength/maxLength must be consistent
- minimum/maximum must be consistent
- Required fields must exist in properties
- Enum values must match schema type
Security:
- Security requirements must reference defined security schemes
- Security schemes must have required fields for their type
- OAuth2 flows must have required URLs
Security Considerations ¶
The validator implements several protections:
- Resource limits: Maximum schema nesting depth (100) to prevent stack overflow
- Cycle detection: Prevents infinite loops in circular schema references
- Format validation: Uses standard library parsing for URLs, media types, etc.
- Input validation: All user-provided values are validated before processing
Basic Usage ¶
v := validator.New()
result, err := v.Validate("openapi.yaml")
if err != nil {
log.Fatalf("Validation failed: %v", err)
}
if !result.Valid {
fmt.Printf("Found %d error(s):\n", result.ErrorCount)
for _, err := range result.Errors {
fmt.Printf(" %s\n", err.String())
}
}
Advanced Usage ¶
Enable strict mode for additional validation:
v := validator.New()
v.StrictMode = true
v.IncludeWarnings = true
result, err := v.Validate("openapi.yaml")
if err != nil {
log.Fatalf("Validation failed: %v", err)
}
// Process errors
for _, verr := range result.Errors {
fmt.Printf("ERROR: %s at %s\n", verr.Message, verr.Path)
if verr.SpecRef != "" {
fmt.Printf(" See: %s\n", verr.SpecRef)
}
}
// Process warnings
for _, warn := range result.Warnings {
fmt.Printf("WARNING: %s at %s\n", warn.Message, warn.Path)
}
Suppress warnings for production:
v := validator.New()
v.IncludeWarnings = false
result, err := v.Validate("openapi.yaml")
if err != nil {
log.Fatalf("Validation failed: %v", err)
}
// Only errors will be reported
if !result.Valid {
log.Printf("Validation failed with %d errors", result.ErrorCount)
}
Strict Mode ¶
When StrictMode is enabled, the validator performs additional checks:
- Warns about non-standard HTTP status codes (not defined in RFCs)
- Warns if operations don't have at least one successful (2XX) response
- May add additional best practice validations in future versions
Validation Output ¶
The ValidationResult contains:
- Valid: Boolean indicating if the document is valid (no errors)
- Version: Detected OpenAPI version string (e.g., "3.0.3")
- OASVersion: Enumerated OAS version for programmatic use
- Errors: Slice of validation errors with paths and spec references
- Warnings: Slice of validation warnings (if IncludeWarnings is true)
- ErrorCount: Total number of errors
- WarningCount: Total number of warnings
Each ValidationError contains:
- Path: JSON path to the problematic field (e.g., "paths./pets.get.responses")
- Message: Human-readable error description
- SpecRef: URL to the relevant section of the OAS specification
- Severity: Error or Warning
- Field: Specific field name that has the issue (optional)
- Value: The problematic value (optional)
Performance Notes ¶
The validator performs comprehensive validation which may be resource-intensive for large documents. Performance considerations:
- Schema validation: Deep schemas with many levels of nesting will take longer
- Cycle detection: Maintains a visited map for each schema tree traversal
- Operation ID checking: Requires scanning all operations in the document
- Parameter consistency: Requires comparing path templates with parameter definitions
For better performance:
- Validate documents during development rather than at runtime
- Disable warnings (IncludeWarnings: false) if not needed
- Disable strict mode if the additional checks aren't required
- Cache validation results for unchanged documents
Error Path Format ¶
Validation errors include a Path field that uses JSON path notation to identify the location of the issue:
- "info.title" - Missing or invalid title in info object
- "paths./pets.get.responses" - Issue with responses in GET /pets
- "components.schemas.Pet.properties.name" - Issue with Pet.name property
- "paths./users/{id}.get.parameters[0]" - Issue with first parameter
Common Validation Errors ¶
Missing required fields:
- "Info object must have a title"
- "Info object must have a version"
- "Response must have a description"
Format validation:
- "Path must start with '/'"
- "Invalid HTTP status code: 999"
- "Invalid URL format: not-a-url"
- "Invalid email format: invalid@@email"
Parameter issues:
- "Path parameters must have required: true"
- "Path template references parameter '{id}' but it is not declared"
- "Body parameter must have a schema"
Schema validation:
- "Array schema must have 'items' defined"
- "minLength (10) cannot be greater than maxLength (5)"
- "Required field 'name' not found in properties"
Limitations ¶
- External references: The validator validates the structure but does not follow or validate external $ref links
- Custom validators: No support for custom validation rules or plugins
- Schema keywords: Some advanced JSON Schema keywords may not be fully validated
- OpenAPI extensions: Extension fields (x-*) are preserved but not validated
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ValidationError ¶
type ValidationError struct {
// Path is the JSON path to the problematic field (e.g., "paths./pets.get.responses")
Path string
// Message is a human-readable error message
Message string
// SpecRef is the URL to the relevant section of the OAS specification
SpecRef string
// Severity indicates whether this is an error or warning
Severity Severity
// Field is the specific field name that has the issue
Field string
// Value is the problematic value (optional)
Value interface{}
}
ValidationError represents a single validation issue
func (ValidationError) String ¶
func (e ValidationError) String() string
String returns a formatted string representation of the validation error
Example ¶
ExampleValidationError_String demonstrates formatting of validation errors
package main
import (
"fmt"
"github.com/erraggy/oastools/validator"
)
func main() {
err := validator.ValidationError{
Path: "paths./pets.get.responses",
Message: "Missing required field 'responses'",
SpecRef: "https://spec.openapis.org/oas/v3.0.0.html#operation-object",
Severity: validator.SeverityError,
Field: "responses",
}
fmt.Println(err.String())
// Output will show formatted error with path, message, and spec reference
}
type ValidationResult ¶
type ValidationResult struct {
// Valid is true if no errors were found (warnings are allowed)
Valid bool
// Version is the detected OAS version string
Version string
// OASVersion is the enumerated OAS version
OASVersion parser.OASVersion
// Errors contains all validation errors
Errors []ValidationError
// Warnings contains all validation warnings
Warnings []ValidationError
// ErrorCount is the total number of errors
ErrorCount int
// WarningCount is the total number of warnings
WarningCount int
}
ValidationResult contains the results of validating an OpenAPI specification
Example ¶
ExampleValidationResult demonstrates working with validation results
package main
import (
"fmt"
"log"
"path/filepath"
"github.com/erraggy/oastools/validator"
)
func main() {
v := validator.New()
testFile := filepath.Join("testdata", "invalid-oas3.yaml")
result, err := v.Validate(testFile)
if err != nil {
log.Fatalf("Validation failed: %v", err)
}
// Check if document is valid
if !result.Valid {
fmt.Printf("Validation failed with %d error(s):\n", result.ErrorCount)
for i, validationErr := range result.Errors {
fmt.Printf("%d. %s: %s\n", i+1, validationErr.Path, validationErr.Message)
if validationErr.SpecRef != "" {
fmt.Printf(" See: %s\n", validationErr.SpecRef)
}
}
}
// Show warnings if any
if result.WarningCount > 0 {
fmt.Printf("\nWarnings (%d):\n", result.WarningCount)
for i, warning := range result.Warnings {
fmt.Printf("%d. %s: %s\n", i+1, warning.Path, warning.Message)
}
}
}
type Validator ¶
type Validator struct {
// IncludeWarnings determines whether to include best practice warnings
IncludeWarnings bool
// StrictMode enables stricter validation beyond the spec requirements
StrictMode bool
}
Validator handles OpenAPI specification validation
func New ¶
func New() *Validator
New creates a new Validator instance with default settings
Example ¶
ExampleNew demonstrates creating a new validator with default settings
package main
import (
"fmt"
"github.com/erraggy/oastools/validator"
)
func main() {
// Create a validator with default settings
v := validator.New()
// Default settings
fmt.Printf("Include warnings: %v\n", v.IncludeWarnings)
fmt.Printf("Strict mode: %v\n", v.StrictMode)
}
Output: Include warnings: true Strict mode: false
func (*Validator) Validate ¶
func (v *Validator) Validate(specPath string) (*ValidationResult, error)
Validate validates an OpenAPI specification file
Example ¶
ExampleValidator_Validate demonstrates basic validation of an OpenAPI specification
package main
import (
"fmt"
"log"
"path/filepath"
"github.com/erraggy/oastools/validator"
)
func main() {
// Create a new validator
v := validator.New()
// Validate a specification file
testFile := filepath.Join("testdata", "petstore-3.0.yaml")
result, err := v.Validate(testFile)
if err != nil {
log.Fatalf("Validation failed: %v", err)
}
// Check the results
fmt.Printf("Valid: %v\n", result.Valid)
fmt.Printf("Version: %s\n", result.Version)
fmt.Printf("Errors: %d\n", result.ErrorCount)
fmt.Printf("Warnings: %d\n", result.WarningCount)
}
Example (MultipleVersions) ¶
ExampleValidator_Validate_multipleVersions demonstrates validating different OAS versions
package main
import (
"fmt"
"log"
"path/filepath"
"github.com/erraggy/oastools/validator"
)
func main() {
v := validator.New()
files := []string{
"petstore-2.0.yaml",
"petstore-3.0.yaml",
"petstore-3.1.yaml",
"petstore-3.2.yaml",
}
for _, file := range files {
testFile := filepath.Join("testdata", file)
result, err := v.Validate(testFile)
if err != nil {
log.Printf("Error validating %s: %v", file, err)
continue
}
fmt.Printf("%s: Valid=%v, Version=%s, Errors=%d, Warnings=%d\n",
file, result.Valid, result.Version, result.ErrorCount, result.WarningCount)
}
}
Example (NoWarnings) ¶
ExampleValidator_Validate_noWarnings demonstrates validation with warnings suppressed
package main
import (
"fmt"
"log"
"path/filepath"
"github.com/erraggy/oastools/validator"
)
func main() {
// Create a validator that suppresses warnings
v := validator.New()
v.IncludeWarnings = false
testFile := filepath.Join("testdata", "petstore-3.0.yaml")
result, err := v.Validate(testFile)
if err != nil {
log.Fatalf("Validation failed: %v", err)
}
// Warnings will not be included in the result
fmt.Printf("Valid: %v\n", result.Valid)
fmt.Printf("Warnings count: %d\n", result.WarningCount)
}
Example (Oas2) ¶
ExampleValidator_Validate_oas2 demonstrates validating an OAS 2.0 specification
package main
import (
"fmt"
"log"
"path/filepath"
"github.com/erraggy/oastools/validator"
)
func main() {
v := validator.New()
testFile := filepath.Join("testdata", "petstore-2.0.yaml")
result, err := v.Validate(testFile)
if err != nil {
log.Fatalf("Validation failed: %v", err)
}
fmt.Printf("Valid OAS 2.0 document: %v\n", result.Valid)
fmt.Printf("Version: %s\n", result.Version)
}
Example (StrictMode) ¶
ExampleValidator_Validate_strictMode demonstrates validation with strict mode enabled
package main
import (
"fmt"
"log"
"path/filepath"
"github.com/erraggy/oastools/validator"
)
func main() {
// Create a validator with strict mode
v := validator.New()
v.StrictMode = true
testFile := filepath.Join("testdata", "petstore-3.0.yaml")
result, err := v.Validate(testFile)
if err != nil {
log.Fatalf("Validation failed: %v", err)
}
// Strict mode may produce additional warnings
fmt.Printf("Valid: %v\n", result.Valid)
fmt.Printf("Errors: %d\n", result.ErrorCount)
fmt.Printf("Warnings: %d\n", result.WarningCount)
}
func (*Validator) ValidateParsed ¶ added in v1.3.1
func (v *Validator) ValidateParsed(parseResult parser.ParseResult) (*ValidationResult, error)
ValidateParsed validates an already parsed OpenAPI specification
Example ¶
package main
import (
"fmt"
"log"
"github.com/erraggy/oastools/parser"
"github.com/erraggy/oastools/validator"
)
func main() {
// Parse once
p := parser.New()
parseResult, err := p.Parse("../testdata/petstore-3.0.yaml")
if err != nil {
log.Fatalf("Parse failed: %v", err)
}
// Validate the already-parsed document
v := validator.New()
v.StrictMode = true
result, err := v.ValidateParsed(*parseResult)
if err != nil {
log.Fatalf("Validation failed: %v", err)
}
fmt.Printf("Valid: %v\n", result.Valid)
}