Revision 5c812d1b api/emitter.py
b/api/emitter.py | ||
---|---|---|
3 | 3 |
# Copyright © 2010 Greek Research and Technology Network |
4 | 4 |
# |
5 | 5 |
|
6 |
import re |
|
7 | 6 |
from xml.dom import minidom |
8 |
from django.conf.urls.defaults import url |
|
9 | 7 |
from piston.emitters import Emitter, Mimer |
10 |
from piston.resource import Resource as BaseResource |
|
11 |
|
|
12 |
_accept_re = re.compile(r'([^\s;,]+)(?:[^,]*?;\s*q=(\d*(?:\.\d+)?))?') |
|
13 |
|
|
14 |
def parse_accept_header(value): |
|
15 |
"""Parse an HTTP Accept header |
|
16 |
|
|
17 |
Returns an ordered by quality list of tuples (value, quality) |
|
18 |
""" |
|
19 |
if not value: |
|
20 |
return [] |
|
21 |
|
|
22 |
result = [] |
|
23 |
for match in _accept_re.finditer(value): |
|
24 |
quality = match.group(2) |
|
25 |
if not quality: |
|
26 |
quality = 1 |
|
27 |
else: |
|
28 |
quality = max(min(float(quality), 1), 0) |
|
29 |
result.append((match.group(1), quality)) |
|
30 |
|
|
31 |
# sort by quality |
|
32 |
result.sort(key=lambda x: x[1]) |
|
33 |
|
|
34 |
return result |
|
35 |
|
|
36 |
class Resource(BaseResource): |
|
37 |
def determine_emitter(self, request, *args, **kwargs): |
|
38 |
""" |
|
39 |
Override default emitter policy to account for Accept header |
|
40 |
|
|
41 |
emitter_format (.json or .xml suffix in URL) always takes precedence. |
|
42 |
|
|
43 |
After that, the Accept header is checked; if both JSON and XML are |
|
44 |
equally preferred, use JSON. |
|
45 |
|
|
46 |
If none of the two were provided, then use JSON as per the |
|
47 |
specification. |
|
48 |
""" |
|
49 |
|
|
50 |
em = request.GET.get('format', 'json') |
|
51 |
if 'emitter_format' in kwargs and \ |
|
52 |
kwargs["emitter_format"] is not None: |
|
53 |
em = kwargs.pop('emitter_format') |
|
54 |
elif 'HTTP_ACCEPT' in request.META: |
|
55 |
accepts = parse_accept_header(request.META['HTTP_ACCEPT']) |
|
56 |
for content_type, quality in accepts: |
|
57 |
if content_type == 'application/json': |
|
58 |
break |
|
59 |
elif content_type == 'application/xml': |
|
60 |
em = request.GET.get('format', 'xml') |
|
61 |
break |
|
62 |
|
|
63 |
return em |
|
64 | 8 |
|
65 | 9 |
class OSXMLEmitter(Emitter): |
66 | 10 |
""" |
... | ... | |
118 | 62 |
|
119 | 63 |
Emitter.register('xml', OSXMLEmitter, 'application/xml') |
120 | 64 |
Mimer.register(lambda *a: None, ('application/xml',)) |
121 |
|
|
122 |
def url_with_format(regex, *args, **kwargs): |
|
123 |
""" |
|
124 |
An extended url() that adds an .json/.xml suffix to the end to avoid DRY |
|
125 |
""" |
|
126 |
if regex[-1] == '$' and regex[-2] != '\\': |
|
127 |
regex = regex[:-1] |
|
128 |
regex = regex + r'(\.(?P<emitter_format>json|xml))?$' |
|
129 |
return url(regex, *args, **kwargs) |
Also available in: Unified diff