Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package cache
import (
"github.com/pb33f/libopenapi/datamodel/high/base"
"github.com/santhosh-tekuri/jsonschema/v6"
"go.yaml.in/yaml/v4"
)

// SchemaCacheEntry holds a compiled schema and its intermediate representations.
Expand All @@ -16,6 +17,7 @@ type SchemaCacheEntry struct {
ReferenceSchema string // String version of RenderedInline
RenderedJSON []byte
CompiledSchema *jsonschema.Schema
RenderedNode *yaml.Node
}

// SchemaCache defines the interface for schema caching implementations.
Expand Down
11 changes: 8 additions & 3 deletions requests/validate_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
var renderedSchema, jsonSchema []byte
var referenceSchema string
var compiledSchema *jsonschema.Schema
var cachedNode *yaml.Node

if input.Schema == nil {
return false, []*errors.ValidationError{{
Expand All @@ -71,6 +72,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
referenceSchema = cached.ReferenceSchema
jsonSchema = cached.RenderedJSON
compiledSchema = cached.CompiledSchema
cachedNode = cached.RenderedNode
}
}

Expand Down Expand Up @@ -229,9 +231,12 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
schFlatErrs := jk.BasicOutput().Errors
var schemaValidationErrors []*errors.SchemaValidationFailure

// re-encode the schema.
var renderedNode yaml.Node
_ = yaml.Unmarshal(renderedSchema, &renderedNode)
// Use cached node if available, otherwise parse
renderedNode := cachedNode
if renderedNode == nil {
renderedNode = new(yaml.Node)
_ = yaml.Unmarshal(renderedSchema, renderedNode)
}
for q := range schFlatErrs {
er := schFlatErrs[q]

Expand Down
10 changes: 7 additions & 3 deletions responses/validate_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
var renderedSchema, jsonSchema []byte
var referenceSchema string
var compiledSchema *jsonschema.Schema
var cachedNode *yaml.Node

if input.Schema == nil {
return false, []*errors.ValidationError{{
Expand All @@ -74,6 +75,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
renderedSchema = cached.RenderedInline
referenceSchema = cached.ReferenceSchema
compiledSchema = cached.CompiledSchema
cachedNode = cached.RenderedNode
}
}

Expand Down Expand Up @@ -247,9 +249,11 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
schFlatErrs := jk.BasicOutput().Errors
var schemaValidationErrors []*errors.SchemaValidationFailure

// re-encode the schema once for error reporting
var renderedNode yaml.Node
_ = yaml.Unmarshal(renderedSchema, &renderedNode)
renderedNode := cachedNode
if renderedNode == nil {
renderedNode = new(yaml.Node)
_ = yaml.Unmarshal(renderedSchema, renderedNode)
}

for q := range schFlatErrs {
er := schFlatErrs[q]
Expand Down
11 changes: 11 additions & 0 deletions validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/pb33f/libopenapi"
"github.com/pb33f/libopenapi/datamodel/high/base"
"github.com/pb33f/libopenapi/utils"
"go.yaml.in/yaml/v4"

v3 "github.com/pb33f/libopenapi/datamodel/high/v3"

Expand Down Expand Up @@ -491,12 +492,17 @@ func warmMediaTypeSchema(mediaType *v3.MediaType, schemaCache cache.SchemaCache,
if len(renderedInline) > 0 {
compiledSchema, _ := helpers.NewCompiledSchema(fmt.Sprintf("%x", hash), renderedJSON, options)

// Pre-parse YAML node for error reporting (avoids re-parsing on each error)
var renderedNode yaml.Node
_ = yaml.Unmarshal(renderedInline, &renderedNode)

schemaCache.Store(hash, &cache.SchemaCacheEntry{
Schema: schema,
RenderedInline: renderedInline,
ReferenceSchema: referenceSchema,
RenderedJSON: renderedJSON,
CompiledSchema: compiledSchema,
RenderedNode: &renderedNode,
})
}
}
Expand Down Expand Up @@ -539,13 +545,18 @@ func warmParameterSchema(param *v3.Parameter, schemaCache cache.SchemaCache, opt
if len(renderedInline) > 0 {
compiledSchema, _ := helpers.NewCompiledSchema(fmt.Sprintf("%x", hash), renderedJSON, options)

// Pre-parse YAML node for error reporting (avoids re-parsing on each error)
var renderedNode yaml.Node
_ = yaml.Unmarshal(renderedInline, &renderedNode)

// Store in cache using the shared SchemaCache type
schemaCache.Store(hash, &cache.SchemaCacheEntry{
Schema: schema,
RenderedInline: renderedInline,
ReferenceSchema: referenceSchema,
RenderedJSON: renderedJSON,
CompiledSchema: compiledSchema,
RenderedNode: &renderedNode,
})
}
}
Expand Down