From 94d0949ac6565f329b79fc54e9f56d335cdc647a Mon Sep 17 00:00:00 2001 From: amitt001 Date: Thu, 27 Oct 2016 10:50:42 +0530 Subject: Rest api send error response with headers --- src/mailman/rest/wsgiapp.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py index f3290416e..4e05069b4 100644 --- a/src/mailman/rest/wsgiapp.py +++ b/src/mailman/rest/wsgiapp.py @@ -18,6 +18,7 @@ """Basic WSGI Application object for REST server.""" import re +import time import logging from base64 import b64decode @@ -63,7 +64,8 @@ class StderrLogger: class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): - """Handler class which just logs output to the right place.""" + """Handler class which logs output to the right place and prepend headers + to the error response.""" def log_message(self, format, *args): """See `BaseHTTPRequestHandler`.""" @@ -74,6 +76,26 @@ class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): # the log file. return StderrLogger() + def send_error(self, code, message=None, explain=None): + """See `BaseHTTPRequestHandler`.""" + err_code = "{0} {1}".format(code.value, code.name.replace('_', ' ')) + header_dict = dict( + status="{0} {1}".format(self.request_version, err_code), + rsp_date=time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.gmtime()), + server="{0} {1}".format(self.server_version, self.sys_version), + content_type=self.error_content_type) + # Prepare headers and prepend it to the error response body + error_headers = ("""\ +%(status)s +Date: %(rsp_date)s +Server: %(server)s +content-type: %(content_type)s\n +""" % header_dict) + self.error_message_format = error_headers + self.error_message_format + # Let parent method handle rest of the logic + super().send_error(code, message, explain) + + class Middleware: """Falcon middleware object for Mailman's REST API. -- cgit v1.2.3-70-g09d2 From 61347daf381156ddd63b3983b105c2412c22f998 Mon Sep 17 00:00:00 2001 From: amitt001 Date: Fri, 28 Oct 2016 00:55:31 +0530 Subject: Test invalid url response. --- src/mailman/rest/tests/test_basic.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/mailman/rest/tests/test_basic.py b/src/mailman/rest/tests/test_basic.py index 64c60842c..fade3ed40 100644 --- a/src/mailman/rest/tests/test_basic.py +++ b/src/mailman/rest/tests/test_basic.py @@ -26,6 +26,7 @@ from mailman.app.lifecycle import create_list from mailman.database.transaction import transaction from mailman.testing.helpers import call_api from mailman.testing.layers import RESTLayer +from urllib.error import HTTPError class TestBasicREST(unittest.TestCase): @@ -45,3 +46,10 @@ class TestBasicREST(unittest.TestCase): # This fails with Falcon 0.2; passes with Falcon 0.3. self.assertEqual(self._mlist.description, 'A description with , to check stuff') + + def test_send_error(self): + # Test `AdminWebServiceWSGIRequestHandler` `send_error`. + # Return 400 for invalid url. + with self.assertRaises(HTTPError) as cm: + call_api('http://localhost:9001/3.0/lists/test @example.com') + self.assertEqual(cm.exception.code, 400) -- cgit v1.2.3-70-g09d2 From 7c0cbd970cca597a00ebe31687a36bccfb25445d Mon Sep 17 00:00:00 2001 From: amitt001 Date: Fri, 28 Oct 2016 01:07:55 +0530 Subject: qa fix --- src/mailman/rest/wsgiapp.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py index 4e05069b4..fe1a9fd63 100644 --- a/src/mailman/rest/wsgiapp.py +++ b/src/mailman/rest/wsgiapp.py @@ -96,7 +96,6 @@ content-type: %(content_type)s\n super().send_error(code, message, explain) - class Middleware: """Falcon middleware object for Mailman's REST API. -- cgit v1.2.3-70-g09d2 From 2545dc1e752a960f4dc0d0e48426fdfd9ef79cb6 Mon Sep 17 00:00:00 2001 From: amitt001 Date: Fri, 28 Oct 2016 11:06:33 +0530 Subject: < python 3.5.x non-enum HTTPStatus support --- src/mailman/rest/wsgiapp.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py index fe1a9fd63..f499ec60b 100644 --- a/src/mailman/rest/wsgiapp.py +++ b/src/mailman/rest/wsgiapp.py @@ -78,7 +78,11 @@ class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): def send_error(self, code, message=None, explain=None): """See `BaseHTTPRequestHandler`.""" - err_code = "{0} {1}".format(code.value, code.name.replace('_', ' ')) + try: + shortmsg, longmsg = self.responses[code] + except KeyError: + shortmsg, longmsg = '???', '???' + err_code = "{0} {1}".format(int(code), shortmsg) header_dict = dict( status="{0} {1}".format(self.request_version, err_code), rsp_date=time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.gmtime()), -- cgit v1.2.3-70-g09d2 From a93b1b431b67714e6ae5b648165b8304eded2651 Mon Sep 17 00:00:00 2001 From: amitt001 Date: Fri, 28 Oct 2016 11:58:50 +0530 Subject: qa fix: unused variable --- src/mailman/rest/wsgiapp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py index f499ec60b..e31a46223 100644 --- a/src/mailman/rest/wsgiapp.py +++ b/src/mailman/rest/wsgiapp.py @@ -79,9 +79,9 @@ class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): def send_error(self, code, message=None, explain=None): """See `BaseHTTPRequestHandler`.""" try: - shortmsg, longmsg = self.responses[code] + shortmsg = self.responses[code][0] except KeyError: - shortmsg, longmsg = '???', '???' + shortmsg = '???' err_code = "{0} {1}".format(int(code), shortmsg) header_dict = dict( status="{0} {1}".format(self.request_version, err_code), -- cgit v1.2.3-70-g09d2 From 76d8d7d71b6573b9d36c4a280fb50f61f92764e0 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Sun, 30 Oct 2016 18:19:16 -0400 Subject: Support HTTP/1.1 by default. This works around Python issue 28548 and fixes #288. Test given by Amit. --- src/mailman/docs/NEWS.rst | 1 + src/mailman/rest/tests/test_basic.py | 4 ++-- src/mailman/rest/wsgiapp.py | 29 +++-------------------------- 3 files changed, 6 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst index 33f886d6f..926bb19aa 100644 --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -175,6 +175,7 @@ REST 3.0 except that UUIDs are represented as hex strings instead of 128-bit integers, since the latter are not compatible with all versions of JavaScript. (Closes #121) + * REST clients must minimally support HTTP/1.1. (Closes #288) * The new template system is introduced for API 3.1. See ``src/mailman/rest/docs/templates.rst`` for details. (Closes #249) * When creating a user via REST using an address that already exists, but diff --git a/src/mailman/rest/tests/test_basic.py b/src/mailman/rest/tests/test_basic.py index fade3ed40..23db57f8e 100644 --- a/src/mailman/rest/tests/test_basic.py +++ b/src/mailman/rest/tests/test_basic.py @@ -48,8 +48,8 @@ class TestBasicREST(unittest.TestCase): 'A description with , to check stuff') def test_send_error(self): - # Test `AdminWebServiceWSGIRequestHandler` `send_error`. - # Return 400 for invalid url. + # GL#288 working around Python bug #28548. The improperly encoded + # space in the URL breaks error reporting due to default HTTP/0.9. with self.assertRaises(HTTPError) as cm: call_api('http://localhost:9001/3.0/lists/test @example.com') self.assertEqual(cm.exception.code, 400) diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py index e31a46223..3ba122c00 100644 --- a/src/mailman/rest/wsgiapp.py +++ b/src/mailman/rest/wsgiapp.py @@ -18,7 +18,6 @@ """Basic WSGI Application object for REST server.""" import re -import time import logging from base64 import b64decode @@ -64,8 +63,9 @@ class StderrLogger: class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): - """Handler class which logs output to the right place and prepend headers - to the error response.""" + """Handler class which just logs output to the right place.""" + + default_request_version = 'HTTP/1.1' def log_message(self, format, *args): """See `BaseHTTPRequestHandler`.""" @@ -76,29 +76,6 @@ class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): # the log file. return StderrLogger() - def send_error(self, code, message=None, explain=None): - """See `BaseHTTPRequestHandler`.""" - try: - shortmsg = self.responses[code][0] - except KeyError: - shortmsg = '???' - err_code = "{0} {1}".format(int(code), shortmsg) - header_dict = dict( - status="{0} {1}".format(self.request_version, err_code), - rsp_date=time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.gmtime()), - server="{0} {1}".format(self.server_version, self.sys_version), - content_type=self.error_content_type) - # Prepare headers and prepend it to the error response body - error_headers = ("""\ -%(status)s -Date: %(rsp_date)s -Server: %(server)s -content-type: %(content_type)s\n -""" % header_dict) - self.error_message_format = error_headers + self.error_message_format - # Let parent method handle rest of the logic - super().send_error(code, message, explain) - class Middleware: """Falcon middleware object for Mailman's REST API. -- cgit v1.2.3-70-g09d2 From 20bda7007c6c8546ab403d65e8bf9e0bdfe4ad50 Mon Sep 17 00:00:00 2001 From: Aurélien Bompard Date: Fri, 16 Sep 2016 12:32:44 +0200 Subject: Remove digest mbox after sending it Fixes #259 --- src/mailman/runners/digest.py | 3 +++ src/mailman/runners/tests/test_digest.py | 3 +++ 2 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/mailman/runners/digest.py b/src/mailman/runners/digest.py index c591c10a9..4173d9673 100644 --- a/src/mailman/runners/digest.py +++ b/src/mailman/runners/digest.py @@ -17,6 +17,7 @@ """Digest runner.""" +import os import re import logging @@ -322,6 +323,8 @@ class DigestRunner(Runner): # Finish up the digests. mime = mime_digest.finish() rfc1153 = rfc1153_digest.finish() + # Remove the digest mbox (GL#259) + os.remove(msgdata['digest_path']) # Calculate the recipients lists mime_recipients = set() rfc1153_recipients = set() diff --git a/src/mailman/runners/tests/test_digest.py b/src/mailman/runners/tests/test_digest.py index 6157f500b..f0993cff3 100644 --- a/src/mailman/runners/tests/test_digest.py +++ b/src/mailman/runners/tests/test_digest.py @@ -75,6 +75,9 @@ class TestDigest(unittest.TestCase): bart.preferences.delivery_mode = DeliveryMode.plaintext_digests make_digest_messages(self._mlist) self._check_virgin_queue() + # The digest mbox must have been removed (GL#259) + self.assertFalse(os.path.exists( + os.path.join(self._mlist.data_path, 'digest.mmdf'))) def test_non_ascii_message(self): # Subscribe some users receiving digests. -- cgit v1.2.3-70-g09d2 From added3672526d4770c6b9da8883effc46a0a41da Mon Sep 17 00:00:00 2001 From: Aurélien Bompard Date: Thu, 27 Oct 2016 10:25:45 +0200 Subject: Implment review suggestions --- src/mailman/runners/digest.py | 4 ++-- src/mailman/runners/tests/test_digest.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/mailman/runners/digest.py b/src/mailman/runners/digest.py index 4173d9673..9b8335024 100644 --- a/src/mailman/runners/digest.py +++ b/src/mailman/runners/digest.py @@ -323,8 +323,6 @@ class DigestRunner(Runner): # Finish up the digests. mime = mime_digest.finish() rfc1153 = rfc1153_digest.finish() - # Remove the digest mbox (GL#259) - os.remove(msgdata['digest_path']) # Calculate the recipients lists mime_recipients = set() rfc1153_recipients = set() @@ -372,3 +370,5 @@ class DigestRunner(Runner): recipients=rfc1153_recipients, listid=mlist.list_id, isdigest=True) + # Remove the digest mbox (GL#259) + os.remove(msgdata['digest_path']) diff --git a/src/mailman/runners/tests/test_digest.py b/src/mailman/runners/tests/test_digest.py index f0993cff3..1565af262 100644 --- a/src/mailman/runners/tests/test_digest.py +++ b/src/mailman/runners/tests/test_digest.py @@ -75,9 +75,9 @@ class TestDigest(unittest.TestCase): bart.preferences.delivery_mode = DeliveryMode.plaintext_digests make_digest_messages(self._mlist) self._check_virgin_queue() - # The digest mbox must have been removed (GL#259) - self.assertFalse(os.path.exists( - os.path.join(self._mlist.data_path, 'digest.mmdf'))) + # The digest mbox and all intermediary mboxes must have been removed + # (GL#259). + self.assertEqual(os.listdir(self._mlist.data_path), []) def test_non_ascii_message(self): # Subscribe some users receiving digests. -- cgit v1.2.3-70-g09d2 From 366dc6517716b7c77c4b7a76559b1b6b5996fc8e Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Mon, 31 Oct 2016 18:32:57 -0400 Subject: Closes: #259 Remove the digest mbox files after the digests are sent. Given by Aurélien Bompard. --- src/mailman/docs/NEWS.rst | 2 ++ src/mailman/runners/digest.py | 2 +- src/mailman/runners/tests/test_digest.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst index 926bb19aa..f72498a1d 100644 --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -95,6 +95,8 @@ Bugs edit to work. (Closes: #290) * Prevent posting from banned addresses. Given by Aurélien Bompard. (Closes: #283) + * Remove the digest mbox files after the digests are sent. Given by Aurélien + Bompard. (Closes: #259) Configuration ------------- diff --git a/src/mailman/runners/digest.py b/src/mailman/runners/digest.py index 9b8335024..4971965fa 100644 --- a/src/mailman/runners/digest.py +++ b/src/mailman/runners/digest.py @@ -370,5 +370,5 @@ class DigestRunner(Runner): recipients=rfc1153_recipients, listid=mlist.list_id, isdigest=True) - # Remove the digest mbox (GL#259) + # Remove the digest mbox. (GL #259) os.remove(msgdata['digest_path']) diff --git a/src/mailman/runners/tests/test_digest.py b/src/mailman/runners/tests/test_digest.py index 1565af262..5246ef670 100644 --- a/src/mailman/runners/tests/test_digest.py +++ b/src/mailman/runners/tests/test_digest.py @@ -76,7 +76,7 @@ class TestDigest(unittest.TestCase): make_digest_messages(self._mlist) self._check_virgin_queue() # The digest mbox and all intermediary mboxes must have been removed - # (GL#259). + # (GL #259). self.assertEqual(os.listdir(self._mlist.data_path), []) def test_non_ascii_message(self): -- cgit v1.2.3-70-g09d2