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