Skip to content

Commit

Permalink
#32 Reduce code repetition
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcs committed Jul 13, 2015
1 parent 6d5297f commit f5ef93b
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 53 deletions.
98 changes: 46 additions & 52 deletions connexion/decorators/validation.py
Expand Up @@ -29,57 +29,6 @@
'boolean': bool} # map of swagger types to python types


def validate_schema(data, schema) -> flask.Response:
schema_type = schema.get('type')
log_extra = {'url': flask.request.url, 'schema_type': schema_type}

if schema_type == 'array':
if not isinstance(data, list):
actual_type_name = type(data).__name__
logger.error("Wrong data type, expected 'list' got '%s'", actual_type_name, extra=log_extra)
return problem(400, 'Bad Request', "Wrong type, expected 'array' got '{}'".format(actual_type_name))
for item in data:
error = validate_schema(item, schema.get('items'))
if error:
return error

elif schema_type == 'object':
if not isinstance(data, dict):
actual_type_name = type(data).__name__
logger.error("Wrong data type, expected 'dict' got '%s'", actual_type_name, extra=log_extra)
return problem(400, 'Bad Request', "Wrong type, expected 'object' got '{}'".format(actual_type_name))

# verify if required keys are present
required_keys = schema.get('required', [])
logger.debug('... required keys: %s', required_keys)
log_extra['required_keys'] = required_keys
for required_key in schema.get('required', required_keys):
if required_key not in data:
logger.error("Missing parameter '%s'", required_key, extra=log_extra)
return problem(400, 'Bad Request', "Missing parameter '{}'".format(required_key))

# verify if value types are correct
for key in data.keys():
key_properties = schema['properties'].get(key)
if key_properties:
expected_type = TYPE_MAP.get(key_properties['type']) # type: type
if expected_type and not isinstance(data[key], expected_type):
expected_type_name = expected_type.__name__
actual_type_name = type(data[key]).__name__
logger.error("'%s' is not a '%s'", key, expected_type_name)
return problem(400, 'Bad Request',
"Wrong type, expected '{}' got '{}'".format(expected_type_name, actual_type_name))
else:
expected_type = TYPE_MAP.get(schema_type) # type: type
actual_type = type(data) # type: type
if expected_type and not isinstance(data, expected_type):
expected_type_name = expected_type.__name__
actual_type_name = actual_type.__name__
logger.error("'%s' is not a '%s'", data, expected_type_name)
return problem(400, 'Bad Request',
"Wrong type, expected '{}' got '{}'".format(schema_type, actual_type_name))


class RequestBodyValidator:
def __init__(self, schema):
self.schema = schema
Expand All @@ -90,11 +39,56 @@ def wrapper(*args, **kwargs):
data = flask.request.json

logger.debug("%s validating schema...", flask.request.url)
error = validate_schema(data, self.schema)
error = self.validate_schema(data, self.schema)
if error:
return error

response = function(*args, **kwargs)
return response

return wrapper

def validate_schema(self, data, schema) -> flask.Response:
schema_type = schema.get('type')
log_extra = {'url': flask.request.url, 'schema_type': schema_type}

if schema_type == 'array':
if not isinstance(data, list):
actual_type_name = type(data).__name__
logger.error("Wrong data type, expected 'list' got '%s'", actual_type_name, extra=log_extra)
return problem(400, 'Bad Request', "Wrong type, expected 'array' got '{}'".format(actual_type_name))
for item in data:
error = self.validate_schema(item, schema.get('items'))
if error:
return error
elif schema_type == 'object':
if not isinstance(data, dict):
actual_type_name = type(data).__name__
logger.error("Wrong data type, expected 'dict' got '%s'", actual_type_name, extra=log_extra)
return problem(400, 'Bad Request', "Wrong type, expected 'object' got '{}'".format(actual_type_name))

# verify if required keys are present
required_keys = schema.get('required', [])
logger.debug('... required keys: %s', required_keys)
log_extra['required_keys'] = required_keys
for required_key in schema.get('required', required_keys):
if required_key not in data:
logger.error("Missing parameter '%s'", required_key, extra=log_extra)
return problem(400, 'Bad Request', "Missing parameter '{}'".format(required_key))

# verify if value types are correct
for key in data.keys():
key_properties = schema['properties'].get(key)
if key_properties:
error = self.validate_schema(data[key], key_properties)
if error:
return error
else:
expected_type = TYPE_MAP.get(schema_type) # type: type
actual_type = type(data) # type: type
if expected_type and not isinstance(data, expected_type):
expected_type_name = expected_type.__name__
actual_type_name = actual_type.__name__
logger.error("'%s' is not a '%s'", data, expected_type_name)
return problem(400, 'Bad Request',
"Wrong type, expected '{}' got '{}'".format(schema_type, actual_type_name))
2 changes: 1 addition & 1 deletion tests/test_app.py
Expand Up @@ -247,7 +247,7 @@ def test_schema(app):
assert bad_type.content_type == 'application/problem+json'
bad_type_response = json.loads(bad_type.data.decode()) # type: dict
assert bad_type_response['title'] == 'Bad Request'
assert bad_type_response['detail'] == "Wrong type, expected 'str' got 'int'"
assert bad_type_response['detail'] == "Wrong type, expected 'string' got 'int'"

good_request = app_client.post('/v1.0/test_schema', headers=headers,
data=json.dumps({'image_version': 'version'})) # type: flask.Response
Expand Down

0 comments on commit f5ef93b

Please sign in to comment.