kopia lustrzana https://gitlab.com/marnanel/chapeau
80 wiersze
2.8 KiB
Python
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
|