- Author:
- raven_nevermore
- Posted:
- November 15, 2010
- Language:
- Python
- Version:
- 1.2
- Score:
- 0 (after 0 ratings)
An accept middleware, which is based on the code of http://djangosnippets.org/snippets/1042/ but adds a workaround for the buggy accept header, sent from webkit browsers such as safari and chrome.
The workaround affects any accept header, that has xml and (x)html in the best q, but also the xml mediatype at first place in the list.
If this is the case, the header is rearanged, by shifting the xml mediatype to become the last element of the best quality entries in the header.
If the workaround did manipulate the header, and there is a html entry in the list with lower quality as an xhtml entry that is also in the list (with best q), then the html entry is also raised in q to be one entry in front of xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | from string import lower
def webkit_workaround(bestq, result):
"""The next part is a workaround, to avoid the problem, webkit browsers
generate, by putting application/xml as the first item in theire
accept headers
The algorithm changes the order of the best quality fields, if xml appears
to be the first entry of best quality and eigther an xhtml or html emtry is,
found with also best quality, to xml beeing the last entry of best quality.
If only an xhtml entry is found in bestq, but the request contains an html
entry with lower rating, it rearranges the html entry to be directly
in front of xml.
"""
if result[0][0] == "application/xml":
bestresult = []
length = 0
hashtml = False
hasxhtml = False
idxhtml = None
i = 0
for mediatype in result:
if mediatype[2] == bestq:
bestresult.append(mediatype)
length = length + 1
if not hasxhtml and lower(mediatype[0]) == "application/xhtml+xml":
hasxhtml = True
if not hashtml and lower(mediatype[0]) == "text/html":
hashtml = True
if lower(mediatype[0]) == "text/html":
idxhtml = i
i = i+1
if (hashtml or hasxhtml) and length > 1:
newresult = []
newresult.extend(bestresult[1:])
if not hashtml and idxhtml:
htmltype = result.pop(idxhtml)
htmltype = (htmltype[0], htmltype[1], bestq)
newresult.append(htmltype)
newresult.append(bestresult[0])
newresult.extend(result[length:])
result = newresult
return result
def parse_accept_header(accept):
"""Parse the Accept header *accept*, returning a list with pairs of
(media_type, q_value), ordered by q values.
"""
bestq = 0.0
result = []
for media_range in accept.split(","):
parts = media_range.split(";")
media_type = parts.pop(0)
media_params = []
q = 1.0
for part in parts:
(key, value) = part.lstrip().split("=", 1)
if key == "q":
q = float(value)
else:
media_params.append((key, value))
if q > bestq:
bestq = q
result.append((media_type, tuple(media_params), q))
result.sort(lambda x, y: -cmp(x[2], y[2]))
result = webkit_workaround(bestq, result)
return result
class AcceptMiddleware(object):
def process_request(self, request):
accept = parse_accept_header(request.META.get("HTTP_ACCEPT", ""))
request.accept = accept
request.accepted_types = map(lambda (t, p, q): t, accept)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 8 months ago
Comments
Please login first before commenting.