Skip to content

Commit

Permalink
Minor update from spec-first#828 review
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien Sagnard committed Jan 14, 2019
1 parent 62fa3d4 commit f5c3f2f
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 8 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ htmlcov/
*.swp
.tox/
.idea/
.vscode/
venv/
src/
25 changes: 24 additions & 1 deletion connexion/apis/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,9 @@ def get_request(self, *args, **kwargs):
@abc.abstractmethod
def get_response(self, response, mimetype=None, request=None):
"""
This method converts the ConnexionResponse to a user framework response.
This method converts a handler response to a framework response.
The response can be a ConnexionResponse, an operation handler, a framework response or a tuple.
Other type than ConnexionResponse are handled by `cls._response_from_handler`
:param response: A response to cast.
:param mimetype: The response mimetype.
:param request: The request associated with this response (the user framework request).
Expand All @@ -246,12 +248,33 @@ def get_response(self, response, mimetype=None, request=None):
:type mimetype: str
"""

@classmethod
@abc.abstractmethod
def _response_from_handler(cls, response, mimetype):
"""
Create a framework response from the operation handler data.
An operation handler can return:
- a framework response
- a body (str / binary / dict / list), a response will be created
with a status code 200 by default and empty headers.
- a tuple of (body: str, status_code: int)
- a tuple of (body: str, status_code: int, headers: dict)
:param response: A response from an operation handler.
:type response Union[Response, str, Tuple[str, int], Tuple[str, int, dict]]
:param mimetype: The response mimetype.
:type mimetype: str
:return A framwork response.
:rtype Response
"""

@classmethod
@abc.abstractmethod
def get_connexion_response(cls, response, mimetype=None):
"""
This method converts the user framework response to a ConnexionResponse.
It is used after the user returned a response to give it to response validators.
:param response: A response to cast.
:param mimetype: The response mimetype.
"""

def json_loads(self, data):
Expand Down
8 changes: 5 additions & 3 deletions connexion/apis/aiohttp_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def get_response(cls, response, mimetype=None, request=None):
if isinstance(response, ConnexionResponse):
response = cls._get_aiohttp_response_from_connexion(response, mimetype)
else:
response = cls._get_aiohttp_response(response, mimetype)
response = cls._response_from_handler(response, mimetype)

logger.debug('Got stream response with status code (%d)',
response.status, extra={'url': url})
Expand All @@ -226,7 +226,7 @@ def get_connexion_response(cls, response, mimetype=None):
response = cls._get_aiohttp_response_from_connexion(response, mimetype)

if not isinstance(response, web.StreamResponse):
response = cls._get_aiohttp_response(response, mimetype)
response = cls._response_from_handler(response, mimetype)

return ConnexionResponse(
status_code=response.status,
Expand All @@ -248,9 +248,11 @@ def _get_aiohttp_response_from_connexion(cls, response, mimetype):
)

@classmethod
def _get_aiohttp_response(cls, response, mimetype):
def _response_from_handler(cls, response, mimetype):
if isinstance(response, web.StreamResponse):
return response
elif isinstance(response, tuple) and isinstance(response[0], web.StreamResponse):
raise RuntimeError("Cannot return web.StreamResponse in tuple. Only raw data can be returned in tuple.")

elif isinstance(response, tuple) and len(response) == 3:
data, status_code, headers = response
Expand Down
4 changes: 2 additions & 2 deletions connexion/apis/flask_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def get_response(cls, response, mimetype=None, request=None):
if isinstance(response, ConnexionResponse):
flask_response = cls._get_flask_response_from_connexion(response, mimetype)
else:
flask_response = cls._get_flask_response(response, mimetype)
flask_response = cls._response_from_handler(response, mimetype)

logger.debug('Got data and status code (%d)',
flask_response.status_code,
Expand Down Expand Up @@ -176,7 +176,7 @@ def _jsonify_data(cls, data, mimetype):
return data

@classmethod
def _get_flask_response(cls, response, mimetype):
def _response_from_handler(cls, response, mimetype):
if flask_utils.is_flask_response(response):
return response

Expand Down
2 changes: 0 additions & 2 deletions tests/aiohttp/test_aiohttp_api_secure.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import asyncio

import ujson
from conftest import TEST_FOLDER
from connexion import AioHttpApp


Expand Down
7 changes: 7 additions & 0 deletions tests/aiohttp/test_get_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ def test_get_response_from_string_status_headers(api):
assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8', 'X-header': 'value'}


@asyncio.coroutine
def test_get_response_from_tuple_error(api):
with pytest.raises(RuntimeError) as e:
yield from api.get_response((web.Response(text='foo', status=201, headers={'X-header': 'value'}), 200))
assert str(e.value) == "Cannot return web.StreamResponse in tuple. Only raw data can be returned in tuple."


@asyncio.coroutine
def test_get_response_from_dict(api):
response = yield from api.get_response({'foo': 'bar'})
Expand Down

0 comments on commit f5c3f2f

Please sign in to comment.