Skip to content

Commit 2a27e2e

Browse files
its-hammer-timedaveshanley
authored andcommitted
Cache Reference Schema
1 parent 5ace66c commit 2a27e2e

3 files changed

Lines changed: 40 additions & 30 deletions

File tree

cache/cache.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ import (
1111
// SchemaCacheEntry holds a compiled schema and its intermediate representations.
1212
// This is stored in the cache to avoid re-rendering and re-compiling schemas on each request.
1313
type SchemaCacheEntry struct {
14-
Schema *base.Schema
15-
RenderedInline []byte
16-
RenderedJSON []byte
17-
CompiledSchema *jsonschema.Schema
14+
Schema *base.Schema
15+
RenderedInline []byte
16+
RenderedJSON []byte
17+
ReferenceSchema string // String version of RenderedInline, cached to avoid repeated conversions
18+
CompiledSchema *jsonschema.Schema
1819
}
1920

2021
// SchemaCache defines the interface for schema caching implementations.

requests/validate_request.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
4343
validationOptions := config.NewValidationOptions(input.Options...)
4444
var validationErrors []*errors.ValidationError
4545
var renderedSchema, jsonSchema []byte
46+
var referenceSchema string
4647
var compiledSchema *jsonschema.Schema
4748

4849
if input.Schema == nil {
@@ -65,6 +66,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
6566
hash := input.Schema.GoLow().Hash()
6667
if cached, ok := validationOptions.SchemaCache.Load(hash); ok && cached != nil && cached.CompiledSchema != nil {
6768
renderedSchema = cached.RenderedInline
69+
referenceSchema = cached.ReferenceSchema
6870
jsonSchema = cached.RenderedJSON
6971
compiledSchema = cached.CompiledSchema
7072
}
@@ -73,6 +75,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
7375
// Cache miss or no cache - render and compile
7476
if compiledSchema == nil {
7577
renderedSchema, _ = input.Schema.RenderInline()
78+
referenceSchema = string(renderedSchema)
7679
jsonSchema, _ = utils.ConvertYAMLtoJSON(renderedSchema)
7780

7881
var err error
@@ -87,7 +90,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
8790
violation := &errors.SchemaValidationFailure{
8891
Reason: fmt.Sprintf("failed to compile JSON schema: %s", err.Error()),
8992
Location: "schema compilation",
90-
ReferenceSchema: string(renderedSchema),
93+
ReferenceSchema: referenceSchema,
9194
}
9295
validationErrors = append(validationErrors, &errors.ValidationError{
9396
ValidationType: helpers.RequestBodyValidation,
@@ -99,18 +102,19 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
99102
SpecCol: 0,
100103
SchemaValidationErrors: []*errors.SchemaValidationFailure{violation},
101104
HowToFix: "check the request schema for invalid JSON Schema syntax, complex regex patterns, or unsupported schema constructs",
102-
Context: string(renderedSchema),
105+
Context: referenceSchema,
103106
})
104107
return false, validationErrors
105108
}
106109

107110
if validationOptions.SchemaCache != nil {
108111
hash := input.Schema.GoLow().Hash()
109112
validationOptions.SchemaCache.Store(hash, &cache.SchemaCacheEntry{
110-
Schema: input.Schema,
111-
RenderedInline: renderedSchema,
112-
RenderedJSON: jsonSchema,
113-
CompiledSchema: compiledSchema,
113+
Schema: input.Schema,
114+
RenderedInline: renderedSchema,
115+
ReferenceSchema: referenceSchema,
116+
RenderedJSON: jsonSchema,
117+
CompiledSchema: compiledSchema,
114118
})
115119
}
116120
}
@@ -137,7 +141,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
137141
violation := &errors.SchemaValidationFailure{
138142
Reason: err.Error(),
139143
Location: "unavailable",
140-
ReferenceSchema: string(renderedSchema),
144+
ReferenceSchema: referenceSchema,
141145
ReferenceObject: string(requestBody),
142146
}
143147
validationErrors = append(validationErrors, &errors.ValidationError{
@@ -150,7 +154,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
150154
SpecCol: 0,
151155
SchemaValidationErrors: []*errors.SchemaValidationFailure{violation},
152156
HowToFix: errors.HowToFixInvalidSchema,
153-
Context: string(renderedSchema), // attach the rendered schema to the error
157+
Context: referenceSchema, // attach the rendered schema to the error
154158
})
155159
return false, validationErrors
156160
}
@@ -169,7 +173,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
169173
// cannot decode the request body, so it's not valid
170174
violation := &errors.SchemaValidationFailure{
171175
Reason: "request body is empty, but there is a schema defined",
172-
ReferenceSchema: string(renderedSchema),
176+
ReferenceSchema: referenceSchema,
173177
ReferenceObject: string(requestBody),
174178
}
175179
validationErrors = append(validationErrors, &errors.ValidationError{
@@ -182,7 +186,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
182186
SpecCol: col,
183187
SchemaValidationErrors: []*errors.SchemaValidationFailure{violation},
184188
HowToFix: errors.HowToFixInvalidSchema,
185-
Context: string(renderedSchema), // attach the rendered schema to the error
189+
Context: referenceSchema, // attach the rendered schema to the error
186190
})
187191
return false, validationErrors
188192
}
@@ -237,7 +241,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
237241
FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation),
238242
FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation),
239243
InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation),
240-
ReferenceSchema: string(renderedSchema),
244+
ReferenceSchema: referenceSchema,
241245
ReferenceObject: referenceObject,
242246
OriginalError: jk,
243247
}
@@ -280,7 +284,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
280284
SpecCol: col,
281285
SchemaValidationErrors: schemaValidationErrors,
282286
HowToFix: errors.HowToFixInvalidSchema,
283-
Context: string(renderedSchema), // attach the rendered schema to the error
287+
Context: referenceSchema, // attach the rendered schema to the error
284288
})
285289
}
286290
if len(validationErrors) > 0 {

responses/validate_response.go

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
4747
validationOptions := config.NewValidationOptions(input.Options...)
4848
var validationErrors []*errors.ValidationError
4949
var renderedSchema, jsonSchema []byte
50+
var referenceSchema string
5051
var compiledSchema *jsonschema.Schema
5152

5253
if input.Schema == nil {
@@ -69,13 +70,16 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
6970
hash := input.Schema.GoLow().Hash()
7071
if cached, ok := validationOptions.SchemaCache.Load(hash); ok && cached != nil && cached.CompiledSchema != nil {
7172
renderedSchema = cached.RenderedInline
73+
referenceSchema = cached.ReferenceSchema
74+
jsonSchema = cached.RenderedJSON
7275
compiledSchema = cached.CompiledSchema
7376
}
7477
}
7578

7679
// Cache miss or no cache - render and compile
7780
if compiledSchema == nil {
7881
renderedSchema, _ = input.Schema.RenderInline()
82+
referenceSchema = string(renderedSchema)
7983
jsonSchema, _ = utils.ConvertYAMLtoJSON(renderedSchema)
8084

8185
var err error
@@ -90,7 +94,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
9094
violation := &errors.SchemaValidationFailure{
9195
Reason: fmt.Sprintf("failed to compile JSON schema: %s", err.Error()),
9296
Location: "schema compilation",
93-
ReferenceSchema: string(renderedSchema),
97+
ReferenceSchema: referenceSchema,
9498
}
9599
validationErrors = append(validationErrors, &errors.ValidationError{
96100
ValidationType: helpers.ResponseBodyValidation,
@@ -103,18 +107,19 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
103107
SpecCol: 0,
104108
SchemaValidationErrors: []*errors.SchemaValidationFailure{violation},
105109
HowToFix: "check the response schema for invalid JSON Schema syntax, complex regex patterns, or unsupported schema constructs",
106-
Context: string(renderedSchema),
110+
Context: referenceSchema,
107111
})
108112
return false, validationErrors
109113
}
110114

111115
if validationOptions.SchemaCache != nil {
112116
hash := input.Schema.GoLow().Hash()
113117
validationOptions.SchemaCache.Store(hash, &cache.SchemaCacheEntry{
114-
Schema: input.Schema,
115-
RenderedInline: renderedSchema,
116-
RenderedJSON: jsonSchema,
117-
CompiledSchema: compiledSchema,
118+
Schema: input.Schema,
119+
RenderedInline: renderedSchema,
120+
ReferenceSchema: referenceSchema,
121+
RenderedJSON: jsonSchema,
122+
CompiledSchema: compiledSchema,
118123
})
119124
}
120125
}
@@ -128,7 +133,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
128133
violation := &errors.SchemaValidationFailure{
129134
Reason: "response is empty",
130135
Location: "unavailable",
131-
ReferenceSchema: string(renderedSchema),
136+
ReferenceSchema: referenceSchema,
132137
}
133138
validationErrors = append(validationErrors, &errors.ValidationError{
134139
ValidationType: "response",
@@ -140,7 +145,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
140145
SpecCol: 0,
141146
SchemaValidationErrors: []*errors.SchemaValidationFailure{violation},
142147
HowToFix: "ensure response object has been set",
143-
Context: string(renderedSchema), // attach the rendered schema to the error
148+
Context: referenceSchema, // attach the rendered schema to the error
144149
})
145150
return false, validationErrors
146151
}
@@ -151,7 +156,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
151156
violation := &errors.SchemaValidationFailure{
152157
Reason: ioErr.Error(),
153158
Location: "unavailable",
154-
ReferenceSchema: string(renderedSchema),
159+
ReferenceSchema: referenceSchema,
155160
ReferenceObject: string(responseBody),
156161
}
157162
validationErrors = append(validationErrors, &errors.ValidationError{
@@ -164,7 +169,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
164169
SpecCol: 0,
165170
SchemaValidationErrors: []*errors.SchemaValidationFailure{violation},
166171
HowToFix: "ensure body is not empty",
167-
Context: string(renderedSchema), // attach the rendered schema to the error
172+
Context: referenceSchema, // attach the rendered schema to the error
168173
})
169174
return false, validationErrors
170175
}
@@ -182,7 +187,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
182187
violation := &errors.SchemaValidationFailure{
183188
Reason: err.Error(),
184189
Location: "unavailable",
185-
ReferenceSchema: string(renderedSchema),
190+
ReferenceSchema: referenceSchema,
186191
ReferenceObject: string(responseBody),
187192
}
188193
validationErrors = append(validationErrors, &errors.ValidationError{
@@ -195,7 +200,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
195200
SpecCol: 0,
196201
SchemaValidationErrors: []*errors.SchemaValidationFailure{violation},
197202
HowToFix: errors.HowToFixInvalidSchema,
198-
Context: string(renderedSchema), // attach the rendered schema to the error
203+
Context: referenceSchema, // attach the rendered schema to the error
199204
})
200205
return false, validationErrors
201206
}
@@ -252,7 +257,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
252257
FieldName: helpers.ExtractFieldNameFromStringLocation(er.InstanceLocation),
253258
FieldPath: helpers.ExtractJSONPathFromStringLocation(er.InstanceLocation),
254259
InstancePath: helpers.ConvertStringLocationToPathSegments(er.InstanceLocation),
255-
ReferenceSchema: string(renderedSchema),
260+
ReferenceSchema: referenceSchema,
256261
ReferenceObject: referenceObject,
257262
OriginalError: jk,
258263
}
@@ -295,7 +300,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
295300
SpecCol: col,
296301
SchemaValidationErrors: schemaValidationErrors,
297302
HowToFix: errors.HowToFixInvalidSchema,
298-
Context: string(renderedSchema), // attach the rendered schema to the error
303+
Context: referenceSchema, // attach the rendered schema to the error
299304
})
300305
}
301306
if len(validationErrors) > 0 {

0 commit comments

Comments
 (0)