Statistics
| Branch: | Tag: | Revision:

root / api / util.py @ b016b476

History | View | Annotate | Download (3.1 kB)

1 7e2f9d4b Giorgos Verigakis
#
2 7e2f9d4b Giorgos Verigakis
# Copyright (c) 2010 Greek Research and Technology Network
3 7e2f9d4b Giorgos Verigakis
#
4 7e2f9d4b Giorgos Verigakis
5 7e2f9d4b Giorgos Verigakis
from synnefo.api.errors import *
6 7e2f9d4b Giorgos Verigakis
from synnefo.db.models import *
7 7e2f9d4b Giorgos Verigakis
8 7e2f9d4b Giorgos Verigakis
from django.http import HttpResponse
9 7e2f9d4b Giorgos Verigakis
from django.template.loader import render_to_string
10 7e2f9d4b Giorgos Verigakis
11 7e2f9d4b Giorgos Verigakis
from functools import wraps
12 7e2f9d4b Giorgos Verigakis
from logging import getLogger
13 7e2f9d4b Giorgos Verigakis
from random import choice
14 7e2f9d4b Giorgos Verigakis
from string import ascii_letters, digits
15 7e2f9d4b Giorgos Verigakis
from traceback import format_exc
16 7e2f9d4b Giorgos Verigakis
from xml.etree import ElementTree
17 7e2f9d4b Giorgos Verigakis
from xml.parsers.expat import ExpatError
18 7e2f9d4b Giorgos Verigakis
19 7e2f9d4b Giorgos Verigakis
import json
20 7e2f9d4b Giorgos Verigakis
21 7e2f9d4b Giorgos Verigakis
22 7e2f9d4b Giorgos Verigakis
log = getLogger('synnefo.api')
23 7e2f9d4b Giorgos Verigakis
24 7e2f9d4b Giorgos Verigakis
25 7e2f9d4b Giorgos Verigakis
def tag_name(e):
26 7e2f9d4b Giorgos Verigakis
    ns, sep, name = e.tag.partition('}')
27 7e2f9d4b Giorgos Verigakis
    return name if sep else e.tag
28 7e2f9d4b Giorgos Verigakis
29 7e2f9d4b Giorgos Verigakis
def xml_to_dict(s):
30 c36934a7 Giorgos Verigakis
    # XXX Quick and dirty
31 7e2f9d4b Giorgos Verigakis
    def _xml_to_dict(e):
32 7e2f9d4b Giorgos Verigakis
        root = {}
33 7e2f9d4b Giorgos Verigakis
        d = root[tag_name(e)] = dict(e.items())
34 7e2f9d4b Giorgos Verigakis
        for child in e.getchildren():
35 7e2f9d4b Giorgos Verigakis
            d.update(_xml_to_dict(child))
36 7e2f9d4b Giorgos Verigakis
        return root
37 7e2f9d4b Giorgos Verigakis
    return _xml_to_dict(ElementTree.fromstring(s.strip()))
38 7e2f9d4b Giorgos Verigakis
39 7e2f9d4b Giorgos Verigakis
def get_user():
40 7e2f9d4b Giorgos Verigakis
    # XXX Placeholder function, everything belongs to a single SynnefoUser for now
41 7e2f9d4b Giorgos Verigakis
    try:
42 7e2f9d4b Giorgos Verigakis
        return SynnefoUser.objects.all()[0]
43 7e2f9d4b Giorgos Verigakis
    except IndexError:
44 7e2f9d4b Giorgos Verigakis
        raise Unauthorized
45 7e2f9d4b Giorgos Verigakis
46 7e2f9d4b Giorgos Verigakis
def get_request_dict(request):
47 7e2f9d4b Giorgos Verigakis
    data = request.raw_post_data
48 7e2f9d4b Giorgos Verigakis
    if request.type == 'xml':
49 7e2f9d4b Giorgos Verigakis
        try:
50 7e2f9d4b Giorgos Verigakis
            return xml_to_dict(data)
51 7e2f9d4b Giorgos Verigakis
        except ExpatError:
52 7e2f9d4b Giorgos Verigakis
            raise BadRequest
53 7e2f9d4b Giorgos Verigakis
    else:
54 7e2f9d4b Giorgos Verigakis
        try:
55 7e2f9d4b Giorgos Verigakis
            return json.loads(data)
56 7e2f9d4b Giorgos Verigakis
        except ValueError:
57 7e2f9d4b Giorgos Verigakis
            raise BadRequest
58 7e2f9d4b Giorgos Verigakis
59 7e2f9d4b Giorgos Verigakis
def random_password(length=8):
60 7e2f9d4b Giorgos Verigakis
    pool = ascii_letters + digits
61 7e2f9d4b Giorgos Verigakis
    return ''.join(choice(pool) for i in range(length))
62 7e2f9d4b Giorgos Verigakis
63 7e2f9d4b Giorgos Verigakis
64 c36934a7 Giorgos Verigakis
def render_fault(request, fault):
65 7e2f9d4b Giorgos Verigakis
    if settings.DEBUG or request.META.get('SERVER_NAME', None) == 'testserver':
66 7e2f9d4b Giorgos Verigakis
        fault.details = format_exc(fault)
67 7e2f9d4b Giorgos Verigakis
    if request.type == 'xml':
68 7e2f9d4b Giorgos Verigakis
        mimetype = 'application/xml'
69 7e2f9d4b Giorgos Verigakis
        data = render_to_string('fault.xml', dict(fault=fault))
70 7e2f9d4b Giorgos Verigakis
    else:
71 7e2f9d4b Giorgos Verigakis
        mimetype = 'application/json'
72 7e2f9d4b Giorgos Verigakis
        d = {fault.name: {'code': fault.code, 'message': fault.message, 'details': fault.details}}
73 7e2f9d4b Giorgos Verigakis
        data = json.dumps(d)
74 7e2f9d4b Giorgos Verigakis
    return HttpResponse(data, mimetype=mimetype, status=fault.code)    
75 7e2f9d4b Giorgos Verigakis
76 c36934a7 Giorgos Verigakis
def api_method(http_method):
77 c36934a7 Giorgos Verigakis
    def decorator(func):
78 c36934a7 Giorgos Verigakis
        @wraps(func)
79 c36934a7 Giorgos Verigakis
        def wrapper(request, *args, **kwargs):
80 c36934a7 Giorgos Verigakis
            try:
81 c36934a7 Giorgos Verigakis
                if request.path.endswith('.json'):
82 c36934a7 Giorgos Verigakis
                    type = 'json'
83 c36934a7 Giorgos Verigakis
                elif request.path.endswith('.xml'):
84 c36934a7 Giorgos Verigakis
                    type = 'xml'
85 c36934a7 Giorgos Verigakis
                elif request.META.get('HTTP_ACCEPT', None) == 'application/xml':
86 c36934a7 Giorgos Verigakis
                    type = 'xml'
87 c36934a7 Giorgos Verigakis
                else:
88 c36934a7 Giorgos Verigakis
                    type = 'json'
89 c36934a7 Giorgos Verigakis
                request.type = type
90 c36934a7 Giorgos Verigakis
                
91 c36934a7 Giorgos Verigakis
                if request.method != http_method:
92 c36934a7 Giorgos Verigakis
                    raise BadRequest()
93 c36934a7 Giorgos Verigakis
                
94 c36934a7 Giorgos Verigakis
                resp = func(request, *args, **kwargs)
95 c36934a7 Giorgos Verigakis
                resp['Content-Type'] = 'application/xml' if type == 'xml' else 'application/json'
96 c36934a7 Giorgos Verigakis
                return resp
97 c36934a7 Giorgos Verigakis
            except Fault, fault:
98 c36934a7 Giorgos Verigakis
                return render_fault(request, fault)
99 c36934a7 Giorgos Verigakis
            except Exception, e:
100 c36934a7 Giorgos Verigakis
                log.exception('Unexpected error: %s' % e)
101 c36934a7 Giorgos Verigakis
                fault = ServiceUnavailable()
102 c36934a7 Giorgos Verigakis
                return render_fault(request, fault)
103 c36934a7 Giorgos Verigakis
        return wrapper
104 c36934a7 Giorgos Verigakis
    return decorator