Skip to content

Commit a39571b

Browse files
committed
web: do not send content on HTTPError(204)
Change `write_error()` to not send body if status code in (204, 304) or (100 <= status code < 200) - refactored into `RequestHandler._should_not_send_content(status_code)` Change `get_arguments()` to raise `ValueError` if `strip` is not boolean - as opposed to `AssertionError`. Fixes #3360
1 parent bdfc017 commit a39571b

File tree

2 files changed

+22
-5
lines changed

2 files changed

+22
-5
lines changed

Diff for: tornado/test/web_test.py

+12
Original file line numberDiff line numberDiff line change
@@ -1691,6 +1691,18 @@ def test_204_headers(self):
16911691
self.assertNotIn("Transfer-Encoding", response.headers)
16921692

16931693

1694+
class Header204viaHTTPErrorTest(SimpleHandlerTestCase):
1695+
class Handler(RequestHandler):
1696+
def get(self):
1697+
raise HTTPError(204)
1698+
1699+
def test_204_headers_via_httperror(self):
1700+
response = self.fetch("/")
1701+
self.assertEqual(response.code, 204)
1702+
self.assertNotIn("Content-Length", response.headers)
1703+
self.assertNotIn("Transfer-Encoding", response.headers)
1704+
1705+
16941706
class Header304Test(SimpleHandlerTestCase):
16951707
class Handler(RequestHandler):
16961708
def get(self):

Diff for: tornado/web.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,10 @@ def flush(self, include_footers: bool = False) -> "Future[None]":
12221222
future.set_result(None)
12231223
return future
12241224

1225+
def _should_not_send_content(self, status_code: int) -> bool:
1226+
"""Check if we should not send body content for given `status_code`"""
1227+
return status_code in (204, 304) or (100 <= status_code < 200)
1228+
12251229
def finish(self, chunk: Optional[Union[str, bytes, dict]] = None) -> "Future[None]":
12261230
"""Finishes this response, ending the HTTP request.
12271231
@@ -1255,10 +1259,9 @@ def finish(self, chunk: Optional[Union[str, bytes, dict]] = None) -> "Future[Non
12551259
if self.check_etag_header():
12561260
self._write_buffer = []
12571261
self.set_status(304)
1258-
if self._status_code in (204, 304) or (100 <= self._status_code < 200):
1259-
assert not self._write_buffer, (
1260-
"Cannot send body with %s" % self._status_code
1261-
)
1262+
if self._should_not_send_content(self._status_code):
1263+
if self._write_buffer:
1264+
raise RuntimeError(f"Cannot send body with status code HTTP{self._status_code}")
12621265
self._clear_representation_headers()
12631266
elif "Content-Length" not in self._headers:
12641267
content_length = sum(len(part) for part in self._write_buffer)
@@ -1349,7 +1352,9 @@ def write_error(self, status_code: int, **kwargs: Any) -> None:
13491352
the "current" exception for purposes of methods like
13501353
``sys.exc_info()`` or ``traceback.format_exc``.
13511354
"""
1352-
if self.settings.get("serve_traceback") and "exc_info" in kwargs:
1355+
if self._should_not_send_content(status_code):
1356+
self.finish()
1357+
elif self.settings.get("serve_traceback") and "exc_info" in kwargs:
13531358
# in debug mode, try to send a traceback
13541359
self.set_header("Content-Type", "text/plain")
13551360
for line in traceback.format_exception(*kwargs["exc_info"]):

0 commit comments

Comments
 (0)