Changeset 391 for python/trunk/Lib/httplib.py
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Lib/httplib.py
r2 r391 1 """HTTP/1.1 client library1 r"""HTTP/1.1 client library 2 2 3 3 <intro stuff goes here> … … 68 68 69 69 from array import array 70 import os 70 71 import socket 71 72 from sys import py3kwarning … … 212 213 MAXAMOUNT = 1048576 213 214 215 # maximal line length when calling readline(). 216 _MAXLINE = 65536 217 214 218 class HTTPMessage(mimetools.Message): 215 219 … … 274 278 startofline = tell = None 275 279 self.seekable = 0 276 line = self.fp.readline() 280 line = self.fp.readline(_MAXLINE + 1) 281 if len(line) > _MAXLINE: 282 raise LineTooLong("header line") 277 283 if not line: 278 284 self.status = 'EOF in headers' … … 327 333 # See RFC 2616 sec 19.6 and RFC 1945 sec 6 for details. 328 334 329 def __init__(self, sock, debuglevel=0, strict=0, method=None): 330 self.fp = sock.makefile('rb', 0) 335 def __init__(self, sock, debuglevel=0, strict=0, method=None, buffering=False): 336 if buffering: 337 # The caller won't be using any sock.recv() calls, so buffering 338 # is fine and recommended for performance. 339 self.fp = sock.makefile('rb') 340 else: 341 # The buffer size is specified as zero, because the headers of 342 # the response are read with readline(). If the reads were 343 # buffered the readline() calls could consume some of the 344 # response, which make be read via a recv() on the underlying 345 # socket. 346 self.fp = sock.makefile('rb', 0) 331 347 self.debuglevel = debuglevel 332 348 self.strict = strict … … 347 363 def _read_status(self): 348 364 # Initialize with Simple-Response defaults 349 line = self.fp.readline() 365 line = self.fp.readline(_MAXLINE + 1) 366 if len(line) > _MAXLINE: 367 raise LineTooLong("header line") 350 368 if self.debuglevel > 0: 351 369 print "reply:", repr(line) … … 394 412 # skip the header from the 100 response 395 413 while True: 396 skip = self.fp.readline().strip() 414 skip = self.fp.readline(_MAXLINE + 1) 415 if len(skip) > _MAXLINE: 416 raise LineTooLong("header line") 417 skip = skip.strip() 397 418 if not skip: 398 419 break … … 515 536 return '' 516 537 538 if self._method == 'HEAD': 539 self.close() 540 return '' 541 517 542 if self.chunked: 518 543 return self._read_chunked(amt) … … 523 548 s = self.fp.read() 524 549 else: 525 s = self._safe_read(self.length) 550 try: 551 s = self._safe_read(self.length) 552 except IncompleteRead: 553 self.close() 554 raise 526 555 self.length = 0 527 556 self.close() # we read everything … … 537 566 # (for example, reading in 1k chunks) 538 567 s = self.fp.read(amt) 568 if not s: 569 # Ideally, we would raise IncompleteRead if the content-length 570 # wasn't satisfied, but it might break compatibility. 571 self.close() 539 572 if self.length is not None: 540 573 self.length -= len(s) 541 574 if not self.length: 542 575 self.close() 576 543 577 return s 544 578 … … 549 583 while True: 550 584 if chunk_left is None: 551 line = self.fp.readline() 585 line = self.fp.readline(_MAXLINE + 1) 586 if len(line) > _MAXLINE: 587 raise LineTooLong("chunk size") 552 588 i = line.find(';') 553 589 if i >= 0: … … 584 620 ### note: we shouldn't have any trailers! 585 621 while True: 586 line = self.fp.readline() 622 line = self.fp.readline(_MAXLINE + 1) 623 if len(line) > _MAXLINE: 624 raise LineTooLong("trailer line") 587 625 if not line: 588 626 # a vanishingly small number of sites EOF without … … 611 649 IncompleteRead exception can be used to detect the problem. 612 650 """ 651 # NOTE(gps): As of svn r74426 socket._fileobject.read(x) will never 652 # return less than x bytes unless EOF is encountered. It now handles 653 # signal interruptions (socket.error EINTR) internally. This code 654 # never caught that exception anyways. It seems largely pointless. 655 # self.fp.read(amt) will work fine. 613 656 s = [] 614 657 while amt > 0: … … 620 663 return ''.join(s) 621 664 665 def fileno(self): 666 return self.fp.fileno() 667 622 668 def getheader(self, name, default=None): 623 669 if self.msg is None: … … 644 690 645 691 def __init__(self, host, port=None, strict=None, 646 timeout=socket._GLOBAL_DEFAULT_TIMEOUT ):692 timeout=socket._GLOBAL_DEFAULT_TIMEOUT, source_address=None): 647 693 self.timeout = timeout 694 self.source_address = source_address 648 695 self.sock = None 649 696 self._buffer = [] … … 659 706 self.strict = strict 660 707 661 def _set_tunnel(self, host, port=None, headers=None):708 def set_tunnel(self, host, port=None, headers=None): 662 709 """ Sets up the host and the port for the HTTP CONNECT Tunnelling. 663 710 … … 680 727 port = int(host[i+1:]) 681 728 except ValueError: 682 raise InvalidURL("nonnumeric port: '%s'" % host[i+1:]) 729 if host[i+1:] == "": # http://foo.com:/ == http://foo.com/ 730 port = self.default_port 731 else: 732 raise InvalidURL("nonnumeric port: '%s'" % host[i+1:]) 683 733 host = host[:i] 684 734 else: … … 704 754 if code != 200: 705 755 self.close() 706 raise socket.error ,"Tunnel connection failed: %d %s" % (code,707 message.strip())756 raise socket.error("Tunnel connection failed: %d %s" % (code, 757 message.strip())) 708 758 while True: 709 line = response.fp.readline() 710 if line == '\r\n': break 759 line = response.fp.readline(_MAXLINE + 1) 760 if len(line) > _MAXLINE: 761 raise LineTooLong("header line") 762 if not line: 763 # for sites which EOF without sending trailer 764 break 765 if line == '\r\n': 766 break 711 767 712 768 … … 714 770 """Connect to the host and port specified in __init__.""" 715 771 self.sock = socket.create_connection((self.host,self.port), 716 self.timeout )772 self.timeout, self.source_address) 717 773 718 774 if self._tunnel_host: … … 729 785 self.__state = _CS_IDLE 730 786 731 def send(self, str):732 """Send ` str' to the server."""787 def send(self, data): 788 """Send `data' to the server.""" 733 789 if self.sock is None: 734 790 if self.auto_open: … … 737 793 raise NotConnected() 738 794 739 # send the data to the server. if we get a broken pipe, then close740 # the socket. we want to reconnect when somebody tries to send again.741 #742 # NOTE: we DO propagate the error, though, because we cannot simply743 # ignore the error... the caller will know if they can retry.744 795 if self.debuglevel > 0: 745 print "send:", repr(str) 746 try: 747 blocksize=8192 748 if hasattr(str,'read') and not isinstance(str, array): 749 if self.debuglevel > 0: print "sendIng a read()able" 750 data=str.read(blocksize) 751 while data: 752 self.sock.sendall(data) 753 data=str.read(blocksize) 754 else: 755 self.sock.sendall(str) 756 except socket.error, v: 757 if v[0] == 32: # Broken pipe 758 self.close() 759 raise 796 print "send:", repr(data) 797 blocksize = 8192 798 if hasattr(data,'read') and not isinstance(data, array): 799 if self.debuglevel > 0: print "sendIng a read()able" 800 datablock = data.read(blocksize) 801 while datablock: 802 self.sock.sendall(datablock) 803 datablock = data.read(blocksize) 804 else: 805 self.sock.sendall(data) 760 806 761 807 def _output(self, s): … … 766 812 self._buffer.append(s) 767 813 768 def _send_output(self ):814 def _send_output(self, message_body=None): 769 815 """Send the currently buffered request and clear the buffer. 770 816 771 817 Appends an extra \\r\\n to the buffer. 818 A message_body may be specified, to be appended to the request. 772 819 """ 773 820 self._buffer.extend(("", "")) 774 821 msg = "\r\n".join(self._buffer) 775 822 del self._buffer[:] 823 # If msg and message_body are sent in a single send() call, 824 # it will avoid performance problems caused by the interaction 825 # between delayed ack and the Nagle algorithm. 826 if isinstance(message_body, str): 827 msg += message_body 828 message_body = None 776 829 self.send(msg) 830 if message_body is not None: 831 #message_body was not a string (i.e. it is a file) and 832 #we must run the risk of Nagle 833 self.send(message_body) 777 834 778 835 def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0): … … 818 875 if not url: 819 876 url = '/' 820 str = '%s %s %s' % (method, url, self._http_vsn_str)821 822 self._output( str)877 hdr = '%s %s %s' % (method, url, self._http_vsn_str) 878 879 self._output(hdr) 823 880 824 881 if self._http_vsn == 11: … … 855 912 except UnicodeEncodeError: 856 913 host_enc = self.host.encode("idna") 914 # Wrap the IPv6 Host Header with [] (RFC 2732) 915 if host_enc.find(':') >= 0: 916 host_enc = "[" + host_enc + "]" 857 917 if self.port == self.default_port: 858 918 self.putheader('Host', host_enc) … … 883 943 pass 884 944 885 def putheader(self, header, value):945 def putheader(self, header, *values): 886 946 """Send a request header line to the server. 887 947 … … 891 951 raise CannotSendHeader() 892 952 893 str = '%s: %s' % (header, value) 894 self._output(str) 895 896 def endheaders(self): 897 """Indicate that the last header line has been sent to the server.""" 898 953 hdr = '%s: %s' % (header, '\r\n\t'.join([str(v) for v in values])) 954 self._output(hdr) 955 956 def endheaders(self, message_body=None): 957 """Indicate that the last header line has been sent to the server. 958 959 This method sends the request to the server. The optional 960 message_body argument can be used to pass a message body 961 associated with the request. The message body will be sent in 962 the same packet as the message headers if it is string, otherwise it is 963 sent as a separate packet. 964 """ 899 965 if self.__state == _CS_REQ_STARTED: 900 966 self.__state = _CS_REQ_SENT 901 967 else: 902 968 raise CannotSendHeader() 903 904 self._send_output() 969 self._send_output(message_body) 905 970 906 971 def request(self, method, url, body=None, headers={}): 907 972 """Send a complete request to the server.""" 908 973 self._send_request(method, url, body, headers) 974 975 def _set_content_length(self, body): 976 # Set the content-length based on the body. 977 thelen = None 909 978 try: 910 self._send_request(method, url, body, headers) 911 except socket.error, v: 912 # trap 'Broken pipe' if we're allowed to automatically reconnect 913 if v[0] != 32 or not self.auto_open: 914 raise 915 # try one more time 916 self._send_request(method, url, body, headers) 979 thelen = str(len(body)) 980 except TypeError, te: 981 # If this is a file-like object, try to 982 # fstat its file descriptor 983 try: 984 thelen = str(os.fstat(body.fileno()).st_size) 985 except (AttributeError, OSError): 986 # Don't send a length if this failed 987 if self.debuglevel > 0: print "Cannot stat!!" 988 989 if thelen is not None: 990 self.putheader('Content-Length', thelen) 917 991 918 992 def _send_request(self, method, url, body, headers): 919 # honour explicitly requested Host: and Accept-Encoding headers993 # Honor explicitly requested Host: and Accept-Encoding: headers. 920 994 header_names = dict.fromkeys([k.lower() for k in headers]) 921 995 skips = {} … … 927 1001 self.putrequest(method, url, **skips) 928 1002 929 if body and ('content-length' not in header_names): 930 thelen=None 931 try: 932 thelen=str(len(body)) 933 except TypeError, te: 934 # If this is a file-like object, try to 935 # fstat its file descriptor 936 import os 937 try: 938 thelen = str(os.fstat(body.fileno()).st_size) 939 except (AttributeError, OSError): 940 # Don't send a length if this failed 941 if self.debuglevel > 0: print "Cannot stat!!" 942 943 if thelen is not None: 944 self.putheader('Content-Length',thelen) 1003 if body is not None and 'content-length' not in header_names: 1004 self._set_content_length(body) 945 1005 for hdr, value in headers.iteritems(): 946 1006 self.putheader(hdr, value) 947 self.endheaders() 948 949 if body: 950 self.send(body) 951 952 def getresponse(self): 1007 self.endheaders(body) 1008 1009 def getresponse(self, buffering=False): 953 1010 "Get the response from the server." 954 1011 … … 976 1033 raise ResponseNotReady() 977 1034 1035 args = (self.sock,) 1036 kwds = {"strict":self.strict, "method":self._method} 978 1037 if self.debuglevel > 0: 979 response = self.response_class(self.sock, self.debuglevel,980 strict=self.strict,981 method=self._method)982 else:983 response = self.response_class(self.sock, strict=self.strict,984 method=self._method)1038 args += (self.debuglevel,) 1039 if buffering: 1040 #only add this keyword if non-default, for compatibility with 1041 #other response_classes. 1042 kwds["buffering"] = True; 1043 response = self.response_class(*args, **kwds) 985 1044 986 1045 response.begin() … … 1015 1074 port = None 1016 1075 1017 # Note that we may pass an empty string as the host; this will throw1076 # Note that we may pass an empty string as the host; this will raise 1018 1077 # an error when we attempt to connect. Presumably, the client code 1019 1078 # will call connect before then, with a proper host. … … 1026 1085 self.send = conn.send 1027 1086 self.putrequest = conn.putrequest 1087 self.putheader = conn.putheader 1028 1088 self.endheaders = conn.endheaders 1029 1089 self.set_debuglevel = conn.set_debuglevel … … 1045 1105 return self.file 1046 1106 1047 def putheader(self, header, *values): 1048 "The superclass allows only one value argument." 1049 self._conn.putheader(header, '\r\n\t'.join(values)) 1050 1051 def getreply(self): 1107 def getreply(self, buffering=False): 1052 1108 """Compat definition since superclass does not define it. 1053 1109 … … 1058 1114 """ 1059 1115 try: 1060 response = self._conn.getresponse() 1116 if not buffering: 1117 response = self._conn.getresponse() 1118 else: 1119 #only add this keyword if non-default for compatibility 1120 #with other connection classes 1121 response = self._conn.getresponse(buffering) 1061 1122 except BadStatusLine, e: 1062 1123 ### hmm. if getresponse() ever closes the socket on a bad request, … … 1098 1159 1099 1160 def __init__(self, host, port=None, key_file=None, cert_file=None, 1100 strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): 1101 HTTPConnection.__init__(self, host, port, strict, timeout) 1161 strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, 1162 source_address=None): 1163 HTTPConnection.__init__(self, host, port, strict, timeout, 1164 source_address) 1102 1165 self.key_file = key_file 1103 1166 self.cert_file = cert_file … … 1106 1169 "Connect to a host on a given (SSL) port." 1107 1170 1108 sock = socket.create_connection((self.host, self.port), self.timeout) 1171 sock = socket.create_connection((self.host, self.port), 1172 self.timeout, self.source_address) 1109 1173 if self._tunnel_host: 1110 1174 self.sock = sock … … 1197 1261 class BadStatusLine(HTTPException): 1198 1262 def __init__(self, line): 1263 if not line: 1264 line = repr(line) 1199 1265 self.args = line, 1200 1266 self.line = line 1267 1268 class LineTooLong(HTTPException): 1269 def __init__(self, line_type): 1270 HTTPException.__init__(self, "got more than %d bytes when reading %s" 1271 % (_MAXLINE, line_type)) 1201 1272 1202 1273 # for backwards compatibility … … 1270 1341 else: 1271 1342 return L + self._file.readlines(size) 1272 1273 def test():1274 """Test this module.1275 1276 A hodge podge of tests collected here, because they have too many1277 external dependencies for the regular test suite.1278 """1279 1280 import sys1281 import getopt1282 opts, args = getopt.getopt(sys.argv[1:], 'd')1283 dl = 01284 for o, a in opts:1285 if o == '-d': dl = dl + 11286 host = 'www.python.org'1287 selector = '/'1288 if args[0:]: host = args[0]1289 if args[1:]: selector = args[1]1290 h = HTTP()1291 h.set_debuglevel(dl)1292 h.connect(host)1293 h.putrequest('GET', selector)1294 h.endheaders()1295 status, reason, headers = h.getreply()1296 print 'status =', status1297 print 'reason =', reason1298 print "read", len(h.getfile().read())1299 print1300 if headers:1301 for header in headers.headers: print header.strip()1302 print1303 1304 # minimal test that code to extract host from url works1305 class HTTP11(HTTP):1306 _http_vsn = 111307 _http_vsn_str = 'HTTP/1.1'1308 1309 h = HTTP11('www.python.org')1310 h.putrequest('GET', 'http://www.python.org/~jeremy/')1311 h.endheaders()1312 h.getreply()1313 h.close()1314 1315 try:1316 import ssl1317 except ImportError:1318 pass1319 else:1320 1321 for host, selector in (('sourceforge.net', '/projects/python'),1322 ):1323 print "https://%s%s" % (host, selector)1324 hs = HTTPS()1325 hs.set_debuglevel(dl)1326 hs.connect(host)1327 hs.putrequest('GET', selector)1328 hs.endheaders()1329 status, reason, headers = hs.getreply()1330 print 'status =', status1331 print 'reason =', reason1332 print "read", len(hs.getfile().read())1333 print1334 if headers:1335 for header in headers.headers: print header.strip()1336 print1337 1338 if __name__ == '__main__':1339 test()
Note:
See TracChangeset
for help on using the changeset viewer.