chapeau/kepi/tophat_ui/parse_accept.py

80 wiersze
2.8 KiB
Python

# based on:
# https://gist.github.com/samuraisam/2714195
#
#####
# The author disclaims copyright to this source code. In place of a legal
# notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
# It is based on a snipped found in this project:
# https://github.com/martinblech/mimerender
import functools
def parse_accept_header(accept):
"""
Parse the Accept header *accept*, returning a list with 3-tuples of
[(str(media_type), dict(params), float(q_value)),] ordered by q values.
If the accept header includes vendor-specific types like::
application/vnd.yourcompany.yourproduct-v1.1+json
It will actually convert the vendor and version into parameters and
convert the content type into `application/json` so appropriate content
negotiation decisions can be made.
Default `q` for values that are not specified is 1.0
"""
result = []
for media_range in accept.split(","):
parts = media_range.split(";")
media_type = parts.pop(0).strip()
media_params = []
# convert vendor-specific content types into something useful (see
# docstring)
try:
typ, subtyp = media_type.split('/')
except ValueError:
typ = ''
subtyp = ''
# check for a + in the sub-type
if '+' in subtyp:
# if it exists, determine if the subtype is a vendor-specific type
vnd, sep, extra = subtyp.partition('+')
if vnd.startswith('vnd'):
# and then... if it ends in something like "-v1.1" parse the
# version out
if '-v' in vnd:
vnd, sep, rest = vnd.rpartition('-v')
if len(rest):
# add the version as a media param
try:
version = media_params.append(('version',
float(rest)))
except ValueError:
version = 1.0 # could not be parsed
# add the vendor code as a media param
media_params.append(('vendor', vnd))
# and re-write media_type to something like application/json so
# it can be used usefully when looking up emitters
subtyp = extra
q = 1.0
for part in parts:
(key, value) = part.lstrip().split("=", 1)
key = key.strip()
value = value.strip()
if key == "q":
q = float(value)
else:
media_params.append((key, value))
result.append((typ, subtyp, dict(media_params), q))
result.sort(key=lambda n: -n[3])
return result