root / api / emitter.py @ 00b4f1be
History | View | Annotate | Download (1.8 kB)
1 |
# vim: ts=4 sts=4 et ai sw=4 fileencoding=utf-8
|
---|---|
2 |
#
|
3 |
# Copyright © 2010 Greek Research and Technology Network
|
4 |
#
|
5 |
|
6 |
from piston.resource import Resource as BaseResource |
7 |
import re |
8 |
|
9 |
_accept_re = re.compile(r'([^\s;,]+)(?:[^,]*?;\s*q=(\d*(?:\.\d+)?))?')
|
10 |
|
11 |
def parse_accept_header(value): |
12 |
"""Parse an HTTP Accept header
|
13 |
|
14 |
Returns an ordered by quality list of tuples (value, quality)
|
15 |
"""
|
16 |
if not value: |
17 |
return []
|
18 |
|
19 |
result = [] |
20 |
for match in _accept_re.finditer(value): |
21 |
quality = match.group(2)
|
22 |
if not quality: |
23 |
quality = 1
|
24 |
else:
|
25 |
quality = max(min(float(quality), 1), 0) |
26 |
result.append((match.group(1), quality))
|
27 |
|
28 |
# sort by quality
|
29 |
result.sort(key=lambda x: x[1]) |
30 |
|
31 |
return result
|
32 |
|
33 |
# XXX: works as intended but not used since piston's XMLEmitter doesn't output
|
34 |
# XML according to our spec :(
|
35 |
class Resource(BaseResource): |
36 |
def determine_emitter(self, request, *args, **kwargs): |
37 |
"""
|
38 |
Override default emitter policy to account for Accept header
|
39 |
|
40 |
emitter_format (.json or .xml suffix in URL) always takes precedence.
|
41 |
|
42 |
After that, the Accept header is checked; if both JSON and XML are
|
43 |
equally preferred, use JSON.
|
44 |
|
45 |
If none of the two were provided, then use JSON as per the
|
46 |
specification.
|
47 |
"""
|
48 |
|
49 |
em = request.GET.get('format', 'xml') |
50 |
if 'emitter_format' in kwargs: |
51 |
em = kwargs.pop('emitter_format')
|
52 |
elif 'HTTP_ACCEPT' in request.META: |
53 |
accepts = parse_accept_header(request.META['HTTP_ACCEPT'])
|
54 |
for content_type, quality in accepts: |
55 |
if content_type == 'application/json': |
56 |
break
|
57 |
elif content_type == 'application/xml': |
58 |
em = request.GET.get('format', 'xml') |
59 |
break
|
60 |
|
61 |
return em
|