Esempio n. 1
0
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)
Esempio n. 2
0
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)
Esempio n. 3
0
 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)
Esempio n. 4
0
 def setUp(self):
     super(DispatcherTests, self).setUp()
     self.mapper = Mapper()
     self.mapper.register(TestAPI, '')
     self.dispatcher = Dispatcher(self.mapper)
Esempio n. 5
0
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")
Esempio n. 6
0
 def setUp(self):
     super(DispatcherTests, self).setUp()
     self.mapper = Mapper()
     self.mapper.register(TestAPI, '')
     self.dispatcher = Dispatcher(self.mapper)
Esempio n. 7
0
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")
Esempio n. 8
0
 def setUp(self):
     super().setUp()
     self.mapper = Mapper()
     self.mapper.register(TestAPI, "")
     self.dispatcher = Dispatcher(self.mapper)