Skip to content

Commit

Permalink
Merge pull request #137 from rafaelcaricio/fix_api_returns_flask_resp…
Browse files Browse the repository at this point in the history
…onse

Fix when API returns flask response
  • Loading branch information
hjacobs committed Feb 3, 2016
2 parents 678fbf7 + bf7638f commit 67c24d9
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 3 deletions.
3 changes: 2 additions & 1 deletion connexion/decorators/decorator.py
Expand Up @@ -12,6 +12,7 @@
"""
import logging
import flask
from ..utils import is_flask_response

logger = logging.getLogger('connexion.decorators.decorator')

Expand All @@ -32,7 +33,7 @@ def get_full_response(data):
url = flask.request.url
logger.debug('Getting data and status code', extra={'data': data, 'data_type': type(data), 'url': url})
status_code, headers = 200, {}
if isinstance(data, flask.Response):
if is_flask_response(data):
data = data
status_code = data.status_code
headers = data.headers
Expand Down
5 changes: 3 additions & 2 deletions connexion/decorators/produces.py
Expand Up @@ -18,6 +18,7 @@
import json
import logging
from .decorator import BaseDecorator
from ..utils import is_flask_response

logger = logging.getLogger('connexion.decorators.produces')

Expand Down Expand Up @@ -83,7 +84,7 @@ def wrapper(*args, **kwargs):
url = flask.request.url
data, status_code, headers = self.get_full_response(function(*args, **kwargs))
logger.debug('Returning %s', url, extra={'url': url, 'mimetype': self.mimetype})
if isinstance(data, flask.Response): # if the function returns a Response object don't change it
if is_flask_response(data):
logger.debug('Endpoint returned a Flask Response', extra={'url': url, 'mimetype': data.mimetype})
return data

Expand Down Expand Up @@ -114,7 +115,7 @@ def wrapper(*args, **kwargs):
url = flask.request.url
logger.debug('Jsonifing %s', url, extra={'url': url, 'mimetype': self.mimetype})
data, status_code, headers = self.get_full_response(function(*args, **kwargs))
if isinstance(data, flask.Response): # if the function returns a Response object don't change it
if is_flask_response(data):
logger.debug('Endpoint returned a Flask Response', extra={'url': url, 'mimetype': data.mimetype})
return data
elif data is NoContent:
Expand Down
17 changes: 17 additions & 0 deletions connexion/utils.py
Expand Up @@ -14,6 +14,8 @@
import functools
import importlib
import re
import flask
import werkzeug.wrappers

PATH_PARAMETER = re.compile(r'\{([^}]*)\}')

Expand Down Expand Up @@ -59,6 +61,21 @@ def flaskify_path(swagger_path, types={}):
return PATH_PARAMETER.sub(convert_match, swagger_path)


def is_flask_response(obj):
"""
Verifies if obj is a default Flask response instance.
:type obj: object
:rtype bool
>>> is_flask_response(redirect('http://example.com/'))
True
>>> is_flask_response(flask.Response())
True
"""
return isinstance(obj, flask.Response) or isinstance(obj, werkzeug.wrappers.Response)


def deep_getattr(obj, attr):
"""
Recurses through an attribute chain to get the ultimate value.
Expand Down
16 changes: 16 additions & 0 deletions tests/fakeapi/api.yaml
Expand Up @@ -656,6 +656,22 @@ paths:
in: query
required: true

/test-redirect-endpoint:
get:
summary: Tests handlers returning flask.Response objects
operationId: fakeapi.hello.test_redirect_endpoint
responses:
302:
description: 302 Found

/test-redirect-response-endpoint:
get:
summary: Tests handlers returning flask.Response objects
operationId: fakeapi.hello.test_redirect_response_endpoint
responses:
302:
description: 302 Found

definitions:
new_stack:
type: object
Expand Down
10 changes: 10 additions & 0 deletions tests/fakeapi/hello.py
Expand Up @@ -2,6 +2,7 @@

from connexion import problem, request
from connexion import NoContent
from flask import redirect


class DummyClass:
Expand Down Expand Up @@ -234,3 +235,12 @@ def test_bool_default_param(thruthiness):

def test_required_param(simple):
return simple


def test_redirect_endpoint():
headers = {'Location': 'http://www.google.com/'}
return '', 302, headers


def test_redirect_response_endpoint():
return redirect('http://www.google.com/')
12 changes: 12 additions & 0 deletions tests/test_app.py
Expand Up @@ -613,3 +613,15 @@ def test_required_param_miss_config(app):

resp = app_client.get('/v1.0/test-required-param')
assert resp.status_code == 400


def test_redirect_endpoint(app):
app_client = app.app.test_client()
resp = app_client.get('/v1.0/test-redirect-endpoint')
assert resp.status_code == 302


def test_redirect_response_endpoint(app):
app_client = app.app.test_client()
resp = app_client.get('/v1.0/test-redirect-response-endpoint')
assert resp.status_code == 302

0 comments on commit 67c24d9

Please sign in to comment.