summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2022-04-26 23:16:08 -0500
committerGitHub <noreply@github.com>2022-04-26 23:16:08 -0500
commit3066fdd7d558bbd0023b7885900419483251a0f8 (patch)
tree14a2de14b5b11b1ee50e9740a019692291761aa8
parent603d2c12ce09fcd1be0b7a5734b4fca339820286 (diff)
parent4467d76725998d921c3e550479a88eca367bccc6 (diff)
downloadwaitress-3066fdd7d558bbd0023b7885900419483251a0f8.tar.gz
Merge pull request #378 from Pylons/bugfix/expose_tracebacks-encode-error
Bugfix: expose_tracebacks encode error
-rw-r--r--src/waitress/task.py2
-rw-r--r--src/waitress/utilities.py4
-rw-r--r--tests/fixtureapps/error_traceback.py2
-rw-r--r--tests/test_functional.py64
-rw-r--r--tests/test_proxy_headers.py4
-rw-r--r--tests/test_task.py8
6 files changed, 70 insertions, 14 deletions
diff --git a/src/waitress/task.py b/src/waitress/task.py
index a003919..3bc7f7c 100644
--- a/src/waitress/task.py
+++ b/src/waitress/task.py
@@ -355,7 +355,7 @@ class ErrorTask(Task):
self.response_headers.append(("Connection", "close"))
self.close_on_finish = True
self.content_length = len(body)
- self.write(body.encode("latin-1"))
+ self.write(body)
class WSGITask(Task):
diff --git a/src/waitress/utilities.py b/src/waitress/utilities.py
index 6ae4742..a9d3361 100644
--- a/src/waitress/utilities.py
+++ b/src/waitress/utilities.py
@@ -262,8 +262,8 @@ class Error:
status = "%s %s" % (self.code, self.reason)
body = "%s\r\n\r\n%s" % (self.reason, self.body)
tag = "\r\n\r\n(generated by waitress)"
- body = body + tag
- headers = [("Content-Type", "text/plain")]
+ body = (body + tag).encode("utf-8")
+ headers = [("Content-Type", "text/plain; charset=utf-8")]
return status, headers, body
diff --git a/tests/fixtureapps/error_traceback.py b/tests/fixtureapps/error_traceback.py
new file mode 100644
index 0000000..24e4cbf
--- /dev/null
+++ b/tests/fixtureapps/error_traceback.py
@@ -0,0 +1,2 @@
+def app(environ, start_response): # pragma: no cover
+ raise ValueError("Invalid application: " + chr(8364))
diff --git a/tests/test_functional.py b/tests/test_functional.py
index 60eb24a..1dfd889 100644
--- a/tests/test_functional.py
+++ b/tests/test_functional.py
@@ -359,7 +359,7 @@ class EchoTests:
sorted(headers.keys()),
["connection", "content-length", "content-type", "date", "server"],
)
- self.assertEqual(headers["content-type"], "text/plain")
+ self.assertEqual(headers["content-type"], "text/plain; charset=utf-8")
# connection has been closed
self.send_check_error(to_send)
self.assertRaises(ConnectionClosed, read_http, fp)
@@ -381,7 +381,7 @@ class EchoTests:
sorted(headers.keys()),
["connection", "content-length", "content-type", "date", "server"],
)
- self.assertEqual(headers["content-type"], "text/plain")
+ self.assertEqual(headers["content-type"], "text/plain; charset=utf-8")
# connection has been closed
self.send_check_error(to_send)
self.assertRaises(ConnectionClosed, read_http, fp)
@@ -403,7 +403,7 @@ class EchoTests:
sorted(headers.keys()),
["connection", "content-length", "content-type", "date", "server"],
)
- self.assertEqual(headers["content-type"], "text/plain")
+ self.assertEqual(headers["content-type"], "text/plain; charset=utf-8")
# connection has been closed
self.send_check_error(to_send)
self.assertRaises(ConnectionClosed, read_http, fp)
@@ -428,7 +428,7 @@ class EchoTests:
sorted(headers.keys()),
["connection", "content-length", "content-type", "date", "server"],
)
- self.assertEqual(headers["content-type"], "text/plain")
+ self.assertEqual(headers["content-type"], "text/plain; charset=utf-8")
# connection has been closed
self.send_check_error(to_send)
self.assertRaises(ConnectionClosed, read_http, fp)
@@ -1121,7 +1121,7 @@ class TooLargeTests:
self.assertline(line, "413", "Request Entity Too Large", "HTTP/1.1")
cl = int(headers["content-length"])
self.assertEqual(cl, len(response_body))
- self.assertEqual(headers["content-type"], "text/plain")
+ self.assertEqual(headers["content-type"], "text/plain; charset=utf-8")
# connection has been closed
self.send_check_error(to_send)
self.assertRaises(ConnectionClosed, read_http, fp)
@@ -1269,6 +1269,49 @@ class InternalServerErrorTests:
self.assertRaises(ConnectionClosed, read_http, fp)
+class InternalServerErrorTestsWithTraceback:
+ def setUp(self):
+ from tests.fixtureapps import error_traceback
+
+ self.start_subprocess(error_traceback.app, expose_tracebacks=True)
+
+ def tearDown(self):
+ self.stop_subprocess()
+
+ def test_expose_tracebacks_http_10(self):
+ to_send = b"GET / HTTP/1.0\r\n\r\n"
+ self.connect()
+ self.sock.send(to_send)
+ with self.sock.makefile("rb", 0) as fp:
+ line, headers, response_body = read_http(fp)
+ self.assertline(line, "500", "Internal Server Error", "HTTP/1.0")
+ cl = int(headers["content-length"])
+ self.assertEqual(cl, len(response_body))
+ self.assertTrue(response_body.startswith(b"Internal Server Error"))
+ self.assertEqual(headers["connection"], "close")
+ # connection has been closed
+ self.send_check_error(to_send)
+ self.assertRaises(ConnectionClosed, read_http, fp)
+
+ def test_expose_tracebacks_http_11(self):
+ to_send = b"GET / HTTP/1.1\r\n\r\n"
+ self.connect()
+ self.sock.send(to_send)
+ with self.sock.makefile("rb", 0) as fp:
+ line, headers, response_body = read_http(fp)
+ self.assertline(line, "500", "Internal Server Error", "HTTP/1.1")
+ cl = int(headers["content-length"])
+ self.assertEqual(cl, len(response_body))
+ self.assertTrue(response_body.startswith(b"Internal Server Error"))
+ self.assertEqual(
+ sorted(headers.keys()),
+ ["connection", "content-length", "content-type", "date", "server"],
+ )
+ # connection has been closed
+ self.send_check_error(to_send)
+ self.assertRaises(ConnectionClosed, read_http, fp)
+
+
class FileWrapperTests:
def setUp(self):
from tests.fixtureapps import filewrapper
@@ -1538,6 +1581,12 @@ class TcpInternalServerErrorTests(
pass
+class TcpInternalServerErrorTestsWithTraceback(
+ InternalServerErrorTestsWithTraceback, TcpTests, unittest.TestCase
+):
+ pass
+
+
class TcpFileWrapperTests(FileWrapperTests, TcpTests, unittest.TestCase):
pass
@@ -1604,6 +1653,11 @@ if hasattr(socket, "AF_UNIX"):
):
pass
+ class UnixInternalServerErrorTestsWithTraceback(
+ InternalServerErrorTestsWithTraceback, UnixTests, unittest.TestCase
+ ):
+ pass
+
class UnixFileWrapperTests(FileWrapperTests, UnixTests, unittest.TestCase):
pass
diff --git a/tests/test_proxy_headers.py b/tests/test_proxy_headers.py
index 9ed131e..45f9878 100644
--- a/tests/test_proxy_headers.py
+++ b/tests/test_proxy_headers.py
@@ -16,7 +16,7 @@ class TestProxyHeadersMiddleware(unittest.TestCase):
response.headers = response_headers
response.steps = list(app(environ, start_response))
- response.body = b"".join(s.encode("latin-1") for s in response.steps)
+ response.body = b"".join(s for s in response.steps)
return response
def test_get_environment_values_w_scheme_override_untrusted(self):
@@ -727,7 +727,7 @@ class DummyApp:
def __call__(self, environ, start_response):
self.environ = environ
start_response("200 OK", [("Content-Type", "text/plain")])
- yield "hello"
+ yield b"hello"
class DummyResponse:
diff --git a/tests/test_task.py b/tests/test_task.py
index cc579b0..47868e1 100644
--- a/tests/test_task.py
+++ b/tests/test_task.py
@@ -869,7 +869,7 @@ class TestErrorTask(unittest.TestCase):
self.assertEqual(lines[0], b"HTTP/1.0 432 Too Ugly")
self.assertEqual(lines[1], b"Connection: close")
self.assertEqual(lines[2], b"Content-Length: 43")
- self.assertEqual(lines[3], b"Content-Type: text/plain")
+ self.assertEqual(lines[3], b"Content-Type: text/plain; charset=utf-8")
self.assertTrue(lines[4])
self.assertEqual(lines[5], b"Server: waitress")
self.assertEqual(lines[6], b"Too Ugly")
@@ -885,7 +885,7 @@ class TestErrorTask(unittest.TestCase):
self.assertEqual(lines[0], b"HTTP/1.1 432 Too Ugly")
self.assertEqual(lines[1], b"Connection: close")
self.assertEqual(lines[2], b"Content-Length: 43")
- self.assertEqual(lines[3], b"Content-Type: text/plain")
+ self.assertEqual(lines[3], b"Content-Type: text/plain; charset=utf-8")
self.assertTrue(lines[4])
self.assertEqual(lines[5], b"Server: waitress")
self.assertEqual(lines[6], b"Too Ugly")
@@ -902,7 +902,7 @@ class TestErrorTask(unittest.TestCase):
self.assertEqual(lines[0], b"HTTP/1.1 432 Too Ugly")
self.assertEqual(lines[1], b"Connection: close")
self.assertEqual(lines[2], b"Content-Length: 43")
- self.assertEqual(lines[3], b"Content-Type: text/plain")
+ self.assertEqual(lines[3], b"Content-Type: text/plain; charset=utf-8")
self.assertTrue(lines[4])
self.assertEqual(lines[5], b"Server: waitress")
self.assertEqual(lines[6], b"Too Ugly")
@@ -919,7 +919,7 @@ class TestErrorTask(unittest.TestCase):
self.assertEqual(lines[0], b"HTTP/1.1 432 Too Ugly")
self.assertEqual(lines[1], b"Connection: close")
self.assertEqual(lines[2], b"Content-Length: 43")
- self.assertEqual(lines[3], b"Content-Type: text/plain")
+ self.assertEqual(lines[3], b"Content-Type: text/plain; charset=utf-8")
self.assertTrue(lines[4])
self.assertEqual(lines[5], b"Server: waitress")
self.assertEqual(lines[6], b"Too Ugly")