diff --git a/vumi_twilio_api/tests/test_twilio_api.py b/vumi_twilio_api/tests/test_twilio_api.py index 332debc..3592f43 100644 --- a/vumi_twilio_api/tests/test_twilio_api.py +++ b/vumi_twilio_api/tests/test_twilio_api.py @@ -60,6 +60,22 @@ def test_root_json(self): content = yield response.json() self.assertEqual(content, {}) + @inlineCallbacks + def test_root_invalid_format(self): + response = yield self._server_request('.foo') + self.assertEqual( + response.headers.getRawHeaders('content-type'), + ['application/xml']) + self.assertEqual(response.code, 400) + content = yield response.content() + root = ET.fromstring(content) + [error_message, error_type] = sorted(root, key=lambda c: c.tag) + self.assertEqual(error_message.tag, 'error_message') + self.assertEqual( + error_message.text, "'foo' is not a valid request format") + self.assertEqual(error_type.tag, 'error_type') + self.assertEqual(error_type.text, 'UsageError') + class TestServerFormatting(TestCase): diff --git a/vumi_twilio_api/twilio_api.py b/vumi_twilio_api/twilio_api.py index 0348db1..71df373 100644 --- a/vumi_twilio_api/twilio_api.py +++ b/vumi_twilio_api/twilio_api.py @@ -34,6 +34,13 @@ def teardown_application(self): yield self.webserver.loseConnection() +class TwilioAPIUsageException(Exception): + """Called when in incorrect query is sent to the API""" + def __init__(self, message, format_='xml'): + super(TwilioAPIUsageException, self).__init__(message) + self.format_ = format_ + + class TwilioAPIServer(object): app = Klein() @@ -60,10 +67,23 @@ def format_json(dct): def _format_response(self, request, dct, format_): format_ = str(format_.lstrip('.').lower()) func = getattr( - TwilioAPIServer, 'format_' + format_, TwilioAPIServer.format_xml) + TwilioAPIServer, 'format_' + format_, None) + if not func: + raise TwilioAPIUsageException( + '%r is not a valid request format' % format_) request.setHeader('Content-Type', 'application/%s' % format_) return func(dct) + @app.handle_errors(TwilioAPIUsageException) + def usage_exception(self, request, failure): + request.setResponseCode(400) + return self._format_response( + request, { + 'error_type': 'UsageError', + 'error_message': failure.value.message + }, + failure.value.format_) + @app.route('/', defaults={'format_': 'xml'}, methods=['GET']) @app.route('/', methods=['GET']) def root(self, request, format_):