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