1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 """Client classes used by REST Client."""
21
22 import urllib
23 import urllib2
24 import urlparse
25 import json
26
27
28
30 """Base client to provide common functionaility."""
31
33 """Ubuntu One RESTful Client."""
34 self.auth = auth
35 self.http_host = http_host
36
38 """Using the path, parameters and host, create a URL.
39
40 @param path: The url path
41 @param params: A dict of parameters to be used as a query string.
42 """
43 path = urllib.quote(path.encode('utf-8'), '~/[]()')
44 if params:
45 path = "%s?%s" % (path, urllib.urlencode(params))
46 return urlparse.urljoin(self.http_host, path)
47
50 """Helper to get a urllib2.Request object with the auth headers."""
51 headers = self.auth.get_auth_headers(url, params, method)
52 request = urllib2.Request(url, data, headers)
53 request.get_method = lambda: method
54 return request
55
57 """Helper to handle urllib2.Resquest object."""
58 opener = urllib2.build_opener(urllib2.BaseHandler)
59 try:
60 return opener.open(request, timeout=30)
61 except urllib2.URLError, ex:
62 raise Exception(
63 "Error opening %s\n%s" % (request.get_full_url(), ex.message))
64
65
67 """A client used to handle authenticated REST Requests."""
68
69 - def __init__(self, http_host, auth, base_api_path):
72
74 """Process a REST request.
75
76 This is specifically for JSON request/responses. The data, for PUT must
77 be serializable by JSON. The http responses must be JSON serializable as
78 well.
79 """
80 url = self.get_url_from_path(path, params)
81 if method == 'PUT' and data:
82 data = json.dumps(data)
83 else:
84 data = None
85 request = self._get_authenticated_request(url, params, method, data)
86 request.add_header('Content-Type', 'application/json')
87 response = self._handle_request(request)
88 content = response.read()
89 try:
90 return json.loads(content)
91 except ValueError:
92 raise Exception("JSON could not be decoded.\n%s\n%s" % (url,
93 content))
94
96 """Join the path with the API base path.
97
98 This also removes trailing slashes wish are not part of the resource.
99 """
100 if path:
101 return self.base_path + '/' + path.lstrip("/")
102 return self.base_path
103
108
113
118