196 |
195 |
197 class httpconnection(keepalive.HTTPConnection): |
196 class httpconnection(keepalive.HTTPConnection): |
198 # must be able to send big bundle as stream. |
197 # must be able to send big bundle as stream. |
199 send = _gen_sendfile(keepalive.HTTPConnection.send) |
198 send = _gen_sendfile(keepalive.HTTPConnection.send) |
200 |
199 |
201 def getresponse(self): |
|
202 proxyres = getattr(self, 'proxyres', None) |
|
203 if proxyres: |
|
204 if proxyres.will_close: |
|
205 self.close() |
|
206 self.proxyres = None |
|
207 return proxyres |
|
208 return keepalive.HTTPConnection.getresponse(self) |
|
209 |
|
210 |
200 |
211 # Large parts of this function have their origin from before Python 2.6 |
201 # Large parts of this function have their origin from before Python 2.6 |
212 # and could potentially be removed. |
202 # and could potentially be removed. |
213 def _generic_start_transaction(handler, h, req): |
203 def _generic_start_transaction(handler, h, req): |
214 tunnel_host = req._tunnel_host |
204 tunnel_host = req._tunnel_host |
253 version, status, reason = res._read_status() |
243 version, status, reason = res._read_status() |
254 if status != httplib.CONTINUE: |
244 if status != httplib.CONTINUE: |
255 break |
245 break |
256 # skip lines that are all whitespace |
246 # skip lines that are all whitespace |
257 list(iter(lambda: res.fp.readline().strip(), b'')) |
247 list(iter(lambda: res.fp.readline().strip(), b'')) |
258 res.status = status |
248 |
259 res.reason = reason.strip() |
249 if status == 200: |
260 |
|
261 if res.status == 200: |
|
262 # skip lines until we find a blank line |
250 # skip lines until we find a blank line |
263 list(iter(res.fp.readline, b'\r\n')) |
251 list(iter(res.fp.readline, b'\r\n')) |
264 return True |
|
265 |
|
266 if version == b'HTTP/1.0': |
|
267 res.version = 10 |
|
268 elif version.startswith(b'HTTP/1.'): |
|
269 res.version = 11 |
|
270 elif version == b'HTTP/0.9': |
|
271 res.version = 9 |
|
272 else: |
252 else: |
273 raise httplib.UnknownProtocol(version) |
253 self.close() |
274 |
254 raise socket.error( |
275 if res.version == 9: |
255 "Tunnel connection failed: %d %s" % (status, reason.strip()) |
276 res.length = None |
256 ) |
277 res.chunked = 0 |
|
278 res.will_close = 1 |
|
279 res.msg = httplib.HTTPMessage(stringio()) |
|
280 return False |
|
281 |
|
282 res.msg = httplib.HTTPMessage(res.fp) |
|
283 res.msg.fp = None |
|
284 |
|
285 # are we using the chunked-style of transfer encoding? |
|
286 trenc = res.msg.getheader(b'transfer-encoding') |
|
287 if trenc and trenc.lower() == b"chunked": |
|
288 res.chunked = 1 |
|
289 res.chunk_left = None |
|
290 else: |
|
291 res.chunked = 0 |
|
292 |
|
293 # will the connection close at the end of the response? |
|
294 res.will_close = res._check_close() |
|
295 |
|
296 # do we have a Content-Length? |
|
297 # NOTE: RFC 2616, section 4.4, #3 says we ignore this if |
|
298 # transfer-encoding is "chunked" |
|
299 length = res.msg.getheader(b'content-length') |
|
300 if length and not res.chunked: |
|
301 try: |
|
302 res.length = int(length) |
|
303 except ValueError: |
|
304 res.length = None |
|
305 else: |
|
306 if res.length < 0: # ignore nonsensical negative lengths |
|
307 res.length = None |
|
308 else: |
|
309 res.length = None |
|
310 |
|
311 # does the body have a fixed length? (of zero) |
|
312 if ( |
|
313 status == httplib.NO_CONTENT |
|
314 or status == httplib.NOT_MODIFIED |
|
315 or 100 <= status < 200 |
|
316 or res._method == b'HEAD' # 1xx codes |
|
317 ): |
|
318 res.length = 0 |
|
319 |
|
320 # if the connection remains open, and we aren't using chunked, and |
|
321 # a content-length was not provided, then assume that the connection |
|
322 # WILL close. |
|
323 if not res.will_close and not res.chunked and res.length is None: |
|
324 res.will_close = 1 |
|
325 |
|
326 self.proxyres = res |
|
327 |
|
328 return False |
|
329 |
257 |
330 |
258 |
331 class httphandler(keepalive.HTTPHandler): |
259 class httphandler(keepalive.HTTPHandler): |
332 def http_open(self, req): |
260 def http_open(self, req): |
333 return self.do_open(httpconnection, req) |
261 return self.do_open(httpconnection, req) |