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