1r"""HTTP/1.1 client library 2 3<intro stuff goes here> 4<other stuff, too> 5 6HTTPConnection goes through a number of "states", which define when a client 7may legally make another request or fetch the response for a particular 8request. This diagram details these state transitions: 9 10 (null) 11 | 12 | HTTPConnection() 13 v 14 Idle 15 | 16 | putrequest() 17 v 18 Request-started 19 | 20 | ( putheader() )* endheaders() 21 v 22 Request-sent 23 |\_____________________________ 24 | | getresponse() raises 25 | response = getresponse() | ConnectionError 26 v v 27 Unread-response Idle 28 [Response-headers-read] 29 |\____________________ 30 | | 31 | response.read() | putrequest() 32 v v 33 Idle Req-started-unread-response 34 ______/| 35 / | 36 response.read() | | ( putheader() )* endheaders() 37 v v 38 Request-started Req-sent-unread-response 39 | 40 | response.read() 41 v 42 Request-sent 43 44This diagram presents the following rules: 45 -- a second request may not be started until {response-headers-read} 46 -- a response [object] cannot be retrieved until {request-sent} 47 -- there is no differentiation between an unread response body and a 48 partially read response body 49 50Note: this enforcement is applied by the HTTPConnection class. The 51 HTTPResponse class does not enforce this state machine, which 52 implies sophisticated clients may accelerate the request/response 53 pipeline. Caution should be taken, though: accelerating the states 54 beyond the above pattern may imply knowledge of the server's 55 connection-close behavior for certain requests. For example, it 56 is impossible to tell whether the server will close the connection 57 UNTIL the response headers have been read; this means that further 58 requests cannot be placed into the pipeline until it is known that 59 the server will NOT be closing the connection. 60 61Logical State __state __response 62------------- ------- ---------- 63Idle _CS_IDLE None 64Request-started _CS_REQ_STARTED None 65Request-sent _CS_REQ_SENT None 66Unread-response _CS_IDLE <response_class> 67Req-started-unread-response _CS_REQ_STARTED <response_class> 68Req-sent-unread-response _CS_REQ_SENT <response_class> 69""" 70 71import email.parser 72import email.message 73import http 74import io 75import re 76import socket 77import collections.abc 78from urllib.parse import urlsplit 79 80# HTTPMessage, parse_headers(), and the HTTP status code constants are 81# intentionally omitted for simplicity 82__all__ = ["HTTPResponse", "HTTPConnection", 83 "HTTPException", "NotConnected", "UnknownProtocol", 84 "UnknownTransferEncoding", "UnimplementedFileMode", 85 "IncompleteRead", "InvalidURL", "ImproperConnectionState", 86 "CannotSendRequest", "CannotSendHeader", "ResponseNotReady", 87 "BadStatusLine", "LineTooLong", "RemoteDisconnected", "error", 88 "responses"] 89 90HTTP_PORT = 80 91HTTPS_PORT = 443 92 93_UNKNOWN = 'UNKNOWN' 94 95# connection states 96_CS_IDLE = 'Idle' 97_CS_REQ_STARTED = 'Request-started' 98_CS_REQ_SENT = 'Request-sent' 99 100 101# hack to maintain backwards compatibility 102globals().update(http.HTTPStatus.__members__) 103 104# another hack to maintain backwards compatibility 105# Mapping status codes to official W3C names 106responses = {v: v.phrase for v in http.HTTPStatus.__members__.values()} 107 108# maximal amount of data to read at one time in _safe_read 109MAXAMOUNT = 1048576 110 111# maximal line length when calling readline(). 112_MAXLINE = 65536 113_MAXHEADERS = 100 114 115# Header name/value ABNF (http://tools.ietf.org/html/rfc7230#section-3.2) 116# 117# VCHAR = %x21-7E 118# obs-text = %x80-FF 119# header-field = field-name ":" OWS field-value OWS 120# field-name = token 121# field-value = *( field-content / obs-fold ) 122# field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] 123# field-vchar = VCHAR / obs-text 124# 125# obs-fold = CRLF 1*( SP / HTAB ) 126# ; obsolete line folding 127# ; see Section 3.2.4 128 129# token = 1*tchar 130# 131# tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" 132# / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" 133# / DIGIT / ALPHA 134# ; any VCHAR, except delimiters 135# 136# VCHAR defined in http://tools.ietf.org/html/rfc5234#appendix-B.1 137 138# the patterns for both name and value are more lenient than RFC 139# definitions to allow for backwards compatibility 140_is_legal_header_name = re.compile(rb'[^:\s][^:\r\n]*').fullmatch 141_is_illegal_header_value = re.compile(rb'\n(?![ \t])|\r(?![ \t\n])').search 142 143# These characters are not allowed within HTTP URL paths. 144# See https://tools.ietf.org/html/rfc3986#section-3.3 and the 145# https://tools.ietf.org/html/rfc3986#appendix-A pchar definition. 146# Prevents CVE-2019-9740. Includes control characters such as \r\n. 147# We don't restrict chars above \x7f as putrequest() limits us to ASCII. 148_contains_disallowed_url_pchar_re = re.compile('[\x00-\x20\x7f]') 149# Arguably only these _should_ allowed: 150# _is_allowed_url_pchars_re = re.compile(r"^[/!$&'()*+,;=:@%a-zA-Z0-9._~-]+$") 151# We are more lenient for assumed real world compatibility purposes. 152 153# These characters are not allowed within HTTP method names 154# to prevent http header injection. 155_contains_disallowed_method_pchar_re = re.compile('[\x00-\x1f]') 156 157# We always set the Content-Length header for these methods because some 158# servers will otherwise respond with a 411 159_METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'} 160 161 162def _encode(data, name='data'): 163 """Call data.encode("latin-1") but show a better error message.""" 164 try: 165 return data.encode("latin-1") 166 except UnicodeEncodeError as err: 167 raise UnicodeEncodeError( 168 err.encoding, 169 err.object, 170 err.start, 171 err.end, 172 "%s (%.20r) is not valid Latin-1. Use %s.encode('utf-8') " 173 "if you want to send it encoded in UTF-8." % 174 (name.title(), data[err.start:err.end], name)) from None 175 176 177class HTTPMessage(email.message.Message): 178 # XXX The only usage of this method is in 179 # http.server.CGIHTTPRequestHandler. Maybe move the code there so 180 # that it doesn't need to be part of the public API. The API has 181 # never been defined so this could cause backwards compatibility 182 # issues. 183 184 def getallmatchingheaders(self, name): 185 """Find all header lines matching a given header name. 186 187 Look through the list of headers and find all lines matching a given 188 header name (and their continuation lines). A list of the lines is 189 returned, without interpretation. If the header does not occur, an 190 empty list is returned. If the header occurs multiple times, all 191 occurrences are returned. Case is not important in the header name. 192 193 """ 194 name = name.lower() + ':' 195 n = len(name) 196 lst = [] 197 hit = 0 198 for line in self.keys(): 199 if line[:n].lower() == name: 200 hit = 1 201 elif not line[:1].isspace(): 202 hit = 0 203 if hit: 204 lst.append(line) 205 return lst 206 207def _read_headers(fp): 208 """Reads potential header lines into a list from a file pointer. 209 210 Length of line is limited by _MAXLINE, and number of 211 headers is limited by _MAXHEADERS. 212 """ 213 headers = [] 214 while True: 215 line = fp.readline(_MAXLINE + 1) 216 if len(line) > _MAXLINE: 217 raise LineTooLong("header line") 218 headers.append(line) 219 if len(headers) > _MAXHEADERS: 220 raise HTTPException("got more than %d headers" % _MAXHEADERS) 221 if line in (b'\r\n', b'\n', b''): 222 break 223 return headers 224 225def parse_headers(fp, _class=HTTPMessage): 226 """Parses only RFC2822 headers from a file pointer. 227 228 email Parser wants to see strings rather than bytes. 229 But a TextIOWrapper around self.rfile would buffer too many bytes 230 from the stream, bytes which we later need to read as bytes. 231 So we read the correct bytes here, as bytes, for email Parser 232 to parse. 233 234 """ 235 headers = _read_headers(fp) 236 hstring = b''.join(headers).decode('iso-8859-1') 237 return email.parser.Parser(_class=_class).parsestr(hstring) 238 239 240class HTTPResponse(io.BufferedIOBase): 241 242 # See RFC 2616 sec 19.6 and RFC 1945 sec 6 for details. 243 244 # The bytes from the socket object are iso-8859-1 strings. 245 # See RFC 2616 sec 2.2 which notes an exception for MIME-encoded 246 # text following RFC 2047. The basic status line parsing only 247 # accepts iso-8859-1. 248 249 def __init__(self, sock, debuglevel=0, method=None, url=None): 250 # If the response includes a content-length header, we need to 251 # make sure that the client doesn't read more than the 252 # specified number of bytes. If it does, it will block until 253 # the server times out and closes the connection. This will 254 # happen if a self.fp.read() is done (without a size) whether 255 # self.fp is buffered or not. So, no self.fp.read() by 256 # clients unless they know what they are doing. 257 self.fp = sock.makefile("rb") 258 self.debuglevel = debuglevel 259 self._method = method 260 261 # The HTTPResponse object is returned via urllib. The clients 262 # of http and urllib expect different attributes for the 263 # headers. headers is used here and supports urllib. msg is 264 # provided as a backwards compatibility layer for http 265 # clients. 266 267 self.headers = self.msg = None 268 269 # from the Status-Line of the response 270 self.version = _UNKNOWN # HTTP-Version 271 self.status = _UNKNOWN # Status-Code 272 self.reason = _UNKNOWN # Reason-Phrase 273 274 self.chunked = _UNKNOWN # is "chunked" being used? 275 self.chunk_left = _UNKNOWN # bytes left to read in current chunk 276 self.length = _UNKNOWN # number of bytes left in response 277 self.will_close = _UNKNOWN # conn will close at end of response 278 279 def _read_status(self): 280 line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") 281 if len(line) > _MAXLINE: 282 raise LineTooLong("status line") 283 if self.debuglevel > 0: 284 print("reply:", repr(line)) 285 if not line: 286 # Presumably, the server closed the connection before 287 # sending a valid response. 288 raise RemoteDisconnected("Remote end closed connection without" 289 " response") 290 try: 291 version, status, reason = line.split(None, 2) 292 except ValueError: 293 try: 294 version, status = line.split(None, 1) 295 reason = "" 296 except ValueError: 297 # empty version will cause next test to fail. 298 version = "" 299 if not version.startswith("HTTP/"): 300 self._close_conn() 301 raise BadStatusLine(line) 302 303 # The status code is a three-digit number 304 try: 305 status = int(status) 306 if status < 100 or status > 999: 307 raise BadStatusLine(line) 308 except ValueError: 309 raise BadStatusLine(line) 310 return version, status, reason 311 312 def begin(self): 313 if self.headers is not None: 314 # we've already started reading the response 315 return 316 317 # read until we get a non-100 response 318 while True: 319 version, status, reason = self._read_status() 320 if status != CONTINUE: 321 break 322 # skip the header from the 100 response 323 skipped_headers = _read_headers(self.fp) 324 if self.debuglevel > 0: 325 print("headers:", skipped_headers) 326 del skipped_headers 327 328 self.code = self.status = status 329 self.reason = reason.strip() 330 if version in ("HTTP/1.0", "HTTP/0.9"): 331 # Some servers might still return "0.9", treat it as 1.0 anyway 332 self.version = 10 333 elif version.startswith("HTTP/1."): 334 self.version = 11 # use HTTP/1.1 code for HTTP/1.x where x>=1 335 else: 336 raise UnknownProtocol(version) 337 338 self.headers = self.msg = parse_headers(self.fp) 339 340 if self.debuglevel > 0: 341 for hdr, val in self.headers.items(): 342 print("header:", hdr + ":", val) 343 344 # are we using the chunked-style of transfer encoding? 345 tr_enc = self.headers.get("transfer-encoding") 346 if tr_enc and tr_enc.lower() == "chunked": 347 self.chunked = True 348 self.chunk_left = None 349 else: 350 self.chunked = False 351 352 # will the connection close at the end of the response? 353 self.will_close = self._check_close() 354 355 # do we have a Content-Length? 356 # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked" 357 self.length = None 358 length = self.headers.get("content-length") 359 360 # are we using the chunked-style of transfer encoding? 361 tr_enc = self.headers.get("transfer-encoding") 362 if length and not self.chunked: 363 try: 364 self.length = int(length) 365 except ValueError: 366 self.length = None 367 else: 368 if self.length < 0: # ignore nonsensical negative lengths 369 self.length = None 370 else: 371 self.length = None 372 373 # does the body have a fixed length? (of zero) 374 if (status == NO_CONTENT or status == NOT_MODIFIED or 375 100 <= status < 200 or # 1xx codes 376 self._method == "HEAD"): 377 self.length = 0 378 379 # if the connection remains open, and we aren't using chunked, and 380 # a content-length was not provided, then assume that the connection 381 # WILL close. 382 if (not self.will_close and 383 not self.chunked and 384 self.length is None): 385 self.will_close = True 386 387 def _check_close(self): 388 conn = self.headers.get("connection") 389 if self.version == 11: 390 # An HTTP/1.1 proxy is assumed to stay open unless 391 # explicitly closed. 392 if conn and "close" in conn.lower(): 393 return True 394 return False 395 396 # Some HTTP/1.0 implementations have support for persistent 397 # connections, using rules different than HTTP/1.1. 398 399 # For older HTTP, Keep-Alive indicates persistent connection. 400 if self.headers.get("keep-alive"): 401 return False 402 403 # At least Akamai returns a "Connection: Keep-Alive" header, 404 # which was supposed to be sent by the client. 405 if conn and "keep-alive" in conn.lower(): 406 return False 407 408 # Proxy-Connection is a netscape hack. 409 pconn = self.headers.get("proxy-connection") 410 if pconn and "keep-alive" in pconn.lower(): 411 return False 412 413 # otherwise, assume it will close 414 return True 415 416 def _close_conn(self): 417 fp = self.fp 418 self.fp = None 419 fp.close() 420 421 def close(self): 422 try: 423 super().close() # set "closed" flag 424 finally: 425 if self.fp: 426 self._close_conn() 427 428 # These implementations are for the benefit of io.BufferedReader. 429 430 # XXX This class should probably be revised to act more like 431 # the "raw stream" that BufferedReader expects. 432 433 def flush(self): 434 super().flush() 435 if self.fp: 436 self.fp.flush() 437 438 def readable(self): 439 """Always returns True""" 440 return True 441 442 # End of "raw stream" methods 443 444 def isclosed(self): 445 """True if the connection is closed.""" 446 # NOTE: it is possible that we will not ever call self.close(). This 447 # case occurs when will_close is TRUE, length is None, and we 448 # read up to the last byte, but NOT past it. 449 # 450 # IMPLIES: if will_close is FALSE, then self.close() will ALWAYS be 451 # called, meaning self.isclosed() is meaningful. 452 return self.fp is None 453 454 def read(self, amt=None): 455 if self.fp is None: 456 return b"" 457 458 if self._method == "HEAD": 459 self._close_conn() 460 return b"" 461 462 if amt is not None: 463 # Amount is given, implement using readinto 464 b = bytearray(amt) 465 n = self.readinto(b) 466 return memoryview(b)[:n].tobytes() 467 else: 468 # Amount is not given (unbounded read) so we must check self.length 469 # and self.chunked 470 471 if self.chunked: 472 return self._readall_chunked() 473 474 if self.length is None: 475 s = self.fp.read() 476 else: 477 try: 478 s = self._safe_read(self.length) 479 except IncompleteRead: 480 self._close_conn() 481 raise 482 self.length = 0 483 self._close_conn() # we read everything 484 return s 485 486 def readinto(self, b): 487 """Read up to len(b) bytes into bytearray b and return the number 488 of bytes read. 489 """ 490 491 if self.fp is None: 492 return 0 493 494 if self._method == "HEAD": 495 self._close_conn() 496 return 0 497 498 if self.chunked: 499 return self._readinto_chunked(b) 500 501 if self.length is not None: 502 if len(b) > self.length: 503 # clip the read to the "end of response" 504 b = memoryview(b)[0:self.length] 505 506 # we do not use _safe_read() here because this may be a .will_close 507 # connection, and the user is reading more bytes than will be provided 508 # (for example, reading in 1k chunks) 509 n = self.fp.readinto(b) 510 if not n and b: 511 # Ideally, we would raise IncompleteRead if the content-length 512 # wasn't satisfied, but it might break compatibility. 513 self._close_conn() 514 elif self.length is not None: 515 self.length -= n 516 if not self.length: 517 self._close_conn() 518 return n 519 520 def _read_next_chunk_size(self): 521 # Read the next chunk size from the file 522 line = self.fp.readline(_MAXLINE + 1) 523 if len(line) > _MAXLINE: 524 raise LineTooLong("chunk size") 525 i = line.find(b";") 526 if i >= 0: 527 line = line[:i] # strip chunk-extensions 528 try: 529 return int(line, 16) 530 except ValueError: 531 # close the connection as protocol synchronisation is 532 # probably lost 533 self._close_conn() 534 raise 535 536 def _read_and_discard_trailer(self): 537 # read and discard trailer up to the CRLF terminator 538 ### note: we shouldn't have any trailers! 539 while True: 540 line = self.fp.readline(_MAXLINE + 1) 541 if len(line) > _MAXLINE: 542 raise LineTooLong("trailer line") 543 if not line: 544 # a vanishingly small number of sites EOF without 545 # sending the trailer 546 break 547 if line in (b'\r\n', b'\n', b''): 548 break 549 550 def _get_chunk_left(self): 551 # return self.chunk_left, reading a new chunk if necessary. 552 # chunk_left == 0: at the end of the current chunk, need to close it 553 # chunk_left == None: No current chunk, should read next. 554 # This function returns non-zero or None if the last chunk has 555 # been read. 556 chunk_left = self.chunk_left 557 if not chunk_left: # Can be 0 or None 558 if chunk_left is not None: 559 # We are at the end of chunk, discard chunk end 560 self._safe_read(2) # toss the CRLF at the end of the chunk 561 try: 562 chunk_left = self._read_next_chunk_size() 563 except ValueError: 564 raise IncompleteRead(b'') 565 if chunk_left == 0: 566 # last chunk: 1*("0") [ chunk-extension ] CRLF 567 self._read_and_discard_trailer() 568 # we read everything; close the "file" 569 self._close_conn() 570 chunk_left = None 571 self.chunk_left = chunk_left 572 return chunk_left 573 574 def _readall_chunked(self): 575 assert self.chunked != _UNKNOWN 576 value = [] 577 try: 578 while True: 579 chunk_left = self._get_chunk_left() 580 if chunk_left is None: 581 break 582 value.append(self._safe_read(chunk_left)) 583 self.chunk_left = 0 584 return b''.join(value) 585 except IncompleteRead: 586 raise IncompleteRead(b''.join(value)) 587 588 def _readinto_chunked(self, b): 589 assert self.chunked != _UNKNOWN 590 total_bytes = 0 591 mvb = memoryview(b) 592 try: 593 while True: 594 chunk_left = self._get_chunk_left() 595 if chunk_left is None: 596 return total_bytes 597 598 if len(mvb) <= chunk_left: 599 n = self._safe_readinto(mvb) 600 self.chunk_left = chunk_left - n 601 return total_bytes + n 602 603 temp_mvb = mvb[:chunk_left] 604 n = self._safe_readinto(temp_mvb) 605 mvb = mvb[n:] 606 total_bytes += n 607 self.chunk_left = 0 608 609 except IncompleteRead: 610 raise IncompleteRead(bytes(b[0:total_bytes])) 611 612 def _safe_read(self, amt): 613 """Read the number of bytes requested, compensating for partial reads. 614 615 Normally, we have a blocking socket, but a read() can be interrupted 616 by a signal (resulting in a partial read). 617 618 Note that we cannot distinguish between EOF and an interrupt when zero 619 bytes have been read. IncompleteRead() will be raised in this 620 situation. 621 622 This function should be used when <amt> bytes "should" be present for 623 reading. If the bytes are truly not available (due to EOF), then the 624 IncompleteRead exception can be used to detect the problem. 625 """ 626 s = [] 627 while amt > 0: 628 chunk = self.fp.read(min(amt, MAXAMOUNT)) 629 if not chunk: 630 raise IncompleteRead(b''.join(s), amt) 631 s.append(chunk) 632 amt -= len(chunk) 633 return b"".join(s) 634 635 def _safe_readinto(self, b): 636 """Same as _safe_read, but for reading into a buffer.""" 637 total_bytes = 0 638 mvb = memoryview(b) 639 while total_bytes < len(b): 640 if MAXAMOUNT < len(mvb): 641 temp_mvb = mvb[0:MAXAMOUNT] 642 n = self.fp.readinto(temp_mvb) 643 else: 644 n = self.fp.readinto(mvb) 645 if not n: 646 raise IncompleteRead(bytes(mvb[0:total_bytes]), len(b)) 647 mvb = mvb[n:] 648 total_bytes += n 649 return total_bytes 650 651 def read1(self, n=-1): 652 """Read with at most one underlying system call. If at least one 653 byte is buffered, return that instead. 654 """ 655 if self.fp is None or self._method == "HEAD": 656 return b"" 657 if self.chunked: 658 return self._read1_chunked(n) 659 if self.length is not None and (n < 0 or n > self.length): 660 n = self.length 661 result = self.fp.read1(n) 662 if not result and n: 663 self._close_conn() 664 elif self.length is not None: 665 self.length -= len(result) 666 return result 667 668 def peek(self, n=-1): 669 # Having this enables IOBase.readline() to read more than one 670 # byte at a time 671 if self.fp is None or self._method == "HEAD": 672 return b"" 673 if self.chunked: 674 return self._peek_chunked(n) 675 return self.fp.peek(n) 676 677 def readline(self, limit=-1): 678 if self.fp is None or self._method == "HEAD": 679 return b"" 680 if self.chunked: 681 # Fallback to IOBase readline which uses peek() and read() 682 return super().readline(limit) 683 if self.length is not None and (limit < 0 or limit > self.length): 684 limit = self.length 685 result = self.fp.readline(limit) 686 if not result and limit: 687 self._close_conn() 688 elif self.length is not None: 689 self.length -= len(result) 690 return result 691 692 def _read1_chunked(self, n): 693 # Strictly speaking, _get_chunk_left() may cause more than one read, 694 # but that is ok, since that is to satisfy the chunked protocol. 695 chunk_left = self._get_chunk_left() 696 if chunk_left is None or n == 0: 697 return b'' 698 if not (0 <= n <= chunk_left): 699 n = chunk_left # if n is negative or larger than chunk_left 700 read = self.fp.read1(n) 701 self.chunk_left -= len(read) 702 if not read: 703 raise IncompleteRead(b"") 704 return read 705 706 def _peek_chunked(self, n): 707 # Strictly speaking, _get_chunk_left() may cause more than one read, 708 # but that is ok, since that is to satisfy the chunked protocol. 709 try: 710 chunk_left = self._get_chunk_left() 711 except IncompleteRead: 712 return b'' # peek doesn't worry about protocol 713 if chunk_left is None: 714 return b'' # eof 715 # peek is allowed to return more than requested. Just request the 716 # entire chunk, and truncate what we get. 717 return self.fp.peek(chunk_left)[:chunk_left] 718 719 def fileno(self): 720 return self.fp.fileno() 721 722 def getheader(self, name, default=None): 723 '''Returns the value of the header matching *name*. 724 725 If there are multiple matching headers, the values are 726 combined into a single string separated by commas and spaces. 727 728 If no matching header is found, returns *default* or None if 729 the *default* is not specified. 730 731 If the headers are unknown, raises http.client.ResponseNotReady. 732 733 ''' 734 if self.headers is None: 735 raise ResponseNotReady() 736 headers = self.headers.get_all(name) or default 737 if isinstance(headers, str) or not hasattr(headers, '__iter__'): 738 return headers 739 else: 740 return ', '.join(headers) 741 742 def getheaders(self): 743 """Return list of (header, value) tuples.""" 744 if self.headers is None: 745 raise ResponseNotReady() 746 return list(self.headers.items()) 747 748 # We override IOBase.__iter__ so that it doesn't check for closed-ness 749 750 def __iter__(self): 751 return self 752 753 # For compatibility with old-style urllib responses. 754 755 def info(self): 756 '''Returns an instance of the class mimetools.Message containing 757 meta-information associated with the URL. 758 759 When the method is HTTP, these headers are those returned by 760 the server at the head of the retrieved HTML page (including 761 Content-Length and Content-Type). 762 763 When the method is FTP, a Content-Length header will be 764 present if (as is now usual) the server passed back a file 765 length in response to the FTP retrieval request. A 766 Content-Type header will be present if the MIME type can be 767 guessed. 768 769 When the method is local-file, returned headers will include 770 a Date representing the file's last-modified time, a 771 Content-Length giving file size, and a Content-Type 772 containing a guess at the file's type. See also the 773 description of the mimetools module. 774 775 ''' 776 return self.headers 777 778 def geturl(self): 779 '''Return the real URL of the page. 780 781 In some cases, the HTTP server redirects a client to another 782 URL. The urlopen() function handles this transparently, but in 783 some cases the caller needs to know which URL the client was 784 redirected to. The geturl() method can be used to get at this 785 redirected URL. 786 787 ''' 788 return self.url 789 790 def getcode(self): 791 '''Return the HTTP status code that was sent with the response, 792 or None if the URL is not an HTTP URL. 793 794 ''' 795 return self.status 796 797class HTTPConnection: 798 799 _http_vsn = 11 800 _http_vsn_str = 'HTTP/1.1' 801 802 response_class = HTTPResponse 803 default_port = HTTP_PORT 804 auto_open = 1 805 debuglevel = 0 806 807 @staticmethod 808 def _is_textIO(stream): 809 """Test whether a file-like object is a text or a binary stream. 810 """ 811 return isinstance(stream, io.TextIOBase) 812 813 @staticmethod 814 def _get_content_length(body, method): 815 """Get the content-length based on the body. 816 817 If the body is None, we set Content-Length: 0 for methods that expect 818 a body (RFC 7230, Section 3.3.2). We also set the Content-Length for 819 any method if the body is a str or bytes-like object and not a file. 820 """ 821 if body is None: 822 # do an explicit check for not None here to distinguish 823 # between unset and set but empty 824 if method.upper() in _METHODS_EXPECTING_BODY: 825 return 0 826 else: 827 return None 828 829 if hasattr(body, 'read'): 830 # file-like object. 831 return None 832 833 try: 834 # does it implement the buffer protocol (bytes, bytearray, array)? 835 mv = memoryview(body) 836 return mv.nbytes 837 except TypeError: 838 pass 839 840 if isinstance(body, str): 841 return len(body) 842 843 return None 844 845 def __init__(self, host, port=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, 846 source_address=None, blocksize=8192): 847 self.timeout = timeout 848 self.source_address = source_address 849 self.blocksize = blocksize 850 self.sock = None 851 self._buffer = [] 852 self.__response = None 853 self.__state = _CS_IDLE 854 self._method = None 855 self._tunnel_host = None 856 self._tunnel_port = None 857 self._tunnel_headers = {} 858 859 (self.host, self.port) = self._get_hostport(host, port) 860 861 self._validate_host(self.host) 862 863 # This is stored as an instance variable to allow unit 864 # tests to replace it with a suitable mockup 865 self._create_connection = socket.create_connection 866 867 def set_tunnel(self, host, port=None, headers=None): 868 """Set up host and port for HTTP CONNECT tunnelling. 869 870 In a connection that uses HTTP CONNECT tunneling, the host passed to the 871 constructor is used as a proxy server that relays all communication to 872 the endpoint passed to `set_tunnel`. This done by sending an HTTP 873 CONNECT request to the proxy server when the connection is established. 874 875 This method must be called before the HTML connection has been 876 established. 877 878 The headers argument should be a mapping of extra HTTP headers to send 879 with the CONNECT request. 880 """ 881 882 if self.sock: 883 raise RuntimeError("Can't set up tunnel for established connection") 884 885 self._tunnel_host, self._tunnel_port = self._get_hostport(host, port) 886 if headers: 887 self._tunnel_headers = headers 888 else: 889 self._tunnel_headers.clear() 890 891 def _get_hostport(self, host, port): 892 if port is None: 893 i = host.rfind(':') 894 j = host.rfind(']') # ipv6 addresses have [...] 895 if i > j: 896 try: 897 port = int(host[i+1:]) 898 except ValueError: 899 if host[i+1:] == "": # http://foo.com:/ == http://foo.com/ 900 port = self.default_port 901 else: 902 raise InvalidURL("nonnumeric port: '%s'" % host[i+1:]) 903 host = host[:i] 904 else: 905 port = self.default_port 906 if host and host[0] == '[' and host[-1] == ']': 907 host = host[1:-1] 908 909 return (host, port) 910 911 def set_debuglevel(self, level): 912 self.debuglevel = level 913 914 def _tunnel(self): 915 connect_str = "CONNECT %s:%d HTTP/1.0\r\n" % (self._tunnel_host, 916 self._tunnel_port) 917 connect_bytes = connect_str.encode("ascii") 918 self.send(connect_bytes) 919 for header, value in self._tunnel_headers.items(): 920 header_str = "%s: %s\r\n" % (header, value) 921 header_bytes = header_str.encode("latin-1") 922 self.send(header_bytes) 923 self.send(b'\r\n') 924 925 response = self.response_class(self.sock, method=self._method) 926 (version, code, message) = response._read_status() 927 928 if code != http.HTTPStatus.OK: 929 self.close() 930 raise OSError("Tunnel connection failed: %d %s" % (code, 931 message.strip())) 932 while True: 933 line = response.fp.readline(_MAXLINE + 1) 934 if len(line) > _MAXLINE: 935 raise LineTooLong("header line") 936 if not line: 937 # for sites which EOF without sending a trailer 938 break 939 if line in (b'\r\n', b'\n', b''): 940 break 941 942 if self.debuglevel > 0: 943 print('header:', line.decode()) 944 945 def connect(self): 946 """Connect to the host and port specified in __init__.""" 947 self.sock = self._create_connection( 948 (self.host,self.port), self.timeout, self.source_address) 949 self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 950 951 if self._tunnel_host: 952 self._tunnel() 953 954 def close(self): 955 """Close the connection to the HTTP server.""" 956 self.__state = _CS_IDLE 957 try: 958 sock = self.sock 959 if sock: 960 self.sock = None 961 sock.close() # close it manually... there may be other refs 962 finally: 963 response = self.__response 964 if response: 965 self.__response = None 966 response.close() 967 968 def send(self, data): 969 """Send `data' to the server. 970 ``data`` can be a string object, a bytes object, an array object, a 971 file-like object that supports a .read() method, or an iterable object. 972 """ 973 974 if self.sock is None: 975 if self.auto_open: 976 self.connect() 977 else: 978 raise NotConnected() 979 980 if self.debuglevel > 0: 981 print("send:", repr(data)) 982 if hasattr(data, "read") : 983 if self.debuglevel > 0: 984 print("sendIng a read()able") 985 encode = self._is_textIO(data) 986 if encode and self.debuglevel > 0: 987 print("encoding file using iso-8859-1") 988 while 1: 989 datablock = data.read(self.blocksize) 990 if not datablock: 991 break 992 if encode: 993 datablock = datablock.encode("iso-8859-1") 994 self.sock.sendall(datablock) 995 return 996 try: 997 self.sock.sendall(data) 998 except TypeError: 999 if isinstance(data, collections.abc.Iterable): 1000 for d in data: 1001 self.sock.sendall(d) 1002 else: 1003 raise TypeError("data should be a bytes-like object " 1004 "or an iterable, got %r" % type(data)) 1005 1006 def _output(self, s): 1007 """Add a line of output to the current request buffer. 1008 1009 Assumes that the line does *not* end with \\r\\n. 1010 """ 1011 self._buffer.append(s) 1012 1013 def _read_readable(self, readable): 1014 if self.debuglevel > 0: 1015 print("sendIng a read()able") 1016 encode = self._is_textIO(readable) 1017 if encode and self.debuglevel > 0: 1018 print("encoding file using iso-8859-1") 1019 while True: 1020 datablock = readable.read(self.blocksize) 1021 if not datablock: 1022 break 1023 if encode: 1024 datablock = datablock.encode("iso-8859-1") 1025 yield datablock 1026 1027 def _send_output(self, message_body=None, encode_chunked=False): 1028 """Send the currently buffered request and clear the buffer. 1029 1030 Appends an extra \\r\\n to the buffer. 1031 A message_body may be specified, to be appended to the request. 1032 """ 1033 self._buffer.extend((b"", b"")) 1034 msg = b"\r\n".join(self._buffer) 1035 del self._buffer[:] 1036 self.send(msg) 1037 1038 if message_body is not None: 1039 1040 # create a consistent interface to message_body 1041 if hasattr(message_body, 'read'): 1042 # Let file-like take precedence over byte-like. This 1043 # is needed to allow the current position of mmap'ed 1044 # files to be taken into account. 1045 chunks = self._read_readable(message_body) 1046 else: 1047 try: 1048 # this is solely to check to see if message_body 1049 # implements the buffer API. it /would/ be easier 1050 # to capture if PyObject_CheckBuffer was exposed 1051 # to Python. 1052 memoryview(message_body) 1053 except TypeError: 1054 try: 1055 chunks = iter(message_body) 1056 except TypeError: 1057 raise TypeError("message_body should be a bytes-like " 1058 "object or an iterable, got %r" 1059 % type(message_body)) 1060 else: 1061 # the object implements the buffer interface and 1062 # can be passed directly into socket methods 1063 chunks = (message_body,) 1064 1065 for chunk in chunks: 1066 if not chunk: 1067 if self.debuglevel > 0: 1068 print('Zero length chunk ignored') 1069 continue 1070 1071 if encode_chunked and self._http_vsn == 11: 1072 # chunked encoding 1073 chunk = f'{len(chunk):X}\r\n'.encode('ascii') + chunk \ 1074 + b'\r\n' 1075 self.send(chunk) 1076 1077 if encode_chunked and self._http_vsn == 11: 1078 # end chunked transfer 1079 self.send(b'0\r\n\r\n') 1080 1081 def putrequest(self, method, url, skip_host=False, 1082 skip_accept_encoding=False): 1083 """Send a request to the server. 1084 1085 `method' specifies an HTTP request method, e.g. 'GET'. 1086 `url' specifies the object being requested, e.g. '/index.html'. 1087 `skip_host' if True does not add automatically a 'Host:' header 1088 `skip_accept_encoding' if True does not add automatically an 1089 'Accept-Encoding:' header 1090 """ 1091 1092 # if a prior response has been completed, then forget about it. 1093 if self.__response and self.__response.isclosed(): 1094 self.__response = None 1095 1096 1097 # in certain cases, we cannot issue another request on this connection. 1098 # this occurs when: 1099 # 1) we are in the process of sending a request. (_CS_REQ_STARTED) 1100 # 2) a response to a previous request has signalled that it is going 1101 # to close the connection upon completion. 1102 # 3) the headers for the previous response have not been read, thus 1103 # we cannot determine whether point (2) is true. (_CS_REQ_SENT) 1104 # 1105 # if there is no prior response, then we can request at will. 1106 # 1107 # if point (2) is true, then we will have passed the socket to the 1108 # response (effectively meaning, "there is no prior response"), and 1109 # will open a new one when a new request is made. 1110 # 1111 # Note: if a prior response exists, then we *can* start a new request. 1112 # We are not allowed to begin fetching the response to this new 1113 # request, however, until that prior response is complete. 1114 # 1115 if self.__state == _CS_IDLE: 1116 self.__state = _CS_REQ_STARTED 1117 else: 1118 raise CannotSendRequest(self.__state) 1119 1120 self._validate_method(method) 1121 1122 # Save the method for use later in the response phase 1123 self._method = method 1124 1125 url = url or '/' 1126 self._validate_path(url) 1127 1128 request = '%s %s %s' % (method, url, self._http_vsn_str) 1129 1130 self._output(self._encode_request(request)) 1131 1132 if self._http_vsn == 11: 1133 # Issue some standard headers for better HTTP/1.1 compliance 1134 1135 if not skip_host: 1136 # this header is issued *only* for HTTP/1.1 1137 # connections. more specifically, this means it is 1138 # only issued when the client uses the new 1139 # HTTPConnection() class. backwards-compat clients 1140 # will be using HTTP/1.0 and those clients may be 1141 # issuing this header themselves. we should NOT issue 1142 # it twice; some web servers (such as Apache) barf 1143 # when they see two Host: headers 1144 1145 # If we need a non-standard port,include it in the 1146 # header. If the request is going through a proxy, 1147 # but the host of the actual URL, not the host of the 1148 # proxy. 1149 1150 netloc = '' 1151 if url.startswith('http'): 1152 nil, netloc, nil, nil, nil = urlsplit(url) 1153 1154 if netloc: 1155 try: 1156 netloc_enc = netloc.encode("ascii") 1157 except UnicodeEncodeError: 1158 netloc_enc = netloc.encode("idna") 1159 self.putheader('Host', netloc_enc) 1160 else: 1161 if self._tunnel_host: 1162 host = self._tunnel_host 1163 port = self._tunnel_port 1164 else: 1165 host = self.host 1166 port = self.port 1167 1168 try: 1169 host_enc = host.encode("ascii") 1170 except UnicodeEncodeError: 1171 host_enc = host.encode("idna") 1172 1173 # As per RFC 273, IPv6 address should be wrapped with [] 1174 # when used as Host header 1175 1176 if host.find(':') >= 0: 1177 host_enc = b'[' + host_enc + b']' 1178 1179 if port == self.default_port: 1180 self.putheader('Host', host_enc) 1181 else: 1182 host_enc = host_enc.decode("ascii") 1183 self.putheader('Host', "%s:%s" % (host_enc, port)) 1184 1185 # note: we are assuming that clients will not attempt to set these 1186 # headers since *this* library must deal with the 1187 # consequences. this also means that when the supporting 1188 # libraries are updated to recognize other forms, then this 1189 # code should be changed (removed or updated). 1190 1191 # we only want a Content-Encoding of "identity" since we don't 1192 # support encodings such as x-gzip or x-deflate. 1193 if not skip_accept_encoding: 1194 self.putheader('Accept-Encoding', 'identity') 1195 1196 # we can accept "chunked" Transfer-Encodings, but no others 1197 # NOTE: no TE header implies *only* "chunked" 1198 #self.putheader('TE', 'chunked') 1199 1200 # if TE is supplied in the header, then it must appear in a 1201 # Connection header. 1202 #self.putheader('Connection', 'TE') 1203 1204 else: 1205 # For HTTP/1.0, the server will assume "not chunked" 1206 pass 1207 1208 def _encode_request(self, request): 1209 # ASCII also helps prevent CVE-2019-9740. 1210 return request.encode('ascii') 1211 1212 def _validate_method(self, method): 1213 """Validate a method name for putrequest.""" 1214 # prevent http header injection 1215 match = _contains_disallowed_method_pchar_re.search(method) 1216 if match: 1217 raise ValueError( 1218 f"method can't contain control characters. {method!r} " 1219 f"(found at least {match.group()!r})") 1220 1221 def _validate_path(self, url): 1222 """Validate a url for putrequest.""" 1223 # Prevent CVE-2019-9740. 1224 match = _contains_disallowed_url_pchar_re.search(url) 1225 if match: 1226 raise InvalidURL(f"URL can't contain control characters. {url!r} " 1227 f"(found at least {match.group()!r})") 1228 1229 def _validate_host(self, host): 1230 """Validate a host so it doesn't contain control characters.""" 1231 # Prevent CVE-2019-18348. 1232 match = _contains_disallowed_url_pchar_re.search(host) 1233 if match: 1234 raise InvalidURL(f"URL can't contain control characters. {host!r} " 1235 f"(found at least {match.group()!r})") 1236 1237 def putheader(self, header, *values): 1238 """Send a request header line to the server. 1239 1240 For example: h.putheader('Accept', 'text/html') 1241 """ 1242 if self.__state != _CS_REQ_STARTED: 1243 raise CannotSendHeader() 1244 1245 if hasattr(header, 'encode'): 1246 header = header.encode('ascii') 1247 1248 if not _is_legal_header_name(header): 1249 raise ValueError('Invalid header name %r' % (header,)) 1250 1251 values = list(values) 1252 for i, one_value in enumerate(values): 1253 if hasattr(one_value, 'encode'): 1254 values[i] = one_value.encode('latin-1') 1255 elif isinstance(one_value, int): 1256 values[i] = str(one_value).encode('ascii') 1257 1258 if _is_illegal_header_value(values[i]): 1259 raise ValueError('Invalid header value %r' % (values[i],)) 1260 1261 value = b'\r\n\t'.join(values) 1262 header = header + b': ' + value 1263 self._output(header) 1264 1265 def endheaders(self, message_body=None, *, encode_chunked=False): 1266 """Indicate that the last header line has been sent to the server. 1267 1268 This method sends the request to the server. The optional message_body 1269 argument can be used to pass a message body associated with the 1270 request. 1271 """ 1272 if self.__state == _CS_REQ_STARTED: 1273 self.__state = _CS_REQ_SENT 1274 else: 1275 raise CannotSendHeader() 1276 self._send_output(message_body, encode_chunked=encode_chunked) 1277 1278 def request(self, method, url, body=None, headers={}, *, 1279 encode_chunked=False): 1280 """Send a complete request to the server.""" 1281 self._send_request(method, url, body, headers, encode_chunked) 1282 1283 def _send_request(self, method, url, body, headers, encode_chunked): 1284 # Honor explicitly requested Host: and Accept-Encoding: headers. 1285 header_names = frozenset(k.lower() for k in headers) 1286 skips = {} 1287 if 'host' in header_names: 1288 skips['skip_host'] = 1 1289 if 'accept-encoding' in header_names: 1290 skips['skip_accept_encoding'] = 1 1291 1292 self.putrequest(method, url, **skips) 1293 1294 # chunked encoding will happen if HTTP/1.1 is used and either 1295 # the caller passes encode_chunked=True or the following 1296 # conditions hold: 1297 # 1. content-length has not been explicitly set 1298 # 2. the body is a file or iterable, but not a str or bytes-like 1299 # 3. Transfer-Encoding has NOT been explicitly set by the caller 1300 1301 if 'content-length' not in header_names: 1302 # only chunk body if not explicitly set for backwards 1303 # compatibility, assuming the client code is already handling the 1304 # chunking 1305 if 'transfer-encoding' not in header_names: 1306 # if content-length cannot be automatically determined, fall 1307 # back to chunked encoding 1308 encode_chunked = False 1309 content_length = self._get_content_length(body, method) 1310 if content_length is None: 1311 if body is not None: 1312 if self.debuglevel > 0: 1313 print('Unable to determine size of %r' % body) 1314 encode_chunked = True 1315 self.putheader('Transfer-Encoding', 'chunked') 1316 else: 1317 self.putheader('Content-Length', str(content_length)) 1318 else: 1319 encode_chunked = False 1320 1321 for hdr, value in headers.items(): 1322 self.putheader(hdr, value) 1323 if isinstance(body, str): 1324 # RFC 2616 Section 3.7.1 says that text default has a 1325 # default charset of iso-8859-1. 1326 body = _encode(body, 'body') 1327 self.endheaders(body, encode_chunked=encode_chunked) 1328 1329 def getresponse(self): 1330 """Get the response from the server. 1331 1332 If the HTTPConnection is in the correct state, returns an 1333 instance of HTTPResponse or of whatever object is returned by 1334 the response_class variable. 1335 1336 If a request has not been sent or if a previous response has 1337 not be handled, ResponseNotReady is raised. If the HTTP 1338 response indicates that the connection should be closed, then 1339 it will be closed before the response is returned. When the 1340 connection is closed, the underlying socket is closed. 1341 """ 1342 1343 # if a prior response has been completed, then forget about it. 1344 if self.__response and self.__response.isclosed(): 1345 self.__response = None 1346 1347 # if a prior response exists, then it must be completed (otherwise, we 1348 # cannot read this response's header to determine the connection-close 1349 # behavior) 1350 # 1351 # note: if a prior response existed, but was connection-close, then the 1352 # socket and response were made independent of this HTTPConnection 1353 # object since a new request requires that we open a whole new 1354 # connection 1355 # 1356 # this means the prior response had one of two states: 1357 # 1) will_close: this connection was reset and the prior socket and 1358 # response operate independently 1359 # 2) persistent: the response was retained and we await its 1360 # isclosed() status to become true. 1361 # 1362 if self.__state != _CS_REQ_SENT or self.__response: 1363 raise ResponseNotReady(self.__state) 1364 1365 if self.debuglevel > 0: 1366 response = self.response_class(self.sock, self.debuglevel, 1367 method=self._method) 1368 else: 1369 response = self.response_class(self.sock, method=self._method) 1370 1371 try: 1372 try: 1373 response.begin() 1374 except ConnectionError: 1375 self.close() 1376 raise 1377 assert response.will_close != _UNKNOWN 1378 self.__state = _CS_IDLE 1379 1380 if response.will_close: 1381 # this effectively passes the connection to the response 1382 self.close() 1383 else: 1384 # remember this, so we can tell when it is complete 1385 self.__response = response 1386 1387 return response 1388 except: 1389 response.close() 1390 raise 1391 1392try: 1393 import ssl 1394except ImportError: 1395 pass 1396else: 1397 class HTTPSConnection(HTTPConnection): 1398 "This class allows communication via SSL." 1399 1400 default_port = HTTPS_PORT 1401 1402 # XXX Should key_file and cert_file be deprecated in favour of context? 1403 1404 def __init__(self, host, port=None, key_file=None, cert_file=None, 1405 timeout=socket._GLOBAL_DEFAULT_TIMEOUT, 1406 source_address=None, *, context=None, 1407 check_hostname=None, blocksize=8192): 1408 super(HTTPSConnection, self).__init__(host, port, timeout, 1409 source_address, 1410 blocksize=blocksize) 1411 if (key_file is not None or cert_file is not None or 1412 check_hostname is not None): 1413 import warnings 1414 warnings.warn("key_file, cert_file and check_hostname are " 1415 "deprecated, use a custom context instead.", 1416 DeprecationWarning, 2) 1417 self.key_file = key_file 1418 self.cert_file = cert_file 1419 if context is None: 1420 context = ssl._create_default_https_context() 1421 # enable PHA for TLS 1.3 connections if available 1422 if context.post_handshake_auth is not None: 1423 context.post_handshake_auth = True 1424 will_verify = context.verify_mode != ssl.CERT_NONE 1425 if check_hostname is None: 1426 check_hostname = context.check_hostname 1427 if check_hostname and not will_verify: 1428 raise ValueError("check_hostname needs a SSL context with " 1429 "either CERT_OPTIONAL or CERT_REQUIRED") 1430 if key_file or cert_file: 1431 context.load_cert_chain(cert_file, key_file) 1432 # cert and key file means the user wants to authenticate. 1433 # enable TLS 1.3 PHA implicitly even for custom contexts. 1434 if context.post_handshake_auth is not None: 1435 context.post_handshake_auth = True 1436 self._context = context 1437 if check_hostname is not None: 1438 self._context.check_hostname = check_hostname 1439 1440 def connect(self): 1441 "Connect to a host on a given (SSL) port." 1442 1443 super().connect() 1444 1445 if self._tunnel_host: 1446 server_hostname = self._tunnel_host 1447 else: 1448 server_hostname = self.host 1449 1450 self.sock = self._context.wrap_socket(self.sock, 1451 server_hostname=server_hostname) 1452 1453 __all__.append("HTTPSConnection") 1454 1455class HTTPException(Exception): 1456 # Subclasses that define an __init__ must call Exception.__init__ 1457 # or define self.args. Otherwise, str() will fail. 1458 pass 1459 1460class NotConnected(HTTPException): 1461 pass 1462 1463class InvalidURL(HTTPException): 1464 pass 1465 1466class UnknownProtocol(HTTPException): 1467 def __init__(self, version): 1468 self.args = version, 1469 self.version = version 1470 1471class UnknownTransferEncoding(HTTPException): 1472 pass 1473 1474class UnimplementedFileMode(HTTPException): 1475 pass 1476 1477class IncompleteRead(HTTPException): 1478 def __init__(self, partial, expected=None): 1479 self.args = partial, 1480 self.partial = partial 1481 self.expected = expected 1482 def __repr__(self): 1483 if self.expected is not None: 1484 e = ', %i more expected' % self.expected 1485 else: 1486 e = '' 1487 return '%s(%i bytes read%s)' % (self.__class__.__name__, 1488 len(self.partial), e) 1489 def __str__(self): 1490 return repr(self) 1491 1492class ImproperConnectionState(HTTPException): 1493 pass 1494 1495class CannotSendRequest(ImproperConnectionState): 1496 pass 1497 1498class CannotSendHeader(ImproperConnectionState): 1499 pass 1500 1501class ResponseNotReady(ImproperConnectionState): 1502 pass 1503 1504class BadStatusLine(HTTPException): 1505 def __init__(self, line): 1506 if not line: 1507 line = repr(line) 1508 self.args = line, 1509 self.line = line 1510 1511class LineTooLong(HTTPException): 1512 def __init__(self, line_type): 1513 HTTPException.__init__(self, "got more than %d bytes when reading %s" 1514 % (_MAXLINE, line_type)) 1515 1516class RemoteDisconnected(ConnectionResetError, BadStatusLine): 1517 def __init__(self, *pos, **kw): 1518 BadStatusLine.__init__(self, "") 1519 ConnectionResetError.__init__(self, *pos, **kw) 1520 1521# for backwards compatibility 1522error = HTTPException 1523