Skip to content

Archive for December, 2009

9
Dec

RPC4Django v0.1.6 Feature Requests

A number of feature requests have come in and I am going to outline what I’m going to try to get done. I hope to put out a release next week (I’ve said that before), but that greatly depends on what features go into it.

Access to HttpRequest

One user submitted feature that seems particularly useful is the ability to access variables and data in the HttpRequest that dispatches the RPC method. For example:

@rpcmethod(permission='myproject.mypermission')
def testmethod(a, b, c):
    # Do something

This RPC method will be authenticated, but it cannot tell who the user is for example. It does not have the ability to read the REMOTE_USER variable. This would be particularly useful if the RPC method was submitting data and needed to know who the submitter was. To rectify this situation, I am proposing sending the HttpRequest object as a keyword argument:

@rpcmethod(permission='myproject.mypermission')
def testmethod(a, b, c, **kwargs):
    if 'REMOTE_USER' in kwargs['request'].META:
        user = request.kwargs.META['REMOTE_USER']
        # Do something

Methods that need access can accept all the additional keyword arguments and methods that don’t care can be written as normal and do not need to change.

Work with the cross site request forgery framework

Django has added a new module to protect against cross site request forgery (CSRF). Unfortunately, if a user adds the django.middleware.csrf.CsrfViewMiddleware to their project, it will break RPC4Django. CSRF protection works by ensuring that all GET requests are side-effect free and then adding a little bit of random data (the CSRF token) to every form that submits via POST. The server can then verify that the correct random data was POSTed and this ensures that the form was submitted from your site and not some remote site.

Unfortunately, RPC is usually intended to be used in a cross site fashion. The fix is relatively painless, but requires some adversarial testing to make it work under Django 1.0, Django 1.1 and Django 1.2. The code (views.py) will look something like this:

try:
    # Django 1.2
    from django.views.decorators.csrf import csrf_exempt
except ImportError:
    try:
        # Django 1.1
        from django.contrib.csrf.middleware import csrf_exempt
    except ImportError:
        # Django 1.0
        csrf_exempt = None

if csrf_exempt is not None:
    csrf_exempt(serve_rpc_request)

I need to test it out very thoroughly and on a number of setups, but I think this code should do it.

HTTP access control

Usually the Javascript XmlHttpRequest object is subject to the same origin policy. This is a security measure that ensures that Javascript will only access data from the same domain, protocol and port as the initial request. There have always been hacks to get around this and the browser vendors are finally providing a uniform, secure way around.

Basically, RPC4Django will need to respond to an HTTP OPTIONS request with the header Access-Control-Allow-Origin specifying what domains are allowed to send requests. Both allowing HTTP access control and which domains are allowed will be options in settings.py.

Patches and feature requests

As always, I am happy to accept patches, but this is what I’ll be working on next week. Please let me know if there are any other important features that you would like to see in RPC4Django.