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 from .client import Client
18 from .filters import BasicAuth
19 from . import util
20 from .wrappers import Response
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 = Response
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.Client` 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 self.client = Client(**self.client_opts)
72
74 return '<%s %s>' % (self.__class__.__name__, self.uri)
75
77 """if you want to add a path to resource uri, you can do:
78
79 .. code-block:: python
80
81 resr2 = res.clone()
82
83 """
84 obj = self.__class__(self.initial['uri'],
85 **self.initial['client_opts'])
86 return obj
87
89 """if you want to add a path to resource uri, you can do:
90
91 .. code-block:: python
92
93 Resource("/path").get()
94 """
95
96 uri = self.initial['uri']
97
98 new_uri = util.make_uri(uri, path, charset=self.charset,
99 safe=self.safe, encode_keys=self.encode_keys)
100
101 obj = type(self)(new_uri, **self.initial['client_opts'])
102 return obj
103
104 - def get(self, path=None, headers=None, params_dict=None, **params):
105 """ HTTP GET
106
107 :param path: string additionnal path to the uri
108 :param headers: dict, optionnal headers that will
109 be added to HTTP request.
110 :param params: Optionnal parameterss added to the request.
111 """
112 return self.request("GET", path=path, headers=headers,
113 params_dict=params_dict, **params)
114
115 - def head(self, path=None, headers=None, params_dict=None, **params):
116 """ HTTP HEAD
117
118 see GET for params description.
119 """
120 return self.request("HEAD", path=path, headers=headers,
121 params_dict=params_dict, **params)
122
123 - def delete(self, path=None, headers=None, params_dict=None, **params):
124 """ HTTP DELETE
125
126 see GET for params description.
127 """
128 return self.request("DELETE", path=path, headers=headers,
129 params_dict=params_dict, **params)
130
131 - def post(self, path=None, payload=None, headers=None,
132 params_dict=None, **params):
133 """ HTTP POST
134
135 :param payload: string passed to the body of the request
136 :param path: string additionnal path to the uri
137 :param headers: dict, optionnal headers that will
138 be added to HTTP request.
139 :param params: Optionnal parameterss added to the request
140 """
141
142 return self.request("POST", path=path, payload=payload,
143 headers=headers, params_dict=params_dict, **params)
144
145 - def put(self, path=None, payload=None, headers=None,
146 params_dict=None, **params):
147 """ HTTP PUT
148
149 see POST for params description.
150 """
151 return self.request("PUT", path=path, payload=payload,
152 headers=headers, params_dict=params_dict, **params)
153
156
159
162
163 - def request(self, method, path=None, payload=None, headers=None,
164 params_dict=None, **params):
165 """ HTTP request
166
167 This method may be the only one you want to override when
168 subclassing `restkit.rest.Resource`.
169
170 :param payload: string or File object passed to the body of the request
171 :param path: string additionnal path to the uri
172 :param headers: dict, optionnal headers that will
173 be added to HTTP request.
174 :params_dict: Options parameters added to the request as a dict
175 :param params: Optionnal parameterss added to the request
176 """
177
178 params = params or {}
179 params.update(params_dict or {})
180
181 while True:
182 uri = util.make_uri(self.uri, path, charset=self.charset,
183 safe=self.safe, encode_keys=self.encode_keys,
184 **self.make_params(params))
185
186
187
188 resp = self.client.request(uri, method=method, body=payload,
189 headers=self.make_headers(headers))
190
191 if resp is None:
192
193 raise ValueError("Unkown error: response object is None")
194
195 if resp.status_int >= 400:
196 if resp.status_int == 404:
197 raise ResourceNotFound(resp.body_string(),
198 response=resp)
199 elif resp.status_int in (401, 403):
200 if self.unauthorized(resp):
201 raise Unauthorized(resp.body_string(),
202 http_code=resp.status_int,
203 response=resp)
204 else:
205 raise RequestFailed(resp.body_string(),
206 http_code=resp.status_int,
207 response=resp)
208 else:
209 break
210
211 return resp
212
223