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