1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 '''
32 This module implements a series of hacks to the HTTPResponse class to enable
33 extra functionaliy (and practical in some cases) for the HttxLib
34
35 Rather than creating a new class and given that HTTPResponse is already well
36 suited for usage in CookieJars (except for the missing info method), extending
37 the class seems suitable.
38
39 Subclassing is not possible, because the HTTPResponse is instantiated inside
40 httplib.
41
42 Creating a class and instantiating it out of the data stored in the HTTPResponse
43 would be possible but data would have to be copied for each response.
44
45 This alternative seems the better: patching the class definition at the start of
46 the program and therefore be able to use the instantiated HTTPResponse everywhere
47 '''
48
49 from cStringIO import StringIO
50 from httplib import HTTPResponse
51
52
53 -def httxinit(self, sock, debuglevel=0, strict=0, method=None):
54 '''
55 It replaces the HTTPResponse.__init__ to allow to add and initialize
56 a member variable at object instantiation
57
58 Sock is the opaque type (actually a Python sock object) used in HttxLib
59 to index connecting objects with pending network activity
60 '''
61 self._httxinit(sock, debuglevel=debuglevel, strict=strict, method=method)
62 self.sock = None
63
64 HTTPResponse._httxinit = HTTPResponse.__init__
65 HTTPResponse.__init__ = httxinit
66
67
69 '''
70 Utility function to check if a response is underdoing a redirection
71 or authentication and network activity is pending redirection or a
72 CONNECT tunnel has been initiated
73
74 @return: if the response is underdoing a redirection or authentication
75 and network activity is pending
76 @rtype: bool
77 '''
78 return self.redirecting() or self.authenticating() or hasattr(self, 'tunnelreq')
79
81 '''
82 Utility function to check if a response is requesting redirection
83
84 @return: if the response is a request to redirect
85 @rtype: bool
86 '''
87 return self.status in (301, 302, 303, 307)
88
90 '''
91 Utility function to check if the redir codes are good for a GET request
92
93 @return: if the redir codes are good for a GET request
94 @rtype: bool
95 '''
96 return self.status in (301, 302, 303, 307)
97
99 '''
100 Utility function to check if the redir codes are good for a POST request
101
102 @return: if the redir codes are good for a POST request
103 @rtype: bool
104 '''
105 return self.status in (301, 302, 303)
106
108 '''
109 Utility function to check if the redir codes are good for a POST request
110 according to RFC 2616
111
112 @return: if the redir codes are good for a POST request
113 according to RFC 2616
114 @rtype: bool
115 '''
116 return self.status in (301, 302)
117
119 '''
120 Utility function to check if a response is requesting authentication
121
122 @return: if a response is requesting authentication
123 @rtype: bool
124 '''
125 return self.status in (401, 407)
126
128 '''
129 Utility function to check if a response indicates that pending network
130 activity exists, because a new request has been isssued following a
131 redirect request
132
133 @return: if a response is undergoing network activity because a
134 redirection request has been sent
135 @rtype: bool
136 '''
137 return self.sock and self.isredir()
138
140 '''
141 Utility function to check if a response indicates that pending network
142 activity exists, because a new request has been isssued following an
143 authentication request
144
145 @return: if a response is undergoing network activity because an
146 authentication request has been sent
147 @rtype: bool
148 '''
149 return self.sock and self.isauth()
150
152 '''
153 Utility function to check if the requested authentication is www-authenticate
154
155 @return: if the requested authentication is www-authenticate
156 @rtype: bool
157 '''
158 return self.status == 401
159
161 '''
162 Utility function to check if the requested authentication is proxy-authenticate
163
164 @return: if the requested authentication is proxy-authenticate
165 @rtype: bool
166 '''
167 return self.status == 407
168
169
170 HTTPResponse.redirecting = httxredirecting
171 HTTPResponse.authenticating = httxauthenticating
172 HTTPResponse.isauthuser = httxisauthuser
173 HTTPResponse.isauthproxy = httxisauthproxy
174 HTTPResponse.redirecting_or_authenticating = httxredirecting_or_authenticating
175 HTTPResponse.isactive = httxredirecting_or_authenticating
176 HTTPResponse.isauth = httxisauth
177 HTTPResponse.isredir = httxisredir
178 HTTPResponse.isredirget = httxisredirget
179 HTTPResponse.isredirpost = httxisredirpost
180 HTTPResponse.isredirpostrfc2616 = httxisredirpostrfc2616
181
183 '''
184 Utility function to make HTTPResponse fully compatible with CookieJar requirements
185
186 @return: the message object from HTTPResponse
187 @rtype: HTTPMessage
188 '''
189 return self.msg
190
191 HTTPResponse.info = httxinfo
192
193
195 '''
196 Wrapper for HTTPResponse.begin to allow for the body to be read and leave the
197 connection free for further re-use
198 '''
199
200
201
202
203 if self.msg is not None:
204 return
205
206
207 self._httxbegin()
208
209
210
211
212
213
214
215
216
217 self.will_close = self._check_close()
218
219
220
221
222 if not self.will_close and (self.chunked or self.length):
223 self.setbody(self._httxread())
224 else:
225
226 self.setbody('')
227
228
229 HTTPResponse._httxbegin = HTTPResponse.begin
230 HTTPResponse.begin = httxbegin
231
233 '''
234 Wrapper for HTTPResponse.read to read the body contents from the
235 StringIO object created during httxbegin
236 connection free for further re-use
237
238 @param amt: amount of bytes to be read
239 @type amt: int or None
240 @return: the read bytes
241 @rtype: str
242 '''
243
244
245
246 return self._httxbodyfile.read(amt)
247
248 HTTPResponse._httxread = HTTPResponse.read
249 HTTPResponse.read = httxread
250
251
252
253 -def httxgetbody(self):
254 '''
255 Utility function for a property get descriptor for body
256
257 @return: the body of the http response
258 @rtype: str
259 '''
260 return self._httxbody
261
262 -def httxsetbody(self, value):
263 '''
264 Utility function for a property set descriptor for body
265
266 @param value: the body of the http response to set
267 @type value: str
268 '''
269 self._httxbody = value
270 self._httxbodyfile = StringIO(self._httxbody)
271
272 HTTPResponse.getbody = httxgetbody
273 HTTPResponse.setbody = httxsetbody
274 HTTPResponse.body = property(HTTPResponse.getbody, HTTPResponse.setbody)
275
276
277
279 '''
280 Utility function for a property tet descriptor for bodyfile
281 '''
282 return self._httxbodyfile
283
284 HTTPResponse.getbodyfile = httxgetbodyfile
285 HTTPResponse.bodyfile = property(HTTPResponse.getbodyfile)
286
287
288 HTTPResponse.headers = property(HTTPResponse.getheaders)
289
291 '''
292 return a list of all header returned with the same name
293 (www-authenticate is an example)
294
295 @param name: name of the header
296 @type name: str
297
298 @return: a list of the values sent for the header
299 @rtype: list
300 '''
301 if self.msg is None:
302 raise ResponseNotReady()
303 return self.msg.getheaders(name)
304
305
306 HTTPResponse.getheaderlist = _httxgetheaderlist
307
308
309 HttxResponse = HTTPResponse
310