21
21
Response ,
22
22
json_response ,
23
23
)
24
- from collections import defaultdict
24
+ from collections import defaultdict , MutableMapping
25
25
from jsonschema import (
26
- validate ,
27
26
ValidationError ,
28
27
FormatChecker ,
28
+ Draft4Validator ,
29
+ validators ,
29
30
)
30
- from jsonschema .validators import validator_for
31
31
32
32
33
33
__all__ = (
@@ -54,12 +54,35 @@ def multi_dict_to_dict(mld: Mapping) -> Mapping:
54
54
}
55
55
56
56
57
- def validate_schema (obj : Mapping , schema : Mapping ):
58
- validate (obj , schema , format_checker = FormatChecker ())
57
+ def extend_with_default (validator_class ):
59
58
59
+ validate_properties = validator_class .VALIDATORS ["properties" ]
60
60
61
- def validate_multi_dict (obj , schema ):
62
- validate (multi_dict_to_dict (obj ), schema , format_checker = FormatChecker ())
61
+ def set_defaults (validator , properties , instance , schema ):
62
+ if isinstance (instance , MutableMapping ):
63
+ for prop , sub_schema in properties .items ():
64
+ if "default" in sub_schema :
65
+ instance .setdefault (prop , sub_schema ["default" ])
66
+ for error in validate_properties (
67
+ validator , properties , instance , schema ):
68
+ yield error
69
+
70
+ return validators .extend (validator_class , {"properties" : set_defaults })
71
+
72
+
73
+ json_schema_validator = extend_with_default (Draft4Validator )
74
+
75
+
76
+ def validate_schema (obj : Mapping , schema : Mapping ) -> Mapping :
77
+ json_schema_validator (schema , format_checker = FormatChecker ()).validate (obj )
78
+ return obj
79
+
80
+
81
+ def validate_multi_dict (obj , schema ) -> Mapping :
82
+ _obj = multi_dict_to_dict (obj )
83
+ json_schema_validator (
84
+ schema , format_checker = FormatChecker ()).validate (_obj )
85
+ return _obj
63
86
64
87
65
88
def validate_content_type (swagger : Mapping , content_type : str ):
@@ -73,34 +96,34 @@ async def validate_request(
73
96
request : Request ,
74
97
parameter_groups : Mapping ,
75
98
swagger : Mapping ):
99
+ res = {}
76
100
validate_content_type (swagger , request .content_type )
77
- for group_name , group_schemas in parameter_groups .items ():
101
+ for group_name , group_schema in parameter_groups .items ():
78
102
if group_name == 'header' :
79
- headers = request .headers
80
- for schema in group_schemas :
81
- validate_multi_dict (headers , schema )
103
+ res ['headers' ] = validate_multi_dict (request .headers , group_schema )
82
104
if group_name == 'query' :
83
- query = request .query
84
- for schema in group_schemas :
85
- validate_multi_dict (query , schema )
105
+ res ['query' ] = validate_multi_dict (request .query , group_schema )
86
106
if group_name == 'formData' :
87
107
try :
88
108
data = await request .post ()
89
109
except ValueError :
90
110
data = None
91
- for schema in group_schemas :
92
- validate_multi_dict (data , schema )
111
+ res ['formData' ] = validate_multi_dict (data , group_schema )
93
112
if group_name == 'body' :
94
- try :
95
- content = await request .json ()
96
- except json .JSONDecodeError :
97
- content = None
98
- for schema in group_schemas :
99
- validate_schema (content , schema )
113
+ if request .content_type == 'application/json' :
114
+ try :
115
+ content = await request .json ()
116
+ except json .JSONDecodeError :
117
+ content = None
118
+ elif request .content_type .startswith ('text' ):
119
+ content = await request .text ()
120
+ else :
121
+ content = await request .read ()
122
+ res ['body' ] = validate_schema (content , group_schema )
100
123
if group_name == 'path' :
101
124
params = dict (request .match_info )
102
- for schema in group_schemas :
103
- validate_schema ( params , schema )
125
+ res [ 'path' ] = validate_schema ( params , group_schema )
126
+ return res
104
127
105
128
106
129
def adjust_swagger_item_to_json_schemes (* schemes : Mapping ) -> Mapping :
@@ -124,7 +147,7 @@ def adjust_swagger_item_to_json_schemes(*schemes: Mapping) -> Mapping:
124
147
required_fields .append (name )
125
148
if required_fields :
126
149
new_schema ['required' ] = required_fields
127
- validator_for (new_schema ).check_schema (new_schema )
150
+ validators . validator_for (new_schema ).check_schema (new_schema )
128
151
return new_schema
129
152
130
153
@@ -139,21 +162,21 @@ def adjust_swagger_body_item_to_json_schema(schema: Mapping) -> Mapping:
139
162
new_schema ,
140
163
]
141
164
}
142
- validator_for (new_schema ).check_schema (new_schema )
165
+ validators . validator_for (new_schema ).check_schema (new_schema )
143
166
return new_schema
144
167
145
168
146
169
def adjust_swagger_to_json_schema (parameter_groups : Iterable ) -> Mapping :
147
- res = defaultdict ( list )
170
+ res = {}
148
171
for group_name , group_schemas in parameter_groups :
149
172
if group_name in ('query' , 'header' , 'path' , 'formData' ):
150
173
json_schema = adjust_swagger_item_to_json_schemes (* group_schemas )
151
- res [group_name ]. append ( json_schema )
174
+ res [group_name ] = json_schema
152
175
else :
153
176
# only one possible schema for in: body
154
177
schema = list (group_schemas )[0 ]
155
178
json_schema = adjust_swagger_body_item_to_json_schema (schema )
156
- res [group_name ]. append ( json_schema )
179
+ res [group_name ] = json_schema
157
180
return res
158
181
159
182
@@ -216,7 +239,9 @@ async def _wrapper(*args, **kwargs) -> Response:
216
239
request = args [0 ].request \
217
240
if isinstance (args [0 ], web .View ) else args [0 ]
218
241
try :
219
- await validate_request (request , parameter_groups , schema )
242
+ validation = \
243
+ await validate_request (request , parameter_groups , schema )
244
+ request .validation = validation
220
245
except ValidationError as exc :
221
246
logger .exception (exc )
222
247
exc_dict = validation_exc_to_dict (exc )
0 commit comments