Skip to content

Commit 526d925

Browse files
committed
perf: use cached rendered schemas for error messages in parameter validation
1 parent 6038995 commit 526d925

7 files changed

Lines changed: 319 additions & 60 deletions

parameters/cookie_parameters.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package parameters
55

66
import (
7-
"encoding/json"
87
"fmt"
98
"net/http"
109
"strconv"
@@ -70,13 +69,8 @@ func (v *paramValidator) ValidateCookieParamsWithPathItem(request *http.Request,
7069
sch = p.Schema.Schema()
7170
}
7271

73-
// Render schema once for ReferenceSchema field in errors
74-
var renderedSchema string
75-
if sch != nil {
76-
rendered, _ := sch.RenderInline()
77-
schemaBytes, _ := json.Marshal(rendered)
78-
renderedSchema = string(schemaBytes)
79-
}
72+
// Get rendered schema for ReferenceSchema field in errors (uses cache if available)
73+
renderedSchema := GetRenderedSchema(sch, v.options)
8074

8175
pType := sch.Type
8276

parameters/header_parameters.go

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package parameters
55

66
import (
7-
"encoding/json"
87
"fmt"
98
"net/http"
109
"strconv"
@@ -60,13 +59,8 @@ func (v *paramValidator) ValidateHeaderParamsWithPathItem(request *http.Request,
6059
sch = p.Schema.Schema()
6160
}
6261

63-
// Render schema once for ReferenceSchema field in errors
64-
var renderedSchema string
65-
if sch != nil {
66-
rendered, _ := sch.RenderInline()
67-
schemaBytes, _ := json.Marshal(rendered)
68-
renderedSchema = string(schemaBytes)
69-
}
62+
// Get rendered schema for ReferenceSchema field in errors (uses cache if available)
63+
renderedSchema := GetRenderedSchema(sch, v.options)
7064

7165
pType := sch.Type
7266

@@ -204,15 +198,10 @@ func (v *paramValidator) ValidateHeaderParamsWithPathItem(request *http.Request,
204198
}
205199
} else {
206200
if p.Required != nil && *p.Required {
207-
// Render schema for missing required parameter
201+
// Get rendered schema for missing required parameter (uses cache if available)
208202
var renderedSchema string
209203
if p.Schema != nil {
210-
sch := p.Schema.Schema()
211-
if sch != nil {
212-
rendered, _ := sch.RenderInline()
213-
schemaBytes, _ := json.Marshal(rendered)
214-
renderedSchema = string(schemaBytes)
215-
}
204+
renderedSchema = GetRenderedSchema(p.Schema.Schema(), v.options)
216205
}
217206
validationErrors = append(validationErrors, errors.HeaderParameterMissing(p, pathValue, operation, renderedSchema))
218207
}

parameters/path_parameters.go

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package parameters
55

66
import (
7-
"encoding/json"
87
"fmt"
98
"net/http"
109
"net/url"
@@ -142,13 +141,8 @@ func (v *paramValidator) ValidatePathParamsWithPathItem(request *http.Request, p
142141
// extract the schema from the parameter
143142
sch := p.Schema.Schema()
144143

145-
// Render schema once for ReferenceSchema field in errors
146-
var renderedSchema string
147-
if sch != nil {
148-
rendered, _ := sch.RenderInline()
149-
schemaBytes, _ := json.Marshal(rendered)
150-
renderedSchema = string(schemaBytes)
151-
}
144+
// Get rendered schema for ReferenceSchema field in errors (uses cache if available)
145+
renderedSchema := GetRenderedSchema(sch, v.options)
152146

153147
// check enum (if present)
154148
enumCheck := func(decodedValue string) {
@@ -309,13 +303,8 @@ func (v *paramValidator) ValidatePathParamsWithPathItem(request *http.Request, p
309303
if sch.Items != nil && sch.Items.IsA() {
310304
iSch := sch.Items.A.Schema()
311305

312-
// Render items schema once for ReferenceSchema field in array errors
313-
var renderedItemsSchema string
314-
if iSch != nil {
315-
rendered, _ := iSch.RenderInline()
316-
schemaBytes, _ := json.Marshal(rendered)
317-
renderedItemsSchema = string(schemaBytes)
318-
}
306+
// Get rendered items schema for ReferenceSchema field in errors (uses cache if available)
307+
renderedItemsSchema := GetRenderedSchema(iSch, v.options)
319308

320309
for n := range iSch.Type {
321310
// determine how to explode the array

parameters/query_parameters.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,8 @@ doneLooking:
121121
}
122122
}
123123

124-
// Render schema once for ReferenceSchema field in errors
125-
var renderedSchema string
126-
if sch != nil {
127-
rendered, _ := sch.RenderInline()
128-
schemaBytes, _ := json.Marshal(rendered)
129-
renderedSchema = string(schemaBytes)
130-
}
124+
// Get rendered schema for ReferenceSchema field in errors (uses cache if available)
125+
renderedSchema := GetRenderedSchema(sch, v.options)
131126

132127
pType := sch.Type
133128

@@ -263,12 +258,8 @@ doneLooking:
263258
break
264259
}
265260
}
266-
var renderedSchema string
267-
if sch != nil {
268-
rendered, _ := sch.RenderInline()
269-
schemaBytes, _ := json.Marshal(rendered)
270-
renderedSchema = string(schemaBytes)
271-
}
261+
// Get rendered schema for ReferenceSchema field in errors (uses cache if available)
262+
renderedSchema := GetRenderedSchema(sch, v.options)
272263
validationErrors = append(validationErrors, errors.QueryParameterMissing(params[p], pathValue, operation, renderedSchema))
273264
}
274265
}

parameters/validate_parameter.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,28 @@ func buildJsonRender(schema *base.Schema) ([]byte, error) {
9797
return utils.ConvertYAMLtoJSON(renderedSchema)
9898
}
9999

100+
// GetRenderedSchema returns a JSON string representation of the schema for error messages.
101+
// It first checks the schema cache for a pre-rendered version, falling back to fresh rendering.
102+
// This avoids expensive re-rendering on each validation when the cache is available.
103+
func GetRenderedSchema(schema *base.Schema, opts *config.ValidationOptions) string {
104+
if schema == nil {
105+
return ""
106+
}
107+
108+
// Try cache lookup first
109+
if opts != nil && opts.SchemaCache != nil && schema.GoLow() != nil {
110+
hash := schema.GoLow().Hash()
111+
if cached, ok := opts.SchemaCache.Load(hash); ok && cached != nil && len(cached.RenderedJSON) > 0 {
112+
return string(cached.RenderedJSON)
113+
}
114+
}
115+
116+
// Cache miss - render fresh
117+
rendered, _ := schema.RenderInline()
118+
schemaBytes, _ := json.Marshal(rendered)
119+
return string(schemaBytes)
120+
}
121+
100122
// ValidateParameterSchema will validate a parameter against a raw object, or a blob of json/yaml.
101123
// It will return a list of validation errors, if any.
102124
//
@@ -128,7 +150,6 @@ func ValidateParameterSchema(
128150
hash := schema.GoLow().Hash()
129151
if cached, ok := validationOptions.SchemaCache.Load(hash); ok && cached != nil && cached.CompiledSchema != nil {
130152
jsch = cached.CompiledSchema
131-
jsonSchema = cached.RenderedJSON
132153
}
133154
}
134155

0 commit comments

Comments
 (0)