Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't validate streamed responses #1259

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion connexion/apis/flask_api.py
Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions connexion/decorators/response.py
Expand Up @@ -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

Expand Down
4 changes: 3 additions & 1 deletion connexion/lifecycle.py
Expand Up @@ -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
6 changes: 6 additions & 0 deletions tests/api/test_responses.py
Expand Up @@ -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
6 changes: 5 additions & 1 deletion tests/fakeapi/hello/__init__.py
Expand Up @@ -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:
Expand Down Expand Up @@ -615,3 +615,7 @@ def test_optional_headers():

def nullable_default(test):
return


def get_streaming_response():
return send_file(__file__)
11 changes: 11 additions & 0 deletions tests/fixtures/simple/openapi.yaml
Expand Up @@ -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}
Expand Down
9 changes: 9 additions & 0 deletions tests/fixtures/simple/swagger.yaml
Expand Up @@ -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
Expand Down