1
2
3
4
5
6
7 """
8 restkit.resource
9 ~~~~~~~~~~~~~~~~
10
11 This module provide a common interface for all HTTP request.
12 """
13 from copy import copy
14 import urlparse
15
16 from restkit.errors import ResourceNotFound, Unauthorized, \
17 RequestFailed, ResourceGone
18 from restkit.client import Client
19 from restkit.filters import BasicAuth
20 from restkit import util
21 from restkit.wrappers import Response
22
24 """A class that can be instantiated for access to a RESTful resource,
25 including authentication.
26 """
27
28 charset = 'utf-8'
29 encode_keys = True
30 safe = "/:"
31 basic_auth_url = True
32 response_class = Response
33
35 """Constructor for a `Resource` object.
36
37 Resource represent an HTTP resource.
38
39 :param uri: str, full uri to the server.
40 :param client_opts: `restkit.client.Client` Options
41 """
42 client_opts = client_opts or {}
43
44 self.initial = dict(
45 uri = uri,
46 client_opts = client_opts.copy()
47 )
48
49
50 if self.response_class is not None and \
51 not 'response_class' in client_opts:
52 client_opts['response_class'] = self.response_class
53
54 self.filters = client_opts.get('filters') or []
55 self.uri = uri
56 if self.basic_auth_url:
57
58 u = urlparse.urlparse(uri)
59 if u.username:
60 password = u.password or ""
61
62
63 filters = copy(self.filters)
64 filters.append(BasicAuth(u.username, password))
65 client_opts['filters'] = filters
66
67
68 self.uri = urlparse.urlunparse((u.scheme, u.netloc.split("@")[-1],
69 u.path, u.params, u.query, u.fragment))
70
71 self.client_opts = client_opts
72 self.client = Client(**self.client_opts)
73
75 return '<%s %s>' % (self.__class__.__name__, self.uri)
76
78 """if you want to add a path to resource uri, you can do:
79
80 .. code-block:: python
81
82 resr2 = res.clone()
83
84 """
85 obj = self.__class__(self.initial['uri'],
86 **self.initial['client_opts'])
87 return obj
88
90 """if you want to add a path to resource uri, you can do:
91
92 .. code-block:: python
93
94 Resource("/path").get()
95 """
96
97 uri = self.initial['uri']
98
99 new_uri = util.make_uri(uri, path, charset=self.charset,
100 safe=self.safe, encode_keys=self.encode_keys)
101
102 obj = type(self)(new_uri, **self.initial['client_opts'])
103 return obj
104
105 - def get(self, path=None, headers=None, params_dict=None, **params):
106 """ HTTP GET
107
108 :param path: string additionnal path to the uri
109 :param headers: dict, optionnal headers that will
110 be added to HTTP request.
111 :param params: Optionnal parameterss added to the request.
112 """
113 return self.request("GET", path=path, headers=headers,
114 params_dict=params_dict, **params)
115
116 - def head(self, path=None, headers=None, params_dict=None, **params):
117 """ HTTP HEAD
118
119 see GET for params description.
120 """
121 return self.request("HEAD", path=path, headers=headers,
122 params_dict=params_dict, **params)
123
124 - def delete(self, path=None, headers=None, params_dict=None, **params):
125 """ HTTP DELETE
126
127 see GET for params description.
128 """
129 return self.request("DELETE", path=path, headers=headers,
130 params_dict=params_dict, **params)
131
132 - def post(self, path=None, payload=None, headers=None,
133 params_dict=None, **params):
134 """ HTTP POST
135
136 :param payload: string passed to the body of the request
137 :param path: string additionnal path to the uri
138 :param headers: dict, optionnal headers that will
139 be added to HTTP request.
140 :param params: Optionnal parameterss added to the request
141 """
142
143 return self.request("POST", path=path, payload=payload,
144 headers=headers, params_dict=params_dict, **params)
145
146 - def put(self, path=None, payload=None, headers=None,
147 params_dict=None, **params):
148 """ HTTP PUT
149
150 see POST for params description.
151 """
152 return self.request("PUT", path=path, payload=payload,
153 headers=headers, params_dict=params_dict, **params)
154
157
160
163
164 - def request(self, method, path=None, payload=None, headers=None,
165 params_dict=None, **params):
166 """ HTTP request
167
168 This method may be the only one you want to override when
169 subclassing `restkit.rest.Resource`.
170
171 :param payload: string or File object passed to the body of the request
172 :param path: string additionnal path to the uri
173 :param headers: dict, optionnal headers that will
174 be added to HTTP request.
175 :params_dict: Options parameters added to the request as a dict
176 :param params: Optionnal parameterss added to the request
177 """
178
179 params = params or {}
180 params.update(params_dict or {})
181
182 while True:
183 uri = util.make_uri(self.uri, path, charset=self.charset,
184 safe=self.safe, encode_keys=self.encode_keys,
185 **self.make_params(params))
186
187
188
189 resp = self.client.request(uri, method=method, body=payload,
190 headers=self.make_headers(headers))
191
192 if resp is None:
193
194 raise ValueError("Unkown error: response object is None")
195
196 if resp.status_int >= 400:
197 if resp.status_int == 404:
198 raise ResourceNotFound(resp.body_string(),
199 response=resp)
200 elif resp.status_int in (401, 403):
201 if self.unauthorized(resp):
202 raise Unauthorized(resp.body_string(),
203 http_code=resp.status_int,
204 response=resp)
205 elif resp.status_int == 410:
206 raise ResourceGone(resp.body_string(), response=resp)
207 else:
208 raise RequestFailed(resp.body_string(),
209 http_code=resp.status_int,
210 response=resp)
211 else:
212 break
213
214 return resp
215
226