xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/http/client.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
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        """Read and return the response body, or up to the next amt bytes."""
452        if self.fp is None:
453            return b""
454
455        if self._method == "HEAD":
456            self._close_conn()
457            return b""
458
459        if self.chunked:
460            return self._read_chunked(amt)
461
462        if amt is not None:
463            if self.length is not None and amt > self.length:
464                # clip the read to the "end of response"
465                amt = self.length
466            s = self.fp.read(amt)
467            if not s and amt:
468                # Ideally, we would raise IncompleteRead if the content-length
469                # wasn't satisfied, but it might break compatibility.
470                self._close_conn()
471            elif self.length is not None:
472                self.length -= len(s)
473                if not self.length:
474                    self._close_conn()
475            return s
476        else:
477            # Amount is not given (unbounded read) so we must check self.length
478            if self.length is None:
479                s = self.fp.read()
480            else:
481                try:
482                    s = self._safe_read(self.length)
483                except IncompleteRead:
484                    self._close_conn()
485                    raise
486                self.length = 0
487            self._close_conn()        # we read everything
488            return s
489
490    def readinto(self, b):
491        """Read up to len(b) bytes into bytearray b and return the number
492        of bytes read.
493        """
494
495        if self.fp is None:
496            return 0
497
498        if self._method == "HEAD":
499            self._close_conn()
500            return 0
501
502        if self.chunked:
503            return self._readinto_chunked(b)
504
505        if self.length is not None:
506            if len(b) > self.length:
507                # clip the read to the "end of response"
508                b = memoryview(b)[0:self.length]
509
510        # we do not use _safe_read() here because this may be a .will_close
511        # connection, and the user is reading more bytes than will be provided
512        # (for example, reading in 1k chunks)
513        n = self.fp.readinto(b)
514        if not n and b:
515            # Ideally, we would raise IncompleteRead if the content-length
516            # wasn't satisfied, but it might break compatibility.
517            self._close_conn()
518        elif self.length is not None:
519            self.length -= n
520            if not self.length:
521                self._close_conn()
522        return n
523
524    def _read_next_chunk_size(self):
525        # Read the next chunk size from the file
526        line = self.fp.readline(_MAXLINE + 1)
527        if len(line) > _MAXLINE:
528            raise LineTooLong("chunk size")
529        i = line.find(b";")
530        if i >= 0:
531            line = line[:i] # strip chunk-extensions
532        try:
533            return int(line, 16)
534        except ValueError:
535            # close the connection as protocol synchronisation is
536            # probably lost
537            self._close_conn()
538            raise
539
540    def _read_and_discard_trailer(self):
541        # read and discard trailer up to the CRLF terminator
542        ### note: we shouldn't have any trailers!
543        while True:
544            line = self.fp.readline(_MAXLINE + 1)
545            if len(line) > _MAXLINE:
546                raise LineTooLong("trailer line")
547            if not line:
548                # a vanishingly small number of sites EOF without
549                # sending the trailer
550                break
551            if line in (b'\r\n', b'\n', b''):
552                break
553
554    def _get_chunk_left(self):
555        # return self.chunk_left, reading a new chunk if necessary.
556        # chunk_left == 0: at the end of the current chunk, need to close it
557        # chunk_left == None: No current chunk, should read next.
558        # This function returns non-zero or None if the last chunk has
559        # been read.
560        chunk_left = self.chunk_left
561        if not chunk_left: # Can be 0 or None
562            if chunk_left is not None:
563                # We are at the end of chunk, discard chunk end
564                self._safe_read(2)  # toss the CRLF at the end of the chunk
565            try:
566                chunk_left = self._read_next_chunk_size()
567            except ValueError:
568                raise IncompleteRead(b'')
569            if chunk_left == 0:
570                # last chunk: 1*("0") [ chunk-extension ] CRLF
571                self._read_and_discard_trailer()
572                # we read everything; close the "file"
573                self._close_conn()
574                chunk_left = None
575            self.chunk_left = chunk_left
576        return chunk_left
577
578    def _read_chunked(self, amt=None):
579        assert self.chunked != _UNKNOWN
580        value = []
581        try:
582            while True:
583                chunk_left = self._get_chunk_left()
584                if chunk_left is None:
585                    break
586
587                if amt is not None and amt <= chunk_left:
588                    value.append(self._safe_read(amt))
589                    self.chunk_left = chunk_left - amt
590                    break
591
592                value.append(self._safe_read(chunk_left))
593                if amt is not None:
594                    amt -= chunk_left
595                self.chunk_left = 0
596            return b''.join(value)
597        except IncompleteRead as exc:
598            raise IncompleteRead(b''.join(value)) from exc
599
600    def _readinto_chunked(self, b):
601        assert self.chunked != _UNKNOWN
602        total_bytes = 0
603        mvb = memoryview(b)
604        try:
605            while True:
606                chunk_left = self._get_chunk_left()
607                if chunk_left is None:
608                    return total_bytes
609
610                if len(mvb) <= chunk_left:
611                    n = self._safe_readinto(mvb)
612                    self.chunk_left = chunk_left - n
613                    return total_bytes + n
614
615                temp_mvb = mvb[:chunk_left]
616                n = self._safe_readinto(temp_mvb)
617                mvb = mvb[n:]
618                total_bytes += n
619                self.chunk_left = 0
620
621        except IncompleteRead:
622            raise IncompleteRead(bytes(b[0:total_bytes]))
623
624    def _safe_read(self, amt):
625        """Read the number of bytes requested.
626
627        This function should be used when <amt> bytes "should" be present for
628        reading. If the bytes are truly not available (due to EOF), then the
629        IncompleteRead exception can be used to detect the problem.
630        """
631        data = self.fp.read(amt)
632        if len(data) < amt:
633            raise IncompleteRead(data, amt-len(data))
634        return data
635
636    def _safe_readinto(self, b):
637        """Same as _safe_read, but for reading into a buffer."""
638        amt = len(b)
639        n = self.fp.readinto(b)
640        if n < amt:
641            raise IncompleteRead(bytes(b[:n]), amt-n)
642        return n
643
644    def read1(self, n=-1):
645        """Read with at most one underlying system call.  If at least one
646        byte is buffered, return that instead.
647        """
648        if self.fp is None or self._method == "HEAD":
649            return b""
650        if self.chunked:
651            return self._read1_chunked(n)
652        if self.length is not None and (n < 0 or n > self.length):
653            n = self.length
654        result = self.fp.read1(n)
655        if not result and n:
656            self._close_conn()
657        elif self.length is not None:
658            self.length -= len(result)
659        return result
660
661    def peek(self, n=-1):
662        # Having this enables IOBase.readline() to read more than one
663        # byte at a time
664        if self.fp is None or self._method == "HEAD":
665            return b""
666        if self.chunked:
667            return self._peek_chunked(n)
668        return self.fp.peek(n)
669
670    def readline(self, limit=-1):
671        if self.fp is None or self._method == "HEAD":
672            return b""
673        if self.chunked:
674            # Fallback to IOBase readline which uses peek() and read()
675            return super().readline(limit)
676        if self.length is not None and (limit < 0 or limit > self.length):
677            limit = self.length
678        result = self.fp.readline(limit)
679        if not result and limit:
680            self._close_conn()
681        elif self.length is not None:
682            self.length -= len(result)
683        return result
684
685    def _read1_chunked(self, n):
686        # Strictly speaking, _get_chunk_left() may cause more than one read,
687        # but that is ok, since that is to satisfy the chunked protocol.
688        chunk_left = self._get_chunk_left()
689        if chunk_left is None or n == 0:
690            return b''
691        if not (0 <= n <= chunk_left):
692            n = chunk_left # if n is negative or larger than chunk_left
693        read = self.fp.read1(n)
694        self.chunk_left -= len(read)
695        if not read:
696            raise IncompleteRead(b"")
697        return read
698
699    def _peek_chunked(self, n):
700        # Strictly speaking, _get_chunk_left() may cause more than one read,
701        # but that is ok, since that is to satisfy the chunked protocol.
702        try:
703            chunk_left = self._get_chunk_left()
704        except IncompleteRead:
705            return b'' # peek doesn't worry about protocol
706        if chunk_left is None:
707            return b'' # eof
708        # peek is allowed to return more than requested.  Just request the
709        # entire chunk, and truncate what we get.
710        return self.fp.peek(chunk_left)[:chunk_left]
711
712    def fileno(self):
713        return self.fp.fileno()
714
715    def getheader(self, name, default=None):
716        '''Returns the value of the header matching *name*.
717
718        If there are multiple matching headers, the values are
719        combined into a single string separated by commas and spaces.
720
721        If no matching header is found, returns *default* or None if
722        the *default* is not specified.
723
724        If the headers are unknown, raises http.client.ResponseNotReady.
725
726        '''
727        if self.headers is None:
728            raise ResponseNotReady()
729        headers = self.headers.get_all(name) or default
730        if isinstance(headers, str) or not hasattr(headers, '__iter__'):
731            return headers
732        else:
733            return ', '.join(headers)
734
735    def getheaders(self):
736        """Return list of (header, value) tuples."""
737        if self.headers is None:
738            raise ResponseNotReady()
739        return list(self.headers.items())
740
741    # We override IOBase.__iter__ so that it doesn't check for closed-ness
742
743    def __iter__(self):
744        return self
745
746    # For compatibility with old-style urllib responses.
747
748    def info(self):
749        '''Returns an instance of the class mimetools.Message containing
750        meta-information associated with the URL.
751
752        When the method is HTTP, these headers are those returned by
753        the server at the head of the retrieved HTML page (including
754        Content-Length and Content-Type).
755
756        When the method is FTP, a Content-Length header will be
757        present if (as is now usual) the server passed back a file
758        length in response to the FTP retrieval request. A
759        Content-Type header will be present if the MIME type can be
760        guessed.
761
762        When the method is local-file, returned headers will include
763        a Date representing the file's last-modified time, a
764        Content-Length giving file size, and a Content-Type
765        containing a guess at the file's type. See also the
766        description of the mimetools module.
767
768        '''
769        return self.headers
770
771    def geturl(self):
772        '''Return the real URL of the page.
773
774        In some cases, the HTTP server redirects a client to another
775        URL. The urlopen() function handles this transparently, but in
776        some cases the caller needs to know which URL the client was
777        redirected to. The geturl() method can be used to get at this
778        redirected URL.
779
780        '''
781        return self.url
782
783    def getcode(self):
784        '''Return the HTTP status code that was sent with the response,
785        or None if the URL is not an HTTP URL.
786
787        '''
788        return self.status
789
790class HTTPConnection:
791
792    _http_vsn = 11
793    _http_vsn_str = 'HTTP/1.1'
794
795    response_class = HTTPResponse
796    default_port = HTTP_PORT
797    auto_open = 1
798    debuglevel = 0
799
800    @staticmethod
801    def _is_textIO(stream):
802        """Test whether a file-like object is a text or a binary stream.
803        """
804        return isinstance(stream, io.TextIOBase)
805
806    @staticmethod
807    def _get_content_length(body, method):
808        """Get the content-length based on the body.
809
810        If the body is None, we set Content-Length: 0 for methods that expect
811        a body (RFC 7230, Section 3.3.2). We also set the Content-Length for
812        any method if the body is a str or bytes-like object and not a file.
813        """
814        if body is None:
815            # do an explicit check for not None here to distinguish
816            # between unset and set but empty
817            if method.upper() in _METHODS_EXPECTING_BODY:
818                return 0
819            else:
820                return None
821
822        if hasattr(body, 'read'):
823            # file-like object.
824            return None
825
826        try:
827            # does it implement the buffer protocol (bytes, bytearray, array)?
828            mv = memoryview(body)
829            return mv.nbytes
830        except TypeError:
831            pass
832
833        if isinstance(body, str):
834            return len(body)
835
836        return None
837
838    def __init__(self, host, port=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
839                 source_address=None, blocksize=8192):
840        self.timeout = timeout
841        self.source_address = source_address
842        self.blocksize = blocksize
843        self.sock = None
844        self._buffer = []
845        self.__response = None
846        self.__state = _CS_IDLE
847        self._method = None
848        self._tunnel_host = None
849        self._tunnel_port = None
850        self._tunnel_headers = {}
851
852        (self.host, self.port) = self._get_hostport(host, port)
853
854        self._validate_host(self.host)
855
856        # This is stored as an instance variable to allow unit
857        # tests to replace it with a suitable mockup
858        self._create_connection = socket.create_connection
859
860    def set_tunnel(self, host, port=None, headers=None):
861        """Set up host and port for HTTP CONNECT tunnelling.
862
863        In a connection that uses HTTP CONNECT tunneling, the host passed to the
864        constructor is used as a proxy server that relays all communication to
865        the endpoint passed to `set_tunnel`. This done by sending an HTTP
866        CONNECT request to the proxy server when the connection is established.
867
868        This method must be called before the HTTP connection has been
869        established.
870
871        The headers argument should be a mapping of extra HTTP headers to send
872        with the CONNECT request.
873        """
874
875        if self.sock:
876            raise RuntimeError("Can't set up tunnel for established connection")
877
878        self._tunnel_host, self._tunnel_port = self._get_hostport(host, port)
879        if headers:
880            self._tunnel_headers = headers
881        else:
882            self._tunnel_headers.clear()
883
884    def _get_hostport(self, host, port):
885        if port is None:
886            i = host.rfind(':')
887            j = host.rfind(']')         # ipv6 addresses have [...]
888            if i > j:
889                try:
890                    port = int(host[i+1:])
891                except ValueError:
892                    if host[i+1:] == "": # http://foo.com:/ == http://foo.com/
893                        port = self.default_port
894                    else:
895                        raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
896                host = host[:i]
897            else:
898                port = self.default_port
899            if host and host[0] == '[' and host[-1] == ']':
900                host = host[1:-1]
901
902        return (host, port)
903
904    def set_debuglevel(self, level):
905        self.debuglevel = level
906
907    def _tunnel(self):
908        connect = b"CONNECT %s:%d HTTP/1.0\r\n" % (
909            self._tunnel_host.encode("ascii"), self._tunnel_port)
910        headers = [connect]
911        for header, value in self._tunnel_headers.items():
912            headers.append(f"{header}: {value}\r\n".encode("latin-1"))
913        headers.append(b"\r\n")
914        # Making a single send() call instead of one per line encourages
915        # the host OS to use a more optimal packet size instead of
916        # potentially emitting a series of small packets.
917        self.send(b"".join(headers))
918        del headers
919
920        response = self.response_class(self.sock, method=self._method)
921        try:
922            (version, code, message) = response._read_status()
923
924            if code != http.HTTPStatus.OK:
925                self.close()
926                raise OSError(f"Tunnel connection failed: {code} {message.strip()}")
927            while True:
928                line = response.fp.readline(_MAXLINE + 1)
929                if len(line) > _MAXLINE:
930                    raise LineTooLong("header line")
931                if not line:
932                    # for sites which EOF without sending a trailer
933                    break
934                if line in (b'\r\n', b'\n', b''):
935                    break
936
937                if self.debuglevel > 0:
938                    print('header:', line.decode())
939        finally:
940            response.close()
941
942    def connect(self):
943        """Connect to the host and port specified in __init__."""
944        sys.audit("http.client.connect", self, self.host, self.port)
945        self.sock = self._create_connection(
946            (self.host,self.port), self.timeout, self.source_address)
947        # Might fail in OSs that don't implement TCP_NODELAY
948        try:
949            self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
950        except OSError as e:
951            if e.errno != errno.ENOPROTOOPT:
952                raise
953
954        if self._tunnel_host:
955            self._tunnel()
956
957    def close(self):
958        """Close the connection to the HTTP server."""
959        self.__state = _CS_IDLE
960        try:
961            sock = self.sock
962            if sock:
963                self.sock = None
964                sock.close()   # close it manually... there may be other refs
965        finally:
966            response = self.__response
967            if response:
968                self.__response = None
969                response.close()
970
971    def send(self, data):
972        """Send `data' to the server.
973        ``data`` can be a string object, a bytes object, an array object, a
974        file-like object that supports a .read() method, or an iterable object.
975        """
976
977        if self.sock is None:
978            if self.auto_open:
979                self.connect()
980            else:
981                raise NotConnected()
982
983        if self.debuglevel > 0:
984            print("send:", repr(data))
985        if hasattr(data, "read") :
986            if self.debuglevel > 0:
987                print("sending a readable")
988            encode = self._is_textIO(data)
989            if encode and self.debuglevel > 0:
990                print("encoding file using iso-8859-1")
991            while 1:
992                datablock = data.read(self.blocksize)
993                if not datablock:
994                    break
995                if encode:
996                    datablock = datablock.encode("iso-8859-1")
997                sys.audit("http.client.send", self, datablock)
998                self.sock.sendall(datablock)
999            return
1000        sys.audit("http.client.send", self, data)
1001        try:
1002            self.sock.sendall(data)
1003        except TypeError:
1004            if isinstance(data, collections.abc.Iterable):
1005                for d in data:
1006                    self.sock.sendall(d)
1007            else:
1008                raise TypeError("data should be a bytes-like object "
1009                                "or an iterable, got %r" % type(data))
1010
1011    def _output(self, s):
1012        """Add a line of output to the current request buffer.
1013
1014        Assumes that the line does *not* end with \\r\\n.
1015        """
1016        self._buffer.append(s)
1017
1018    def _read_readable(self, readable):
1019        if self.debuglevel > 0:
1020            print("reading a readable")
1021        encode = self._is_textIO(readable)
1022        if encode and self.debuglevel > 0:
1023            print("encoding file using iso-8859-1")
1024        while True:
1025            datablock = readable.read(self.blocksize)
1026            if not datablock:
1027                break
1028            if encode:
1029                datablock = datablock.encode("iso-8859-1")
1030            yield datablock
1031
1032    def _send_output(self, message_body=None, encode_chunked=False):
1033        """Send the currently buffered request and clear the buffer.
1034
1035        Appends an extra \\r\\n to the buffer.
1036        A message_body may be specified, to be appended to the request.
1037        """
1038        self._buffer.extend((b"", b""))
1039        msg = b"\r\n".join(self._buffer)
1040        del self._buffer[:]
1041        self.send(msg)
1042
1043        if message_body is not None:
1044
1045            # create a consistent interface to message_body
1046            if hasattr(message_body, 'read'):
1047                # Let file-like take precedence over byte-like.  This
1048                # is needed to allow the current position of mmap'ed
1049                # files to be taken into account.
1050                chunks = self._read_readable(message_body)
1051            else:
1052                try:
1053                    # this is solely to check to see if message_body
1054                    # implements the buffer API.  it /would/ be easier
1055                    # to capture if PyObject_CheckBuffer was exposed
1056                    # to Python.
1057                    memoryview(message_body)
1058                except TypeError:
1059                    try:
1060                        chunks = iter(message_body)
1061                    except TypeError:
1062                        raise TypeError("message_body should be a bytes-like "
1063                                        "object or an iterable, got %r"
1064                                        % type(message_body))
1065                else:
1066                    # the object implements the buffer interface and
1067                    # can be passed directly into socket methods
1068                    chunks = (message_body,)
1069
1070            for chunk in chunks:
1071                if not chunk:
1072                    if self.debuglevel > 0:
1073                        print('Zero length chunk ignored')
1074                    continue
1075
1076                if encode_chunked and self._http_vsn == 11:
1077                    # chunked encoding
1078                    chunk = f'{len(chunk):X}\r\n'.encode('ascii') + chunk \
1079                        + b'\r\n'
1080                self.send(chunk)
1081
1082            if encode_chunked and self._http_vsn == 11:
1083                # end chunked transfer
1084                self.send(b'0\r\n\r\n')
1085
1086    def putrequest(self, method, url, skip_host=False,
1087                   skip_accept_encoding=False):
1088        """Send a request to the server.
1089
1090        `method' specifies an HTTP request method, e.g. 'GET'.
1091        `url' specifies the object being requested, e.g. '/index.html'.
1092        `skip_host' if True does not add automatically a 'Host:' header
1093        `skip_accept_encoding' if True does not add automatically an
1094           'Accept-Encoding:' header
1095        """
1096
1097        # if a prior response has been completed, then forget about it.
1098        if self.__response and self.__response.isclosed():
1099            self.__response = None
1100
1101
1102        # in certain cases, we cannot issue another request on this connection.
1103        # this occurs when:
1104        #   1) we are in the process of sending a request.   (_CS_REQ_STARTED)
1105        #   2) a response to a previous request has signalled that it is going
1106        #      to close the connection upon completion.
1107        #   3) the headers for the previous response have not been read, thus
1108        #      we cannot determine whether point (2) is true.   (_CS_REQ_SENT)
1109        #
1110        # if there is no prior response, then we can request at will.
1111        #
1112        # if point (2) is true, then we will have passed the socket to the
1113        # response (effectively meaning, "there is no prior response"), and
1114        # will open a new one when a new request is made.
1115        #
1116        # Note: if a prior response exists, then we *can* start a new request.
1117        #       We are not allowed to begin fetching the response to this new
1118        #       request, however, until that prior response is complete.
1119        #
1120        if self.__state == _CS_IDLE:
1121            self.__state = _CS_REQ_STARTED
1122        else:
1123            raise CannotSendRequest(self.__state)
1124
1125        self._validate_method(method)
1126
1127        # Save the method for use later in the response phase
1128        self._method = method
1129
1130        url = url or '/'
1131        self._validate_path(url)
1132
1133        request = '%s %s %s' % (method, url, self._http_vsn_str)
1134
1135        self._output(self._encode_request(request))
1136
1137        if self._http_vsn == 11:
1138            # Issue some standard headers for better HTTP/1.1 compliance
1139
1140            if not skip_host:
1141                # this header is issued *only* for HTTP/1.1
1142                # connections. more specifically, this means it is
1143                # only issued when the client uses the new
1144                # HTTPConnection() class. backwards-compat clients
1145                # will be using HTTP/1.0 and those clients may be
1146                # issuing this header themselves. we should NOT issue
1147                # it twice; some web servers (such as Apache) barf
1148                # when they see two Host: headers
1149
1150                # If we need a non-standard port,include it in the
1151                # header.  If the request is going through a proxy,
1152                # but the host of the actual URL, not the host of the
1153                # proxy.
1154
1155                netloc = ''
1156                if url.startswith('http'):
1157                    nil, netloc, nil, nil, nil = urlsplit(url)
1158
1159                if netloc:
1160                    try:
1161                        netloc_enc = netloc.encode("ascii")
1162                    except UnicodeEncodeError:
1163                        netloc_enc = netloc.encode("idna")
1164                    self.putheader('Host', netloc_enc)
1165                else:
1166                    if self._tunnel_host:
1167                        host = self._tunnel_host
1168                        port = self._tunnel_port
1169                    else:
1170                        host = self.host
1171                        port = self.port
1172
1173                    try:
1174                        host_enc = host.encode("ascii")
1175                    except UnicodeEncodeError:
1176                        host_enc = host.encode("idna")
1177
1178                    # As per RFC 273, IPv6 address should be wrapped with []
1179                    # when used as Host header
1180
1181                    if host.find(':') >= 0:
1182                        host_enc = b'[' + host_enc + b']'
1183
1184                    if port == self.default_port:
1185                        self.putheader('Host', host_enc)
1186                    else:
1187                        host_enc = host_enc.decode("ascii")
1188                        self.putheader('Host', "%s:%s" % (host_enc, port))
1189
1190            # note: we are assuming that clients will not attempt to set these
1191            #       headers since *this* library must deal with the
1192            #       consequences. this also means that when the supporting
1193            #       libraries are updated to recognize other forms, then this
1194            #       code should be changed (removed or updated).
1195
1196            # we only want a Content-Encoding of "identity" since we don't
1197            # support encodings such as x-gzip or x-deflate.
1198            if not skip_accept_encoding:
1199                self.putheader('Accept-Encoding', 'identity')
1200
1201            # we can accept "chunked" Transfer-Encodings, but no others
1202            # NOTE: no TE header implies *only* "chunked"
1203            #self.putheader('TE', 'chunked')
1204
1205            # if TE is supplied in the header, then it must appear in a
1206            # Connection header.
1207            #self.putheader('Connection', 'TE')
1208
1209        else:
1210            # For HTTP/1.0, the server will assume "not chunked"
1211            pass
1212
1213    def _encode_request(self, request):
1214        # ASCII also helps prevent CVE-2019-9740.
1215        return request.encode('ascii')
1216
1217    def _validate_method(self, method):
1218        """Validate a method name for putrequest."""
1219        # prevent http header injection
1220        match = _contains_disallowed_method_pchar_re.search(method)
1221        if match:
1222            raise ValueError(
1223                    f"method can't contain control characters. {method!r} "
1224                    f"(found at least {match.group()!r})")
1225
1226    def _validate_path(self, url):
1227        """Validate a url for putrequest."""
1228        # Prevent CVE-2019-9740.
1229        match = _contains_disallowed_url_pchar_re.search(url)
1230        if match:
1231            raise InvalidURL(f"URL can't contain control characters. {url!r} "
1232                             f"(found at least {match.group()!r})")
1233
1234    def _validate_host(self, host):
1235        """Validate a host so it doesn't contain control characters."""
1236        # Prevent CVE-2019-18348.
1237        match = _contains_disallowed_url_pchar_re.search(host)
1238        if match:
1239            raise InvalidURL(f"URL can't contain control characters. {host!r} "
1240                             f"(found at least {match.group()!r})")
1241
1242    def putheader(self, header, *values):
1243        """Send a request header line to the server.
1244
1245        For example: h.putheader('Accept', 'text/html')
1246        """
1247        if self.__state != _CS_REQ_STARTED:
1248            raise CannotSendHeader()
1249
1250        if hasattr(header, 'encode'):
1251            header = header.encode('ascii')
1252
1253        if not _is_legal_header_name(header):
1254            raise ValueError('Invalid header name %r' % (header,))
1255
1256        values = list(values)
1257        for i, one_value in enumerate(values):
1258            if hasattr(one_value, 'encode'):
1259                values[i] = one_value.encode('latin-1')
1260            elif isinstance(one_value, int):
1261                values[i] = str(one_value).encode('ascii')
1262
1263            if _is_illegal_header_value(values[i]):
1264                raise ValueError('Invalid header value %r' % (values[i],))
1265
1266        value = b'\r\n\t'.join(values)
1267        header = header + b': ' + value
1268        self._output(header)
1269
1270    def endheaders(self, message_body=None, *, encode_chunked=False):
1271        """Indicate that the last header line has been sent to the server.
1272
1273        This method sends the request to the server.  The optional message_body
1274        argument can be used to pass a message body associated with the
1275        request.
1276        """
1277        if self.__state == _CS_REQ_STARTED:
1278            self.__state = _CS_REQ_SENT
1279        else:
1280            raise CannotSendHeader()
1281        self._send_output(message_body, encode_chunked=encode_chunked)
1282
1283    def request(self, method, url, body=None, headers={}, *,
1284                encode_chunked=False):
1285        """Send a complete request to the server."""
1286        self._send_request(method, url, body, headers, encode_chunked)
1287
1288    def _send_request(self, method, url, body, headers, encode_chunked):
1289        # Honor explicitly requested Host: and Accept-Encoding: headers.
1290        header_names = frozenset(k.lower() for k in headers)
1291        skips = {}
1292        if 'host' in header_names:
1293            skips['skip_host'] = 1
1294        if 'accept-encoding' in header_names:
1295            skips['skip_accept_encoding'] = 1
1296
1297        self.putrequest(method, url, **skips)
1298
1299        # chunked encoding will happen if HTTP/1.1 is used and either
1300        # the caller passes encode_chunked=True or the following
1301        # conditions hold:
1302        # 1. content-length has not been explicitly set
1303        # 2. the body is a file or iterable, but not a str or bytes-like
1304        # 3. Transfer-Encoding has NOT been explicitly set by the caller
1305
1306        if 'content-length' not in header_names:
1307            # only chunk body if not explicitly set for backwards
1308            # compatibility, assuming the client code is already handling the
1309            # chunking
1310            if 'transfer-encoding' not in header_names:
1311                # if content-length cannot be automatically determined, fall
1312                # back to chunked encoding
1313                encode_chunked = False
1314                content_length = self._get_content_length(body, method)
1315                if content_length is None:
1316                    if body is not None:
1317                        if self.debuglevel > 0:
1318                            print('Unable to determine size of %r' % body)
1319                        encode_chunked = True
1320                        self.putheader('Transfer-Encoding', 'chunked')
1321                else:
1322                    self.putheader('Content-Length', str(content_length))
1323        else:
1324            encode_chunked = False
1325
1326        for hdr, value in headers.items():
1327            self.putheader(hdr, value)
1328        if isinstance(body, str):
1329            # RFC 2616 Section 3.7.1 says that text default has a
1330            # default charset of iso-8859-1.
1331            body = _encode(body, 'body')
1332        self.endheaders(body, encode_chunked=encode_chunked)
1333
1334    def getresponse(self):
1335        """Get the response from the server.
1336
1337        If the HTTPConnection is in the correct state, returns an
1338        instance of HTTPResponse or of whatever object is returned by
1339        the response_class variable.
1340
1341        If a request has not been sent or if a previous response has
1342        not be handled, ResponseNotReady is raised.  If the HTTP
1343        response indicates that the connection should be closed, then
1344        it will be closed before the response is returned.  When the
1345        connection is closed, the underlying socket is closed.
1346        """
1347
1348        # if a prior response has been completed, then forget about it.
1349        if self.__response and self.__response.isclosed():
1350            self.__response = None
1351
1352        # if a prior response exists, then it must be completed (otherwise, we
1353        # cannot read this response's header to determine the connection-close
1354        # behavior)
1355        #
1356        # note: if a prior response existed, but was connection-close, then the
1357        # socket and response were made independent of this HTTPConnection
1358        # object since a new request requires that we open a whole new
1359        # connection
1360        #
1361        # this means the prior response had one of two states:
1362        #   1) will_close: this connection was reset and the prior socket and
1363        #                  response operate independently
1364        #   2) persistent: the response was retained and we await its
1365        #                  isclosed() status to become true.
1366        #
1367        if self.__state != _CS_REQ_SENT or self.__response:
1368            raise ResponseNotReady(self.__state)
1369
1370        if self.debuglevel > 0:
1371            response = self.response_class(self.sock, self.debuglevel,
1372                                           method=self._method)
1373        else:
1374            response = self.response_class(self.sock, method=self._method)
1375
1376        try:
1377            try:
1378                response.begin()
1379            except ConnectionError:
1380                self.close()
1381                raise
1382            assert response.will_close != _UNKNOWN
1383            self.__state = _CS_IDLE
1384
1385            if response.will_close:
1386                # this effectively passes the connection to the response
1387                self.close()
1388            else:
1389                # remember this, so we can tell when it is complete
1390                self.__response = response
1391
1392            return response
1393        except:
1394            response.close()
1395            raise
1396
1397try:
1398    import ssl
1399except ImportError:
1400    pass
1401else:
1402    class HTTPSConnection(HTTPConnection):
1403        "This class allows communication via SSL."
1404
1405        default_port = HTTPS_PORT
1406
1407        # XXX Should key_file and cert_file be deprecated in favour of context?
1408
1409        def __init__(self, host, port=None, key_file=None, cert_file=None,
1410                     timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
1411                     source_address=None, *, context=None,
1412                     check_hostname=None, blocksize=8192):
1413            super(HTTPSConnection, self).__init__(host, port, timeout,
1414                                                  source_address,
1415                                                  blocksize=blocksize)
1416            if (key_file is not None or cert_file is not None or
1417                        check_hostname is not None):
1418                import warnings
1419                warnings.warn("key_file, cert_file and check_hostname are "
1420                              "deprecated, use a custom context instead.",
1421                              DeprecationWarning, 2)
1422            self.key_file = key_file
1423            self.cert_file = cert_file
1424            if context is None:
1425                context = ssl._create_default_https_context()
1426                # send ALPN extension to indicate HTTP/1.1 protocol
1427                if self._http_vsn == 11:
1428                    context.set_alpn_protocols(['http/1.1'])
1429                # enable PHA for TLS 1.3 connections if available
1430                if context.post_handshake_auth is not None:
1431                    context.post_handshake_auth = True
1432            will_verify = context.verify_mode != ssl.CERT_NONE
1433            if check_hostname is None:
1434                check_hostname = context.check_hostname
1435            if check_hostname and not will_verify:
1436                raise ValueError("check_hostname needs a SSL context with "
1437                                 "either CERT_OPTIONAL or CERT_REQUIRED")
1438            if key_file or cert_file:
1439                context.load_cert_chain(cert_file, key_file)
1440                # cert and key file means the user wants to authenticate.
1441                # enable TLS 1.3 PHA implicitly even for custom contexts.
1442                if context.post_handshake_auth is not None:
1443                    context.post_handshake_auth = True
1444            self._context = context
1445            if check_hostname is not None:
1446                self._context.check_hostname = check_hostname
1447
1448        def connect(self):
1449            "Connect to a host on a given (SSL) port."
1450
1451            super().connect()
1452
1453            if self._tunnel_host:
1454                server_hostname = self._tunnel_host
1455            else:
1456                server_hostname = self.host
1457
1458            self.sock = self._context.wrap_socket(self.sock,
1459                                                  server_hostname=server_hostname)
1460
1461    __all__.append("HTTPSConnection")
1462
1463class HTTPException(Exception):
1464    # Subclasses that define an __init__ must call Exception.__init__
1465    # or define self.args.  Otherwise, str() will fail.
1466    pass
1467
1468class NotConnected(HTTPException):
1469    pass
1470
1471class InvalidURL(HTTPException):
1472    pass
1473
1474class UnknownProtocol(HTTPException):
1475    def __init__(self, version):
1476        self.args = version,
1477        self.version = version
1478
1479class UnknownTransferEncoding(HTTPException):
1480    pass
1481
1482class UnimplementedFileMode(HTTPException):
1483    pass
1484
1485class IncompleteRead(HTTPException):
1486    def __init__(self, partial, expected=None):
1487        self.args = partial,
1488        self.partial = partial
1489        self.expected = expected
1490    def __repr__(self):
1491        if self.expected is not None:
1492            e = ', %i more expected' % self.expected
1493        else:
1494            e = ''
1495        return '%s(%i bytes read%s)' % (self.__class__.__name__,
1496                                        len(self.partial), e)
1497    __str__ = object.__str__
1498
1499class ImproperConnectionState(HTTPException):
1500    pass
1501
1502class CannotSendRequest(ImproperConnectionState):
1503    pass
1504
1505class CannotSendHeader(ImproperConnectionState):
1506    pass
1507
1508class ResponseNotReady(ImproperConnectionState):
1509    pass
1510
1511class BadStatusLine(HTTPException):
1512    def __init__(self, line):
1513        if not line:
1514            line = repr(line)
1515        self.args = line,
1516        self.line = line
1517
1518class LineTooLong(HTTPException):
1519    def __init__(self, line_type):
1520        HTTPException.__init__(self, "got more than %d bytes when reading %s"
1521                                     % (_MAXLINE, line_type))
1522
1523class RemoteDisconnected(ConnectionResetError, BadStatusLine):
1524    def __init__(self, *pos, **kw):
1525        BadStatusLine.__init__(self, "")
1526        ConnectionResetError.__init__(self, *pos, **kw)
1527
1528# for backwards compatibility
1529error = HTTPException
1530