diff --git a/CHANGELOG.md b/CHANGELOG.md index c2543fa..c1da0c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [1.0.4] - 2017-05-04 +### Added +- Added support to get service return value in response middlewares. + ## [1.0.3] - 2017-04-27 ### Added - Added support to run a component server and handle a single request diff --git a/katana/__init__.py b/katana/__init__.py index 777b972..fc0fd64 100644 --- a/katana/__init__.py +++ b/katana/__init__.py @@ -12,4 +12,4 @@ __license__ = "MIT" __copyright__ = "Copyright (c) 2016-2017 KUSANAGI S.L. (http://kusanagi.io)" -__version__ = '1.0.3' +__version__ = '1.0.4' diff --git a/katana/api/response.py b/katana/api/response.py index a3fbafb..7008fb8 100644 --- a/katana/api/response.py +++ b/katana/api/response.py @@ -10,12 +10,26 @@ """ from .base import Api +from .base import ApiError from .http.request import HttpRequest from .http.response import HttpResponse +from ..errors import KatanaError __license__ = "MIT" __copyright__ = "Copyright (c) 2016-2017 KUSANAGI S.L. (http://kusanagi.io)" +NO_RETURN_VALUE = object() + + +class NoReturnValueDefined(KatanaError): + """Raised when no return value is defined or available for a Service.""" + + message = 'No return value defined on {} for action: "{}"' + + def __init__(self, service, version, action): + server = '"{}" ({})'.format(service, version) + super().__init__(self.message.format(server, action)) + class Response(Api): """Response API class for Middleware component.""" @@ -39,6 +53,7 @@ def __init__(self, transport, *args, **kwargs): self.__http_response = None self.__transport = transport + self.__return_value = kwargs.get('return_value', NO_RETURN_VALUE) def get_gateway_protocol(self): """Get the protocol implemented by the Gateway handling current request. @@ -76,6 +91,38 @@ def get_http_response(self): return self.__http_response + def has_return(self): + """Check if there is a return value. + + Return value is available when the initial Service that is called + has a return value, and returned a value in its command reply. + + :rtype: bool + + """ + + return self.__return_value != NO_RETURN_VALUE + + def get_return_value(self): + """Get the return value returned by the called Service. + + :raises: NoReturnValueDefined + + :rtype: object + + """ + + if not self.has_return(): + transport = self.get_transport() + origin = transport.get_origin_service() + if not origin: + # During testing there is no origin + return + + raise NoReturnValueDefined(*origin) + + return self.__return_value + def get_transport(self): """Gets the Transport object. diff --git a/katana/middleware.py b/katana/middleware.py index 5d4afa3..1b555d6 100644 --- a/katana/middleware.py +++ b/katana/middleware.py @@ -14,6 +14,7 @@ from .api.param import param_to_payload from .api.request import Request +from .api.response import NO_RETURN_VALUE from .api.response import Response from .api.transport import Transport from .payload import ErrorPayload @@ -100,6 +101,7 @@ def _create_response_component_instance(self, payload): self.framework_version, debug=self.debug, variables=self.variables, + return_value=payload.get('return', NO_RETURN_VALUE), # TODO: Use meta and argument gateway_protocol=payload.get('meta/protocol'), gateway_addresses=payload.get('meta/gateway'), diff --git a/katana/payload.py b/katana/payload.py index cacb0ad..4b412cf 100644 --- a/katana/payload.py +++ b/katana/payload.py @@ -128,8 +128,8 @@ 'result': 'r', 'rollback': 'r', 'remote_calls': 'rc', + 'return': 'rv', 'response': 'R', - 'return': 'R', 'schema': 's', 'schemes': 's', 'scope': 's', @@ -403,14 +403,19 @@ class ResponsePayload(Payload): name = 'response' @classmethod - def new(cls, version=None, status=None, body=None, headers=None): + def new(cls, version=None, status=None, body=None, **kwargs): payload = cls() payload.set('version', version or '1.1') payload.set('status', status or '200 OK') payload.set('body', body or '') + + headers = kwargs.get('headers') if headers: payload.set('headers', headers) + if 'return_value' in kwargs: + payload.set('return', kwargs['return_value']) + return payload diff --git a/tests/data/schema-service.json b/tests/data/schema-service.json index 9f4d679..75af1c2 100644 --- a/tests/data/schema-service.json +++ b/tests/data/schema-service.json @@ -18,7 +18,7 @@ "rc": [["ktp://87.65.43.21:4321", "foo", "1.0", "dummy"]], "F": null, "D": true, - "R": {"t": "integer"}, + "rv": {"t": "integer"}, "h": { "g": false, "p": "/1.0/foo/{bar}",