def handler(request, mapper, help_view): """ XML-RPC handler. If post data is defined, it assumes it's XML-RPC and tries to process as such. Empty POST request and GET requests assumes you're viewing from a browser and tells you about the service by redirecting you to a dedicated help page. For backwards compatibility the help view defaults to the 'default_help' that shows what is registered in the global mapper. If you want to show help specific to your mapper you must specify help_view. It accepts whatever django.shortcuts.redirect() would. """ if len(request.body): raw_data = request.body dispatcher = Dispatcher(mapper) auth_string = request.META.get('HTTP_AUTHORIZATION') if auth_string is not None: if ' ' not in auth_string: return HttpResponse("Invalid HTTP_AUTHORIZATION header", status=400) scheme, value = auth_string.split(" ", 1) if scheme != "Basic": return HttpResponse( "Unsupported HTTP_AUTHORIZATION header, only Basic scheme is supported", status=400) try: decoded_value = base64.standard_b64decode(value) except TypeError: return HttpResponse( "Corrupted HTTP_AUTHORIZATION header, bad base64 encoding", status=400) try: username, secret = decoded_value.split(":", 1) except ValueError: return HttpResponse( "Corrupted HTTP_AUTHORIZATION header, no user:pass", status=400) user = None try: user = AuthToken.get_user_for_secret(username, secret) except Exception: logging.exception("bug") if user is None: response = HttpResponse("Invalid token", status=401) response[ 'WWW-Authenticate'] = 'Basic realm="XML-RPC Authentication token"' return response else: user = request.user result = dispatcher.marshalled_dispatch(raw_data, user, request) response = HttpResponse(content_type="application/xml") response.write(result) response['Content-length'] = str(len(response.content)) return response else: return redirect(help_view)
def handler(request, mapper, help_view): """ XML-RPC handler. If post data is defined, it assumes it's XML-RPC and tries to process as such. Empty POST request and GET requests assumes you're viewing from a browser and tells you about the service by redirecting you to a dedicated help page. For backwards compatibility the help view defaults to the 'default_help' that shows what is registered in the global mapper. If you want to show help specific to your mapper you must specify help_view. It accepts whatever django.shortcuts.redirect() would. """ if len(request.body): raw_data = request.body dispatcher = Dispatcher(mapper) auth_string = request.META.get('HTTP_AUTHORIZATION') if auth_string is not None: if ' ' not in auth_string: return HttpResponse("Invalid HTTP_AUTHORIZATION header", status=400) scheme, value = auth_string.split(" ", 1) if scheme != "Basic": return HttpResponse( "Unsupported HTTP_AUTHORIZATION header, only Basic scheme is supported", status=400) try: decoded_value = base64.standard_b64decode(value) except TypeError: return HttpResponse("Corrupted HTTP_AUTHORIZATION header, bad base64 encoding", status=400) try: username, secret = decoded_value.split(":", 1) except ValueError: return HttpResponse("Corrupted HTTP_AUTHORIZATION header, no user:pass", status=400) user = None try: user = AuthToken.get_user_for_secret(username, secret) except Exception: logging.exception("bug") if user is None: response = HttpResponse("Invalid token", status=401) response['WWW-Authenticate'] = 'Basic realm="XML-RPC Authentication token"' return response else: user = request.user result = dispatcher.marshalled_dispatch(raw_data, user, request) response = HttpResponse(content_type="application/xml") response.write(result) response['Content-length'] = str(len(response.content)) return response else: return redirect(help_view)
def setUp(self): super(SystemAPITest, self).setUp() self.mapper = Mapper() self.dispatcher = Dispatcher(self.mapper) self.context = CallContext( user=None, mapper=self.mapper, dispatcher=self.dispatcher) self.system_api = SystemAPI(self.context)
def setUp(self): super(DispatcherTests, self).setUp() self.mapper = Mapper() self.mapper.register(TestAPI, '') self.dispatcher = Dispatcher(self.mapper)
class DispatcherTests(TestCase): def setUp(self): super(DispatcherTests, self).setUp() self.mapper = Mapper() self.mapper.register(TestAPI, '') self.dispatcher = Dispatcher(self.mapper) def xml_rpc_call(self, method, *args): """ Perform XML-RPC call on our internal dispatcher instance This calls the method just like we would have normally from our view. All arguments are marshaled and un-marshaled. XML-RPC fault exceptions are raised like normal python exceptions (by xmlrpclib.loads) """ request = xmlrpclib.dumps(tuple(args), methodname=method) response = self.dispatcher.marshalled_dispatch(request) # This returns return value wrapped in a tuple and method name # (which we don't have here as this is a response message). return xmlrpclib.loads(response)[0][0] def test_standard_fault_code_for_method_not_found(self): try: self.xml_rpc_call("method_that_does_not_exist") except xmlrpclib.Fault as ex: self.assertEqual(ex.faultCode, FaultCodes.ServerError.REQUESTED_METHOD_NOT_FOUND) else: self.fail("Calling missing method did not raise an exception") def test_internal_error_handler_is_called_on_exception(self): self.was_called = False def handler(method, params): self.assertEqual(method, 'internal_boom') self.assertEqual(params, ()) self.was_called = True self.dispatcher.handle_internal_error = handler try: self.xml_rpc_call("internal_boom") except xmlrpclib.Fault: pass else: self.fail("Exception not raised") self.assertTrue(self.was_called) def test_standard_fault_code_for_internal_error(self): # This handler is here just to prevent the default one from # spamming the console with the error that is raised inside the # internal_boom() method self.dispatcher.handle_internal_error = lambda method, args: None try: self.xml_rpc_call("internal_boom") except xmlrpclib.Fault as ex: self.assertEqual(ex.faultCode, FaultCodes.ServerError.INTERNAL_XML_RPC_ERROR) else: self.fail("Exception not raised") def test_ping(self): retval = self.xml_rpc_call("ping") self.assertEqual(retval, "pong") def test_echo(self): self.assertEqual(self.xml_rpc_call("echo", 1), 1) self.assertEqual(self.xml_rpc_call("echo", "string"), "string") self.assertEqual(self.xml_rpc_call("echo", 1.5), 1.5) def test_boom(self): self.assertRaises(xmlrpclib.Fault, self.xml_rpc_call, "boom", 1, "str")
class DispatcherTests(TestCase): def setUp(self): super(DispatcherTests, self).setUp() self.mapper = Mapper() self.mapper.register(TestAPI, '') self.dispatcher = Dispatcher(self.mapper) def xml_rpc_call(self, method, *args): """ Perform XML-RPC call on our internal dispatcher instance This calls the method just like we would have normally from our view. All arguments are marshaled and un-marshaled. XML-RPC fault exceptions are raised like normal python exceptions (by xmlrpclib.loads) """ request = xmlrpclib.dumps(tuple(args), methodname=method) response = self.dispatcher.marshalled_dispatch(request) # This returns return value wrapped in a tuple and method name # (which we don't have here as this is a response message). return xmlrpclib.loads(response)[0][0] def test_standard_fault_code_for_method_not_found(self): try: self.xml_rpc_call("method_that_does_not_exist") except xmlrpclib.Fault as ex: self.assertEqual( ex.faultCode, FaultCodes.ServerError.REQUESTED_METHOD_NOT_FOUND) else: self.fail("Calling missing method did not raise an exception") def test_internal_error_handler_is_called_on_exception(self): self.was_called = False def handler(method, params): self.assertEqual(method, 'internal_boom') self.assertEqual(params, ()) self.was_called = True self.dispatcher.handle_internal_error = handler try: self.xml_rpc_call("internal_boom") except xmlrpclib.Fault: pass else: self.fail("Exception not raised") self.assertTrue(self.was_called) def test_standard_fault_code_for_internal_error(self): # This handler is here just to prevent the default one from # spamming the console with the error that is raised inside the # internal_boom() method self.dispatcher.handle_internal_error = lambda method, args: None try: self.xml_rpc_call("internal_boom") except xmlrpclib.Fault as ex: self.assertEqual( ex.faultCode, FaultCodes.ServerError.INTERNAL_XML_RPC_ERROR) else: self.fail("Exception not raised") def test_ping(self): retval = self.xml_rpc_call("ping") self.assertEqual(retval, "pong") def test_echo(self): self.assertEqual(self.xml_rpc_call("echo", 1), 1) self.assertEqual(self.xml_rpc_call("echo", "string"), "string") self.assertEqual(self.xml_rpc_call("echo", 1.5), 1.5) def test_boom(self): self.assertRaises(xmlrpclib.Fault, self.xml_rpc_call, "boom", 1, "str")
def setUp(self): super().setUp() self.mapper = Mapper() self.mapper.register(TestAPI, "") self.dispatcher = Dispatcher(self.mapper)