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