Add new utility functions for HTTP Accept-based content negotiation.

Review Request #1643 — Created June 7, 2010 and submitted

djblets, reviewboard
Add new utility functions for HTTP Accept-based content negotiation.

This adds new get_http_requested_mimetype and get_http_accept_lists functions
for doing content negotiation using the HTTP Accept request header. This
header allows clients to tell the server which mimetypes it accepts or
explicitly forbids, based on priorities, so that the server can send the
right data. This can allow a single URL to return various forms of data
based on the client (HTML, PDF, JSON, etc.).

The get_http_accept_lists() function parses the HTTP Accept request header
and returns sorted lists of acceptable mimetypes and unacceptable mimetypes.
These are sorted based on the priorities in the header.

The get_http_requested_mimetype() function takes a HttpRequest and a list
of supported mimetypes for that URL and then, based on the results of
get_http_accept_lists() and the supported mimetypes, determines what mimetype
the server should be using. If nothing is supported, it will return None,
and the server is expected to return a HttpResponseNotAcceptable.
Unit tests pass.

Tested this with my upcoming WebAPIResource content negotiation patch and my Review Board diff resource content negotiation patch.
  1. Minor style issue.  Other than that, looks pretty good to me.  Tests pass.
  2. djblets/util/ (Diff revision 1)
    Too many blank lines here, I think.
  2. djblets/util/ (Diff revision 1)
    This can be a lot simpler:
    mimes = acceptable_mimetypes.intersection(supported_mimetypes)
    if mimes:
        return mimes.pop()
    Same below.
    1. This must be in a specific order. set() doesn't guarantee the same order, and actually will modify it in our case.
      For example:
      >>> set(['z', 'a'])
      set(['a', 'z'])
      No good.
    2. Okay. Ship it.