URI dereferencing with Django / HTTP Content Negotiation

I've been building a Django app that essentially allows for the dereferencing of URIs that follow the USGIN Scheme. The engine also does some content-negotiation by reading HTTP GET accept-headers and responding with an appropriate file located somewhere on the internet. I had never even heard about content negotiation before embarking on this, and here are a few things that I learned:

 

  • I have content-negotiation working now. Client asks for a URI, specifies accept-header. Django listens, checks for the best matching available content-type. If there's a match, Django sends the client a 303 with the appropriate URL for the file to get. Then client sends a request for that file to the returned URL. If there's no acceptable content-type available, client gets a 406: not acceptable.
  • Clients do not seem to keep track of their accept-headers - at least Firefox isn't doing it. For example, if I use Poster to ask for http://granite/uri-gin/usgin/dataset/ and accept-header says nothing but: "text/html", Django server returns a 303 and a URL. Then Firefox makes a GET request to that URL using what appears to be its default accept-header: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8". That is, after a 303, the client "forgets" its original accept-header.
  • The 303 response does not say anything about what the content-type of the redirected URL should be. There's simply no place for it in the HTTP response. There's a content-type header, but that is the content-type of the 303 response: text/html.
  • I'll have to figure out some kind of input validation rule that does not allow you to put a URL into a media-type mapping that does not match the media type. For example I can set up a rule that matches http://granite/uri-gin/usgin/dataset/, and if the accept-header asks for "image/jpeg", it returns a 303 pointing you to http://www.google.com/. That is, the server responds to your request for a .jpg with a 303 pointing you at HTML. Who knows, maybe that's valid?
  • Here's a gem:

    In Firefox, if your html page has an IMG tag, lets say:
    <img src="http://resources.usgin.org/uri-gin/usgin/dataset/" />

    ... when you load the page Firefox makes the request with an accept-header that reads: "image/png,image/*;q=0.8,*/*;q=0.5". Since my URI is setup with an accept-mapping to match image/jpeg, the image comes through.

    Load the same page in Chrome or Internet Explorer and the accept-header reads: "*/*". No image loads, because the server tries to give it the text/html response.
  •  

     

    Also, here's a good read if you are wondering what the heck content-negotiation is: http://www.w3.org/QA/2006/02/content_negotiation.html