Don't (mistakenly) set HTTP 204 on controllers which set response.body_file.
Fixes bug 1339121 Change-Id: I70785315837b3907b63bb10565f3ccdf07559e8d
This commit is contained in:
@@ -2,11 +2,12 @@ try:
|
|||||||
from simplejson import dumps, loads
|
from simplejson import dumps, loads
|
||||||
except ImportError: # pragma: no cover
|
except ImportError: # pragma: no cover
|
||||||
from json import dumps, loads # noqa
|
from json import dumps, loads # noqa
|
||||||
from itertools import chain
|
from itertools import chain, tee
|
||||||
from mimetypes import guess_type, add_type
|
from mimetypes import guess_type, add_type
|
||||||
from os.path import splitext
|
from os.path import splitext
|
||||||
import logging
|
import logging
|
||||||
import operator
|
import operator
|
||||||
|
import types
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
@@ -566,7 +567,26 @@ class PecanBase(object):
|
|||||||
elif result:
|
elif result:
|
||||||
resp.body = result
|
resp.body = result
|
||||||
elif response.status_int == 200:
|
elif response.status_int == 200:
|
||||||
resp.status = 204
|
# If the response is a generator...
|
||||||
|
if isinstance(response.app_iter, types.GeneratorType):
|
||||||
|
# Split the generator into two so we can peek at one of them
|
||||||
|
# and determine if there is any response body content
|
||||||
|
a, b = tee(response.app_iter)
|
||||||
|
try:
|
||||||
|
next(a)
|
||||||
|
except StopIteration:
|
||||||
|
# If we hit StopIteration, the body is empty
|
||||||
|
resp.status = 204
|
||||||
|
finally:
|
||||||
|
resp.app_iter = b
|
||||||
|
else:
|
||||||
|
text = None
|
||||||
|
if response.charset:
|
||||||
|
# `response.text` cannot be accessed without a charset
|
||||||
|
# (because we don't know which encoding to use)
|
||||||
|
text = response.text
|
||||||
|
if not any((response.body, text)):
|
||||||
|
resp.status = 204
|
||||||
|
|
||||||
if resp.status_int in (204, 304):
|
if resp.status_int in (204, 304):
|
||||||
resp.content_type = None
|
resp.content_type = None
|
||||||
|
|||||||
@@ -44,6 +44,30 @@ class TestEmptyContent(PecanTestCase):
|
|||||||
def index(self):
|
def index(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@expose()
|
||||||
|
def explicit_body(self):
|
||||||
|
response.body = b_('Hello, World!')
|
||||||
|
|
||||||
|
@expose()
|
||||||
|
def empty_body(self):
|
||||||
|
response.body = b_('')
|
||||||
|
|
||||||
|
@expose()
|
||||||
|
def explicit_text(self):
|
||||||
|
response.text = six.text_type('Hello, World!')
|
||||||
|
|
||||||
|
@expose()
|
||||||
|
def empty_text(self):
|
||||||
|
response.text = six.text_type('')
|
||||||
|
|
||||||
|
@expose()
|
||||||
|
def explicit_json(self):
|
||||||
|
response.json = {'foo': 'bar'}
|
||||||
|
|
||||||
|
@expose()
|
||||||
|
def explicit_json_body(self):
|
||||||
|
response.json_body = {'foo': 'bar'}
|
||||||
|
|
||||||
return TestApp(Pecan(RootController()))
|
return TestApp(Pecan(RootController()))
|
||||||
|
|
||||||
def test_empty_index(self):
|
def test_empty_index(self):
|
||||||
@@ -53,6 +77,65 @@ class TestEmptyContent(PecanTestCase):
|
|||||||
self.assertEqual(r.headers['Content-Length'], '0')
|
self.assertEqual(r.headers['Content-Length'], '0')
|
||||||
self.assertEqual(len(r.body), 0)
|
self.assertEqual(len(r.body), 0)
|
||||||
|
|
||||||
|
def test_explicit_body(self):
|
||||||
|
r = self.app_.get('/explicit_body/')
|
||||||
|
self.assertEqual(r.status_int, 200)
|
||||||
|
self.assertEqual(r.body, b_('Hello, World!'))
|
||||||
|
|
||||||
|
def test_empty_body(self):
|
||||||
|
r = self.app_.get('/empty_body/')
|
||||||
|
self.assertEqual(r.status_int, 204)
|
||||||
|
self.assertEqual(r.body, b_(''))
|
||||||
|
|
||||||
|
def test_explicit_text(self):
|
||||||
|
r = self.app_.get('/explicit_text/')
|
||||||
|
self.assertEqual(r.status_int, 200)
|
||||||
|
self.assertEqual(r.body, b_('Hello, World!'))
|
||||||
|
|
||||||
|
def test_empty_text(self):
|
||||||
|
r = self.app_.get('/empty_text/')
|
||||||
|
self.assertEqual(r.status_int, 204)
|
||||||
|
self.assertEqual(r.body, b_(''))
|
||||||
|
|
||||||
|
def test_explicit_json(self):
|
||||||
|
r = self.app_.get('/explicit_json/')
|
||||||
|
self.assertEqual(r.status_int, 200)
|
||||||
|
json_resp = json.loads(r.body.decode())
|
||||||
|
assert json_resp == {'foo': 'bar'}
|
||||||
|
|
||||||
|
def test_explicit_json_body(self):
|
||||||
|
r = self.app_.get('/explicit_json_body/')
|
||||||
|
self.assertEqual(r.status_int, 200)
|
||||||
|
json_resp = json.loads(r.body.decode())
|
||||||
|
assert json_resp == {'foo': 'bar'}
|
||||||
|
|
||||||
|
|
||||||
|
class TestAppIterFile(PecanTestCase):
|
||||||
|
@property
|
||||||
|
def app_(self):
|
||||||
|
class RootController(object):
|
||||||
|
@expose()
|
||||||
|
def index(self):
|
||||||
|
body = six.BytesIO(b_('Hello, World!'))
|
||||||
|
response.body_file = body
|
||||||
|
|
||||||
|
@expose()
|
||||||
|
def empty(self):
|
||||||
|
body = six.BytesIO(b_(''))
|
||||||
|
response.body_file = body
|
||||||
|
|
||||||
|
return TestApp(Pecan(RootController()))
|
||||||
|
|
||||||
|
def test_body_generator(self):
|
||||||
|
r = self.app_.get('/')
|
||||||
|
self.assertEqual(r.status_int, 200)
|
||||||
|
assert r.body == b_('Hello, World!')
|
||||||
|
|
||||||
|
def test_empty_body_generator(self):
|
||||||
|
r = self.app_.get('/empty')
|
||||||
|
self.assertEqual(r.status_int, 204)
|
||||||
|
assert len(r.body) == 0
|
||||||
|
|
||||||
|
|
||||||
class TestIndexRouting(PecanTestCase):
|
class TestIndexRouting(PecanTestCase):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user