3
3
import inspect
4
4
import re
5
5
from inspect import signature
6
- from flask import request
6
+ from flask import request , Response
7
7
from werkzeug .datastructures import ImmutableMultiDict
8
8
from werkzeug .exceptions import BadRequest
9
9
from .exceptions import (InvalidParameterTypeError , MissingInputError ,
@@ -40,8 +40,13 @@ def __call__(self, f):
40
40
}
41
41
fn_list [fsig ] = fdocs
42
42
43
- @functools .wraps (f )
44
- async def nested_func (** kwargs ):
43
+ def nested_func_helper (** kwargs ):
44
+ """
45
+ Validates the inputs of a Flask route or returns an error. Returns
46
+ are wrapped in a dictionary with a flag to let nested_func() know
47
+ if it should unpack the resulting dictionary of inputs as kwargs,
48
+ or just return the error message.
49
+ """
45
50
# Step 1 - Get expected input details as dict
46
51
expected_inputs = signature (f ).parameters
47
52
@@ -54,7 +59,7 @@ async def nested_func(**kwargs):
54
59
try :
55
60
json_input = request .json
56
61
except BadRequest :
57
- return {"error" : " Could not parse JSON." }, 400
62
+ return {"error" : ({ "error" : " Could not parse JSON." }, 400 ), "validated" : False }
58
63
59
64
# Step 3 - Extract list of parameters expected to be lists (otherwise all values are converted to lists)
60
65
expected_list_params = []
@@ -79,18 +84,32 @@ async def nested_func(**kwargs):
79
84
try :
80
85
new_input = self .validate (expected , request_inputs )
81
86
except (MissingInputError , ValidationError ) as e :
82
- return {"error" : str (e )}, 400
87
+ return {"error" : ({ "error" : str (e )}, 400 ), "validated" : False }
83
88
else :
84
89
try :
85
90
new_input = self .validate (expected , request_inputs )
86
91
except Exception as e :
87
- return self .custom_error_handler (e )
92
+ return { "error" : self .custom_error_handler (e ), "validated" : False }
88
93
validated_inputs [expected .name ] = new_input
89
94
90
- if asyncio .iscoroutinefunction (f ):
91
- return await f (** validated_inputs )
92
- else :
93
- return f (** validated_inputs )
95
+ return {"inputs" : validated_inputs , "validated" : True }
96
+
97
+ if asyncio .iscoroutinefunction (f ):
98
+ # If the view function is async, return and await a coroutine
99
+ @functools .wraps (f )
100
+ async def nested_func (** kwargs ):
101
+ validated_inputs = nested_func_helper (** kwargs )
102
+ if validated_inputs ["validated" ]:
103
+ return await f (** validated_inputs ["inputs" ])
104
+ return validated_inputs ["error" ]
105
+ else :
106
+ # If the view function is not async, return a function
107
+ @functools .wraps (f )
108
+ def nested_func (** kwargs ):
109
+ validated_inputs = nested_func_helper (** kwargs )
110
+ if validated_inputs ["validated" ]:
111
+ return f (** validated_inputs ["inputs" ])
112
+ return validated_inputs ["error" ]
94
113
95
114
nested_func .__name__ = f .__name__
96
115
return nested_func
0 commit comments