diff --git a/tests/pecantest/test/controllers/ws.py b/tests/pecantest/test/controllers/ws.py index a26f8df..b35a0c6 100644 --- a/tests/pecantest/test/controllers/ws.py +++ b/tests/pecantest/test/controllers/ws.py @@ -111,6 +111,12 @@ class AuthorsController(RestController): if id == 911: return wsme.api.Response(Author(), status_code=401) + if id == 912: + return wsme.api.Response(None, status_code=204) + + if id == 913: + return wsme.api.Response('foo', status_code=200, return_type=text) + author = Author() author.id = id author.firstname = u"aname" diff --git a/tests/pecantest/test/tests/test_ws.py b/tests/pecantest/test/tests/test_ws.py index d4027b4..ea8732f 100644 --- a/tests/pecantest/test/tests/test_ws.py +++ b/tests/pecantest/test/tests/test_ws.py @@ -175,6 +175,22 @@ class TestWS(FunctionalTest): self.assertEqual(res.status_int, expected_status_code) self.assertEqual(res.status, expected_status) + def test_non_default_response_return_type(self): + res = self.app.get( + '/authors/913', + ) + self.assertEqual(res.status_int, 200) + self.assertEqual(res.body, '"foo"') + self.assertEqual(res.content_length, 5) + + def test_non_default_response_return_type_no_content(self): + res = self.app.get( + '/authors/912', + ) + self.assertEqual(res.status_int, 204) + self.assertEqual(res.body, '') + self.assertEqual(res.content_length, 0) + def test_serversideerror(self): expected_status_code = 500 expected_status = http_response_messages[expected_status_code] diff --git a/wsme/api.py b/wsme/api.py index 2321d97..7d5095a 100644 --- a/wsme/api.py +++ b/wsme/api.py @@ -187,7 +187,8 @@ class Response(object): """ Object to hold the "response" from a view function """ - def __init__(self, obj, status_code=None, error=None): + def __init__(self, obj, status_code=None, error=None, + return_type=wsme.types.Unset): #: Store the result object from the view self.obj = obj @@ -199,6 +200,12 @@ class Response(object): #: faultstring and an optional debuginfo self.error = error + #: Return type + #: Type of the value returned by the function + #: If the return type is wsme.types.Unset it will be ignored + #: and the default return type will prevail. + self.return_type = return_type + def format_exception(excinfo, debug=False): """Extract informations that can be sent to the client.""" diff --git a/wsmeext/pecan.py b/wsmeext/pecan.py index 78871d8..f1fa933 100644 --- a/wsmeext/pecan.py +++ b/wsmeext/pecan.py @@ -72,6 +72,8 @@ def wsexpose(*args, **kwargs): @functools.wraps(f) def callfunction(self, *args, **kwargs): + return_type = funcdef.return_type + try: args, kwargs = wsme.rest.args.get_args( funcdef, args, kwargs, pecan.request.params, None, @@ -85,6 +87,17 @@ def wsexpose(*args, **kwargs): pecan.response.status = funcdef.status_code if isinstance(result, wsme.api.Response): pecan.response.status = result.status_code + + # NOTE(lucasagomes): If the return code is 204 + # (No Response) we have to make sure that we are not + # returning anything in the body response and the + # content-length is 0 + if result.status_code == 204: + return_type = None + elif not isinstance(result.return_type, + wsme.types.UnsetType): + return_type = result.return_type + result = result.obj except: @@ -106,13 +119,13 @@ def wsexpose(*args, **kwargs): return data - if funcdef.return_type is None: + if return_type is None: pecan.request.pecan['content_type'] = None pecan.response.content_type = None return '' return dict( - datatype=funcdef.return_type, + datatype=return_type, result=result )