diff --git a/connexion/apis/flask_api.py b/connexion/apis/flask_api.py index b90c3da6e..ec6dc01fb 100644 --- a/connexion/apis/flask_api.py +++ b/connexion/apis/flask_api.py @@ -162,7 +162,8 @@ def _framework_to_connexion_response(cls, response, mimetype): mimetype=response.mimetype, content_type=response.content_type, headers=response.headers, - body=response.get_data(), + body=response.get_data() if not response.direct_passthrough else None, + is_streamed=response.is_streamed ) @classmethod diff --git a/connexion/decorators/response.py b/connexion/decorators/response.py index f1a9bcefc..2aa64d60f 100644 --- a/connexion/decorators/response.py +++ b/connexion/decorators/response.py @@ -88,9 +88,11 @@ def __call__(self, function): def _wrapper(request, response): connexion_response = \ self.operation.api.get_connexion_response(response, self.mimetype) - self.validate_response( - connexion_response.body, connexion_response.status_code, - connexion_response.headers, request.url) + if not connexion_response.is_streamed: + logger.warning("Skipping response validation for streamed response.") + self.validate_response( + connexion_response.body, connexion_response.status_code, + connexion_response.headers, request.url) return response diff --git a/connexion/lifecycle.py b/connexion/lifecycle.py index b6db65244..36a5e5868 100644 --- a/connexion/lifecycle.py +++ b/connexion/lifecycle.py @@ -40,9 +40,11 @@ def __init__(self, mimetype=None, content_type=None, body=None, - headers=None): + headers=None, + is_streamed=False): self.status_code = status_code self.mimetype = mimetype self.content_type = content_type self.body = body self.headers = headers or {} + self.is_streamed = is_streamed diff --git a/tests/api/test_responses.py b/tests/api/test_responses.py index 556a98ca3..e5a6f38be 100644 --- a/tests/api/test_responses.py +++ b/tests/api/test_responses.py @@ -382,3 +382,9 @@ def test_get_bad_default_response(simple_app): resp = app_client.get('/v1.0/get_bad_default_response/202') assert resp.status_code == 500 + + +def test_streaming_response(simple_app): + app_client = simple_app.app.test_client() + resp = app_client.get('/v1.0/get_streaming_response') + assert resp.status_code == 200 diff --git a/tests/fakeapi/hello/__init__.py b/tests/fakeapi/hello/__init__.py index 0645b5ef7..e04b220a0 100644 --- a/tests/fakeapi/hello/__init__.py +++ b/tests/fakeapi/hello/__init__.py @@ -3,7 +3,7 @@ import uuid from connexion import NoContent, ProblemException, context, request -from flask import jsonify, redirect +from flask import jsonify, redirect, send_file class DummyClass: @@ -615,3 +615,7 @@ def test_optional_headers(): def nullable_default(test): return + + +def get_streaming_response(): + return send_file(__file__) diff --git a/tests/fixtures/simple/openapi.yaml b/tests/fixtures/simple/openapi.yaml index 82e253340..94f4c28a3 100644 --- a/tests/fixtures/simple/openapi.yaml +++ b/tests/fixtures/simple/openapi.yaml @@ -1196,6 +1196,17 @@ paths: schema: type: string required: false + /get_streaming_response: + get: + operationId: fakeapi.hello.get_streaming_response + responses: + '200': + description: OK + content: + application/octet-stream: + schema: + type: string + format: binary servers: - url: http://localhost:{port}/{basePath} diff --git a/tests/fixtures/simple/swagger.yaml b/tests/fixtures/simple/swagger.yaml index 1030b0685..8ef06d9b0 100644 --- a/tests/fixtures/simple/swagger.yaml +++ b/tests/fixtures/simple/swagger.yaml @@ -1026,6 +1026,15 @@ paths: schema: type: object + /get_streaming_response: + get: + operationId: fakeapi.hello.get_streaming_response + responses: + '200': + description: OK + schema: + type: file + definitions: new_stack: type: object