mirror of
https://github.com/LukeHagar/connexion.git
synced 2025-12-11 04:19:36 +00:00
Sensible defaults for controller resolution
This commit is contained in:
@@ -33,7 +33,8 @@ class Api:
|
||||
"""
|
||||
|
||||
def __init__(self, swagger_yaml_path, base_url=None, arguments=None, swagger_ui=None, swagger_path=None,
|
||||
swagger_url=None, validate_responses=False, resolver=utils.get_function_from_name):
|
||||
swagger_url=None, validate_responses=False, default_controller_name='',
|
||||
resolver=utils.get_function_from_name):
|
||||
"""
|
||||
:type swagger_yaml_path: pathlib.Path
|
||||
:type base_url: str | None
|
||||
@@ -76,6 +77,7 @@ class Api:
|
||||
|
||||
self.definitions = self.specification.get('definitions', {})
|
||||
self.parameter_definitions = self.specification.get('parameters', {})
|
||||
self.default_controller_name = default_controller_name
|
||||
|
||||
self.swagger_path = swagger_path or SWAGGER_UI_PATH
|
||||
self.swagger_url = swagger_url or SWAGGER_UI_URL
|
||||
@@ -111,9 +113,9 @@ class Api:
|
||||
:type swagger_operation: dict
|
||||
"""
|
||||
operation = Operation(method=method, path=path, operation=swagger_operation,
|
||||
app_produces=self.produces, app_security=self.security,
|
||||
security_definitions=self.security_definitions, definitions=self.definitions,
|
||||
parameter_definitions=self.parameter_definitions,
|
||||
default_controller_name=self.default_controller_name, app_produces=self.produces,
|
||||
app_security=self.security, security_definitions=self.security_definitions,
|
||||
definitions=self.definitions, parameter_definitions=self.parameter_definitions,
|
||||
validate_responses=self.validate_responses, resolver=self.resolver)
|
||||
operation_id = operation.operation_id
|
||||
logger.debug('... Adding %s -> %s', method.upper(), operation_id, extra=vars(operation))
|
||||
|
||||
@@ -26,7 +26,7 @@ logger = logging.getLogger('connexion.app')
|
||||
|
||||
class App:
|
||||
def __init__(self, import_name, port=None, specification_dir='', server=None, arguments=None, debug=False,
|
||||
swagger_ui=True, swagger_path=None, swagger_url=None):
|
||||
swagger_ui=True, swagger_path=None, swagger_url=None, default_controller_name=''):
|
||||
"""
|
||||
:param import_name: the name of the application package
|
||||
:type import_name: str
|
||||
@@ -46,6 +46,8 @@ class App:
|
||||
:type swagger_path: string | None
|
||||
:param swagger_url: URL to access swagger-ui documentation
|
||||
:type swagger_url: string | None
|
||||
:param default_controller_name: Default controller name for operations
|
||||
:type default_controller_name: string | import_name
|
||||
"""
|
||||
self.app = flask.Flask(import_name)
|
||||
|
||||
@@ -72,6 +74,7 @@ class App:
|
||||
self.swagger_ui = swagger_ui
|
||||
self.swagger_path = swagger_path
|
||||
self.swagger_url = swagger_url
|
||||
self.default_controller_name = default_controller_name or import_name
|
||||
|
||||
@staticmethod
|
||||
def common_error_handler(exception):
|
||||
|
||||
@@ -19,7 +19,7 @@ from .decorators.produces import BaseSerializer, Produces, Jsonifier
|
||||
from .decorators.security import security_passthrough, verify_oauth
|
||||
from .decorators.validation import RequestBodyValidator, ParameterValidator
|
||||
from .decorators.metrics import UWSGIMetricsCollector
|
||||
from.decorators.response import ResponseValidator
|
||||
from .decorators.response import ResponseValidator
|
||||
from .exceptions import InvalidSpecification
|
||||
from .utils import flaskify_endpoint, produces_json
|
||||
|
||||
@@ -31,8 +31,8 @@ class Operation:
|
||||
A single API operation on a path.
|
||||
"""
|
||||
|
||||
def __init__(self, method, path, operation, app_produces, app_security,
|
||||
security_definitions, definitions, parameter_definitions, resolver, validate_responses=False):
|
||||
def __init__(self, method, path, operation, app_produces, app_security, security_definitions, definitions,
|
||||
parameter_definitions, resolver, default_controller_name='', validate_responses=False):
|
||||
"""
|
||||
This class uses the OperationID identify the module and function that will handle the operation
|
||||
|
||||
@@ -74,13 +74,10 @@ class Operation:
|
||||
'parameters': self.parameter_definitions
|
||||
}
|
||||
self.validate_responses = validate_responses
|
||||
|
||||
self.default_router_controller_name = default_controller_name
|
||||
self.operation = operation
|
||||
operation_id = operation['operationId']
|
||||
|
||||
router_controller = operation.get('x-swagger-router-controller')
|
||||
|
||||
self.operation_id = self.detect_controller(operation_id, router_controller)
|
||||
self.operation_id = self.detect_controller()
|
||||
# todo support definition references
|
||||
# todo support references to application level parameters
|
||||
self.parameters = list(self.resolve_parameters(operation.get('parameters', [])))
|
||||
@@ -89,10 +86,22 @@ class Operation:
|
||||
self.security = operation.get('security', app_security)
|
||||
self.__undecorated_function = resolver(self.operation_id)
|
||||
|
||||
def detect_controller(self, operation_id, router_controller):
|
||||
if router_controller is None:
|
||||
def detect_controller(self):
|
||||
|
||||
operation_id = self.operation.get('operationId')
|
||||
x_router_controller = self.operation.get('x-swagger-router-controller')
|
||||
|
||||
if operation_id:
|
||||
if x_router_controller:
|
||||
return x_router_controller + '.' + operation_id
|
||||
return operation_id
|
||||
return router_controller + '.' + operation_id
|
||||
|
||||
if x_router_controller:
|
||||
mod_name = x_router_controller
|
||||
else:
|
||||
mod_name = self.default_router_controller_name
|
||||
|
||||
return mod_name + '.' + self.method.lower()
|
||||
|
||||
def resolve_reference(self, schema):
|
||||
schema = schema.copy() # avoid changing the original schema
|
||||
|
||||
@@ -14,6 +14,8 @@ class DummyClass:
|
||||
|
||||
class_instance = DummyClass()
|
||||
|
||||
def get():
|
||||
return ''
|
||||
|
||||
def post_greeting(name):
|
||||
data = {'greeting': 'Hello {name}'.format(name=name)}
|
||||
|
||||
@@ -64,6 +64,11 @@ def test_app_with_relative_path():
|
||||
test_app(app)
|
||||
|
||||
|
||||
def test_default_controller_name_defaults_to_app_module(app):
|
||||
app = App(__name__)
|
||||
assert app.default_controller_name == 'test_app'
|
||||
|
||||
|
||||
def test_app(app):
|
||||
assert app.port == 5001
|
||||
|
||||
|
||||
@@ -122,6 +122,8 @@ OPERATION6 = {'description': 'Adds a new stack to be created by lizzy and return
|
||||
'security': [{'oauth': ['uid']}],
|
||||
'summary': 'Create new stack'}
|
||||
|
||||
OPERATION7 = {'x-swagger-router-controller': 'fakeapi.hello'}
|
||||
|
||||
SECURITY_DEFINITIONS = {'oauth': {'type': 'oauth2',
|
||||
'flow': 'password',
|
||||
'x-tokenInfoUrl': 'https://ouath.example/token_info',
|
||||
@@ -249,6 +251,7 @@ def test_resolve_invalid_reference():
|
||||
exception = exc_info.value # type: InvalidSpecification
|
||||
assert exception.reason == "GET endpoint '$ref' needs to start with '#/'"
|
||||
|
||||
|
||||
def test_detect_controller():
|
||||
operation = Operation(method='GET',
|
||||
path='endpoint',
|
||||
@@ -260,3 +263,30 @@ def test_detect_controller():
|
||||
parameter_definitions=PARAMETER_DEFINITIONS,
|
||||
resolver=get_function_from_name)
|
||||
assert operation.operation_id == 'fakeapi.hello.post_greeting'
|
||||
|
||||
|
||||
def test_controller_resolution_with_x_controller_router():
|
||||
operation = Operation(method='GET',
|
||||
path='endpoint',
|
||||
operation=OPERATION7,
|
||||
app_produces=['application/json'],
|
||||
app_security=[],
|
||||
security_definitions={},
|
||||
definitions={},
|
||||
parameter_definitions=PARAMETER_DEFINITIONS,
|
||||
resolver=get_function_from_name)
|
||||
assert operation.operation_id == 'fakeapi.hello.get'
|
||||
|
||||
|
||||
def test_controller_resolution_with_default_controller_name():
|
||||
operation = Operation(method='GET',
|
||||
path='endpoint',
|
||||
operation={},
|
||||
default_controller_name='fakeapi.hello',
|
||||
app_produces=['application/json'],
|
||||
app_security=[],
|
||||
security_definitions={},
|
||||
definitions={},
|
||||
parameter_definitions=PARAMETER_DEFINITIONS,
|
||||
resolver=get_function_from_name)
|
||||
assert operation.operation_id == 'fakeapi.hello.get'
|
||||
|
||||
Reference in New Issue
Block a user