Tuesday, October 23rd, 2012

Good use for the Http-Accept header?

While working on a project which needs to use JSON for AJAX functions, I thought about using the Http-Accept header to return content depending on what the client asks. Most web browsers send this header, and it is usually on the lines of, I accept anything in the XML mimetypes, including HTML. Since headers can be set from jQuery and various client software, I thought... Why not take advantage of this Http-Accept header and build a Django middleware to return the content which is accepted by the client. So far, it only detects and returns JSON, and there is no caching enabled. Keep in mind that this is my very first version of this middleware, which I did test and works as expected.

from django.utils import simplejson
from django.http import HttpResponse
from django.db.models.query import QuerySet
from django.core import serializers

JSONMime = 'application/json' 

class HttpAcceptMiddleware(object):
    """
    The idea came to me when I thought deeply about the HTTP protocol.
    This middleware uses mime-type to determine what to send back to the client.
    Only works in Django 1.3+ due to new TemplateResponse
    """
    context_data = {}
    can_process = False
    def _serialize(self):
        for e in self.context_data:
            if isinstance(self.context_data[e], QuerySet):
                self.context_data[e] = serializers.serialize("json", self.context_data[e])
        return simplejson.dumps(self.context_data)
    def process_template_response(self, request, response):
        if request.META['HTTP_ACCEPT'] == JSONMime:
            self.context_data.update(response.context_data)
            self.can_process = True
        return response
    def process_response(self, request, response):
        if request.META['HTTP_ACCEPT'] == JSONMime:
            return HttpResponse(self._serialize(), mimetype=JSONMime)
        return response

This middleware will only work on Django 1.3 and above, since it relies on the TemplateResponse to provide the context data. It's very simple and straightforward, but can obviously cause some unwanted security flaws if not properly secured. Additional checks need to be put in place to prevent unwanted data from being leaked, since it does serialize an entire model. I will update this code once I can figure out the best way to secure the serializer, while keeping it simple and easy to use. If you use custom views, and not generic class-based views, it may do the trick without any additional hardening. It is the class-based views which put the entire model into the context.

About Me

My Photo
Names Kevin, hugely into UNIX technologies, not just Linux. I've dabbled with the demons, played with the Sun, and now with the Penguins.




Kevin Veroneau Consulting Services
Do you require the services of a Django contractor? Do you need both a website and hosting services? Perhaps I can help.

This Month

If you like what you read, please consider donating to help with hosting costs, and to fund future books to review.

Python Powered | © 2012-2013 Kevin Veroneau