Statistics
| Branch: | Tag: | Revision:

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