Skip to content

Commit

Permalink
Merge pull request #28 from hjacobs/master
Browse files Browse the repository at this point in the history
Wrap add_operation with try/except to continue even if operationId or function is missing.

Closes #27
  • Loading branch information
jmcs committed Jul 7, 2015
2 parents bb123f5 + bab93ed commit 5cb750f
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ dist
connexion.egg-info
__pycache__
.coverage
*.egg
5 changes: 4 additions & 1 deletion connexion/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ def add_paths(self, paths: list=None):
path = utils.flaskify_path(path)
# TODO Error handling
for method, endpoint in methods.items():
self.add_operation(method, path, endpoint)
try:
self.add_operation(method, path, endpoint)
except:
logger.exception('Failed to add operation for %s %s%s', method.upper(), self.base_url, path)

def add_swagger_json(self):
"""
Expand Down
37 changes: 37 additions & 0 deletions connexion/decorators/validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import flask
import functools
import types

from flask import abort


def validate_schema(data, schema):
_type = schema.get('type')
if _type == 'array':
if not isinstance(data, list):
raise abort(400)
for item in data:
validate_schema(item, schema.get('items'))

if _type == 'object':
if not isinstance(data, dict):
raise abort(400)
for required_key in schema.get('required', []):
if required_key not in data:
raise abort(400)


class RequestBodyValidator:

def __init__(self, schema):
self.schema = schema

def __call__(self, function: types.FunctionType) -> types.FunctionType:
@functools.wraps(function)
def wrapper(*args, **kwargs):
data = flask.request.json
validate_schema(data, self.schema)
response = function(*args, **kwargs)
return response

return wrapper
12 changes: 12 additions & 0 deletions connexion/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from connexion.decorators.produces import BaseSerializer, Produces, Jsonifier
from connexion.decorators.security import security_passthrough, verify_oauth
from connexion.decorators.validation import RequestBodyValidator
from connexion.utils import flaskify_endpoint, get_function_from_name, produces_json

logger = logging.getLogger('connexion.operation')
Expand Down Expand Up @@ -64,6 +65,11 @@ def function(self):
security_decorator = self.__security_decorator
logger.debug('... Adding security decorator (%r)', security_decorator, extra=vars(self))
function = security_decorator(function)

validation_decorator = self.__validation_decorator
if validation_decorator:
function = validation_decorator(function)

return function

@property
Expand Down Expand Up @@ -141,3 +147,9 @@ def __security_decorator(self) -> types.FunctionType:

# if we don't know how to handle the security or it's not defined we will usa a passthrough decorator
return security_passthrough

@property
def __validation_decorator(self) -> types.FunctionType:
for parameter in self.operation.get('parameters', []):
if parameter.get('in') == 'body':
return RequestBodyValidator(parameter.get('schema'))

0 comments on commit 5cb750f

Please sign in to comment.