-
Notifications
You must be signed in to change notification settings - Fork 8
/
content.go
82 lines (75 loc) · 3.42 KB
/
content.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package jsonschema
// EvaluateContent checks if the given data conforms to the encoding, media type, and content schema specified in the schema.
// According to the JSON Schema Draft 2020-12:
// - The "contentEncoding" property defines how a string should be decoded from encoded binary data.
// - The "contentMediaType" describes the media type that the decoded data should conform to.
// - The "contentSchema" provides a schema to validate the structure of the decoded and unmarshalled data.
//
// This method ensures that the data instance conforms to the encoding, media type, and content schema constraints defined in the schema.
// If any stage fails, it returns a EvaluationError detailing the specific failure.
//
// References:
// - https://json-schema.org/draft/2020-12/json-schema-validation#name-contentencoding
// - https://json-schema.org/draft/2020-12/json-schema-validation#name-contentmediatype
// - https://json-schema.org/draft/2020-12/json-schema-validation#name-contentschema
func evaluateContent(schema *Schema, instance interface{}, evaluatedProps map[string]bool, evaluatedItems map[int]bool, dynamicScope *DynamicScope) (*EvaluationResult, *EvaluationError) {
value, isString := instance.(string)
if !isString {
return nil, nil // If instance is not a string, content validation is not applicable.
}
var content []byte
var parsedValue interface{}
var err error
// Decode the content if encoding is specified
if schema.ContentEncoding != nil {
decoder, exists := schema.compiler.Decoders[*schema.ContentEncoding]
if !exists {
return nil, NewEvaluationError("contentEncoding", "unsupported_encoding", "Encoding '{encoding}' is not supported", map[string]interface{}{
"encoding": *schema.ContentEncoding,
})
}
content, err = decoder(value)
if err != nil {
return nil, NewEvaluationError("contentEncoding", "invalid_encoding", "Error decoding data with '{encoding}'", map[string]interface{}{
"encoding": *schema.ContentEncoding,
"error": err.Error(),
})
}
} else {
content = []byte(value) // Assume the content is the raw string if no encoding is specified
}
// Handle content media type validation
if schema.ContentMediaType != nil {
unmarshal, exists := schema.compiler.MediaTypes[*schema.ContentMediaType]
if !exists {
return nil, NewEvaluationError("contentMediaType", "unsupported_media_type", "Media type '{media_type}' is not supported", map[string]interface{}{
"media_type": *schema.ContentMediaType,
})
}
parsedValue, err = unmarshal(content)
if err != nil {
return nil, NewEvaluationError("contentMediaType", "invalid_media_type", "Error unmarshalling data with media type '{media_type}'", map[string]interface{}{
"media_type": *schema.ContentMediaType,
"error": err.Error(),
})
}
} else {
parsedValue = content // If no media type is specified, pass the raw content
}
// Evaluate against the content schema if specified and value was decoded
if schema.ContentSchema != nil {
result, _, _ := schema.ContentSchema.evaluate(parsedValue, dynamicScope)
if result != nil {
//nolint:errcheck
result.SetEvaluationPath("/contentSchema").
SetSchemaLocation(schema.GetSchemaLocation("/contentSchema")).
SetInstanceLocation("")
if !result.IsValid() {
return result, NewEvaluationError("contentSchema", "content_schema_mismatch", "Content does not match the schema")
} else {
return result, nil
}
}
}
return nil, nil
}