"http.client" --- HTTP 프로토콜 클라이언트
******************************************

**소스 코드:** Lib/http/client.py

======================================================================

This module defines classes that implement the client side of the HTTP
and HTTPS protocols.  It is normally not used directly --- the module
"urllib.request" uses it to handle URLs that use HTTP and HTTPS.

더 보기: 더 고수준 HTTP 클라이언트 인터페이스로 Requests 패키지를 권장합니다.

참고:

  HTTPS 지원은 파이썬이 SSL 지원으로 컴파일된 경우에만 사용 가능합니다
  ("ssl" 모듈을 통해).

이 모듈은 다음과 같은 클래스를 제공합니다:

class http.client.HTTPConnection(host, port=None[, timeout], source_address=None, blocksize=8192)

   An "HTTPConnection" instance represents one transaction with an
   HTTP server.  It should be instantiated by passing it a host and
   optional port number.  If no port number is passed, the port is
   extracted from the host string if it has the form "host:port", else
   the default HTTP port (80) is used.  If the optional *timeout*
   parameter is given, blocking operations (like connection attempts)
   will timeout after that many seconds (if it is not given, the
   global default timeout setting is used). The optional
   *source_address* parameter may be a tuple of a (host, port) to use
   as the source address the HTTP connection is made from. The
   optional *blocksize* parameter sets the buffer size in bytes for
   sending a file-like message body.

   예를 들어, 다음 호출은 모두 같은 호스트와 포트에 있는 서버에 연결하
   는 인스턴스를 만듭니다:

      >>> h1 = http.client.HTTPConnection('www.python.org')
      >>> h2 = http.client.HTTPConnection('www.python.org:80')
      >>> h3 = http.client.HTTPConnection('www.python.org', 80)
      >>> h4 = http.client.HTTPConnection('www.python.org', 80, timeout=10)

   버전 3.2에서 변경: *source_address*가 추가되었습니다.

   버전 3.4에서 변경: The  *strict* parameter was removed. HTTP
   0.9-style "Simple Responses" are no longer supported.

   버전 3.7에서 변경: *blocksize* 매개 변수가 추가되었습니다.

class http.client.HTTPSConnection(host, port=None, key_file=None, cert_file=None[, timeout], source_address=None, *, context=None, check_hostname=None, blocksize=8192)

   보안 서버와의 통신에 SSL을 사용하는 "HTTPConnection"의 서브 클래스.
   기본 포트는 "443"입니다. *context*가 지정되면, 다양한 SSL 옵션을 기
   술하는 "ssl.SSLContext" 인스턴스여야 합니다.

   모범 사례에 대한 자세한 내용은 보안 고려 사항을 참조하십시오.

   버전 3.2에서 변경: *source_address*, *context* 및 *check_hostname*
   이 추가되었습니다.

   버전 3.2에서 변경: 이 클래스는 이제 가능하면 (즉, "ssl.HAS_SNI"가
   참이면) HTTPS 가상 호스트를 지원합니다.

   버전 3.4에서 변경: *strict* 매개 변수가 제거되었습니다. HTTP 0.9 스
   타일 "간단한 응답"은 더는 지원되지 않습니다.

   버전 3.4.3에서 변경: 이 클래스는 이제 기본적으로 필요한 모든 인증서
   와 호스트 이름 검사를 수행합니다. 이전의 검사하지 않는 동작으로 되
   돌리려면 "ssl._create_unverified_context()"를 *context* 매개 변수로
   전달할 수 있습니다.

   버전 3.8에서 변경: 이 클래스는 이제 기본 *context*나 *cert_file*이
   사용자 정의 *context*와 함께 전달될 때 TLS 1.3
   "ssl.SSLContext.post_handshake_auth"를 활성화합니다.

   버전 3.10에서 변경: This class now sends an ALPN extension with
   protocol indicator "http/1.1" when no *context* is given. Custom
   *context* should set ALPN protocols with "set_alpn_protocol()".

   버전 3.6부터 폐지: *key_file*과 *cert_file*은 폐지되어 *context*로
   대체되었습니다. 대신 "ssl.SSLContext.load_cert_chain()"을 사용하거
   나, "ssl.create_default_context()"가 시스템의 신뢰할 수 있는 CA 인
   증서를 선택하도록 하십시오.*check_hostname* 매개 변수도 폐지되었습
   니다; 대신 *context*의 "ssl.SSLContext.check_hostname" 어트리뷰트를
   사용해야 합니다.

class http.client.HTTPResponse(sock, debuglevel=0, method=None, url=None)

   성공적으로 연결되면 반환되는 인스턴스의 클래스. 사용자가 직접 인스
   턴스화 하지 않습니다.

   버전 3.4에서 변경: *strict* 매개 변수가 제거되었습니다. HTTP 0.9 스
   타일 "간단한 응답"은 더는 지원되지 않습니다.

이 모듈은 다음 함수를 제공합니다:

http.client.parse_headers(fp)

   HTTP 요청/응답을 나타내는 파일 포인터 *fp*에서 헤더를 구문 분석합니
   다. 파일은 "BufferedIOBase" 판독기(reader)여야 하며 (즉 텍스트가 아
   닙니다) 유효한 **RFC 2822** 스타일 헤더를 제공해야 합니다.

   이 함수는 헤더 필드를 담은 "http.client.HTTPMessage" 인스턴스를 반
   환하지만, 페이 로드는 반환하지 않습니다 ("HTTPResponse.msg"와
   "http.server.BaseHTTPRequestHandler.headers"와 같습니다). 반환 후,
   파일 포인터 *fp*는 HTTP 바디를 읽을 준비가 되었습니다.

   참고:

     "parse_headers()"는 HTTP 메시지의 시작 줄을 구문 분석하지 않습니
     다; "Name: value" 줄만 구문 분석합니다. 파일은 이러한 필드 줄을
     읽을 준비가 되어 있어야 해서, 함수를 호출하기 전에 첫 번째 줄이
     이미 소비되었어야 합니다.

다음과 같은 예외가 적절하게 발생합니다:

exception http.client.HTTPException

   이 모듈에 있는 다른 예외의 베이스 클래스입니다. "Exception"의 서브
   클래스입니다.

exception http.client.NotConnected

   "HTTPException"의 서브 클래스.

exception http.client.InvalidURL

   포트가 제공되고 숫자가 아니거나 비어있을 때 발생하는
   "HTTPException"의 서브 클래스.

exception http.client.UnknownProtocol

   "HTTPException"의 서브 클래스.

exception http.client.UnknownTransferEncoding

   "HTTPException"의 서브 클래스.

exception http.client.UnimplementedFileMode

   "HTTPException"의 서브 클래스.

exception http.client.IncompleteRead

   "HTTPException"의 서브 클래스.

exception http.client.ImproperConnectionState

   "HTTPException"의 서브 클래스.

exception http.client.CannotSendRequest

   "ImproperConnectionState"의 서브 클래스.

exception http.client.CannotSendHeader

   "ImproperConnectionState"의 서브 클래스.

exception http.client.ResponseNotReady

   "ImproperConnectionState"의 서브 클래스.

exception http.client.BadStatusLine

   "HTTPException"의 서브 클래스. 이해하지 못하는 HTTP 상태 코드로 서
   버가 응답하면 발생합니다.

exception http.client.LineTooLong

   "HTTPException"의 서브 클래스. 서버에서 HTTP 프로토콜로 너무 긴 줄
   이 수신되면 발생합니다.

exception http.client.RemoteDisconnected

   "ConnectionResetError"와 "BadStatusLine"의 서브 클래스.
   "HTTPConnection.getresponse()"가 응답을 읽으려고 시도할 때 연결에서
   아무런 데이터를 읽지 못하여, 원격 끝이 연결을 닫았음을 표시하면 발
   생합니다.

   버전 3.5에 추가: 이전에는, "BadStatusLine""('')"가 발생했습니다.

이 모듈에 정의된 상수는 다음과 같습니다:

http.client.HTTP_PORT

   HTTP 프로토콜의 기본 포트 (항상 "80").

http.client.HTTPS_PORT

   HTTPS 프로토콜의 기본 포트 (항상 "443").

http.client.responses

   이 딕셔너리는 HTTP 1.1 상태 코드를 W3C 이름으로 매핑합니다.

   예: "http.client.responses[http.client.NOT_FOUND]"는 "'Not Found'"
   입니다.

이 모듈에서 상수로 사용 가능한 HTTP 상태 코드 목록은 HTTP 상태 코드를
참조하십시오.


HTTPConnection 객체
===================

"HTTPConnection" 인스턴스에는 다음과 같은 메서드가 있습니다:

HTTPConnection.request(method, url, body=None, headers={}, *, encode_chunked=False)

   HTTP 요청 메서드 *method*와 선택기(selector) *url*을 사용하여 서버
   로 요청을 보냅니다.

   *body*가 지정되면, 헤더가 완료된 후 지정된 데이터가 전송됩니다.
   "str", *바이트열류 객체*, 열린 *파일 객체* 또는 "bytes"의 이터러블
   일 수 있습니다. *body*가 문자열이면, HTTP의 기본값인 ISO-8859-1로
   인코딩됩니다. 바이트열류 객체이면, 바이트열은 그대로 전송됩니다. *
   파일 객체*이면, 파일의 내용이 전송됩니다; 이 파일 객체는 최소한
   "read()" 메서드를 지원해야 합니다. 파일 객체가 "io.TextIOBase"의 인
   스턴스이면, "read()" 메서드에서 반환된 데이터는 ISO-8859-1로 인코딩
   되고, 그렇지 않으면 "read()"에서 반환된 데이터가 그대로 전송됩니다.
   *body*가 이터러블이면, 이터러블이 소진될 때까지 이터러블의 요소가
   그대로 전송됩니다.

   *headers* 인자는 요청과 함께 보낼 추가 HTTP 헤더의 매핑이어야 합니
   다.

   *headers*에 Content-Length도 Transfer-Encoding도 없지만, 요청 바디
   가 있으면, 이 헤더 필드 중 하나가 자동으로 추가됩니다. *body*가
   "None"이면, 바디를 기대하는 메서드("PUT", "POST" 및 "PATCH")의 경우
   Content-Length 헤더가 "0"으로 설정됩니다. *body*가 문자열이거나 *파
   일*이 아닌 바이트열류 객체이면, Content-Length 헤더가 그것의 길이로
   설정됩니다. 다른 모든 형의 *body*(파일과 이터러블 일반)는 청크 인코
   딩되며 Content-Length 대신 Transfer-Encoding 헤더가 자동으로 설정됩
   니다.

   *encode_chunked* 인자는 Transfer-Encoding이 *headers*에 지정된 경우
   에만 유효합니다. *encode_chunked*가 "False"이면, HTTPConnection 객
   체는 모든 인코딩이 호출하는 코드에서 처리된다고 가정합니다. "True"
   이면, 바디가 청크 인코딩됩니다.

   참고:

     청크 전송 인코딩은 HTTP 프로토콜 버전 1.1에 추가되었습니다. HTTP
     서버가 HTTP 1.1을 처리하는 것으로 알려지지 않은 한, 호출자는
     Content-Length를 지정하거나, 바디 표현으로 "str"이나 파일이 아닌
     바이트열류 객체를 전달해야 합니다.

   버전 3.2에 추가: *body*는 이제 이터러블일 수 있습니다.

   버전 3.6에서 변경: Content-Length도 Transfer-Encoding도 *headers*에
   설정되지 않으면, 파일과 이터러블 *body* 객체는 이제 청크 인코딩됩니
   다. *encode_chunked* 인자가 추가되었습니다. 파일 객체의 Content-
   Length를 결정하려는 시도는 없습니다.

HTTPConnection.getresponse()

   요청을 보낸 후에 서버에서 응답을 받기 위해 호출해야 합니다.
   "HTTPResponse" 인스턴스를 반환합니다.

   참고:

     서버에 새 요청을 보내기 전에 전체 응답을 읽어야 함에 유의하십시오
     .

   버전 3.5에서 변경: "ConnectionError"나 서브 클래스가 발생하면, 새
   요청이 전송될 때 "HTTPConnection" 객체는 다시 연결할 준비가 됩니다.

HTTPConnection.set_debuglevel(level)

   디버깅 수준을 설정합니다. 기본 디버그 수준은 "0"이며, 디버깅 출력이
   인쇄되지 않음을 의미합니다. "0"보다 큰 값을 지정하면 현재 정의된 모
   든 디버그 출력이 표준 출력으로 인쇄됩니다. "debuglevel"은 만들어지
   는 모든 새로운 "HTTPResponse" 객체로 전달됩니다.

   버전 3.1에 추가.

HTTPConnection.set_tunnel(host, port=None, headers=None)

   HTTP Connect 터널링(tunnelling)을 위한 host와 및 port를 설정합니다.
   프락시 서버를 통해 연결을 실행할 수 있도록 합니다.

   host와 port 인자는 터널링 된 연결의 말단(즉 CONNECT 요청에 포함되는
   주소, 프락시 서버의 주소가 *아닙니다*)을 지정합니다.

   headers 인자는 CONNECT 요청과 함께 보낼 추가 HTTP 헤더의 매핑이어야
   합니다.

   예를 들어, 포트 8080에서 로컬로 실행되는 HTTPS 프락시 서버를 통해
   터널링 하려면, 프락시 주소를 "HTTPSConnection" 생성자에 전달하고,
   최종적으로 "set_tunnel()" 메서드에 도달하려는 호스트 주소를 전달합
   니다:

      >>> import http.client
      >>> conn = http.client.HTTPSConnection("localhost", 8080)
      >>> conn.set_tunnel("www.python.org")
      >>> conn.request("HEAD","/index.html")

   버전 3.2에 추가.

HTTPConnection.connect()

   객체가 만들어질 때 지정된 서버에 연결합니다. 기본적으로, 클라이언트
   가 이미 연결되지 않았다면 요청 시 자동으로 호출됩니다.

   Raises an auditing event "http.client.connect" with arguments
   "self", "host", "port".

HTTPConnection.close()

   서버로의 연결을 닫습니다.

HTTPConnection.blocksize

   파일류 메시지 바디를 보내기 위한 바이트 단위의 버퍼 크기.

   버전 3.7에 추가.

위에서 설명한 "request()" 메서드를 사용하는 대신, 아래 네 가지 함수를
사용하여 단계별로 요청을 보낼 수도 있습니다.

HTTPConnection.putrequest(method, url, skip_host=False, skip_accept_encoding=False)

   서버에 연결한 후 첫 번째 호출이어야 합니다. *method* 문자열, *url*
   문자열 및 HTTP 버전("HTTP/1.1")으로 구성된 줄을 서버로 보냅니다.
   "Host:"나 "Accept-Encoding:" 헤더의 자동 전송을 비활성화하려면 (예
   를 들어 추가 콘텐츠 인코딩을 허용하려면), False가 아닌 값으로
   *skip_host*나 *skip_accept_encoding*을 지정하십시오.

HTTPConnection.putheader(header, argument[, ...])

   **RFC 822** 스타일 헤더를 서버에 보냅니다. header, 콜론과 공백 및
   첫 번째 인자로 구성된 줄을 서버로 보냅니다. 더 많은 인자가 제공되면
   , 탭과 인자로 구성된 연속 줄(continuation lines)이 전송됩니다.

HTTPConnection.endheaders(message_body=None, *, encode_chunked=False)

   헤더의 끝을 알리는 빈 줄을 서버에 보냅니다. 선택적 *message_body*
   인자를 사용하여 요청과 연관된 메시지 바디를 전달할 수 있습니다.

   *encode_chunked*가 "True"이면, *message_body*의 각 이터레이션 결과
   는 **RFC 7230**, 섹션 3.3.1에 지정된 대로 청크 인코딩됩니다. 데이터
   의 인코딩 방식은 *message_body*의 형에 따라 다릅니다.
   *message_body*가 버퍼 인터페이스를 구현하면, 인코딩은 단일 청크를
   만듭니다. *message_body*가 "collections.abc.Iterable"이면,
   *message_body*의 각 이터레이션이 청크가 됩니다. *message_body*가 *
   파일 객체*이면, 각 ".read()" 호출마다 청크가 됩니다. 이 메서드는
   *message_body* 직후에 청크 인코딩된 데이터의 끝을 자동으로 알립니다
   .

   참고:

     청크 인코딩 명세로 인해, 이터레이터 바디에서 산출된 빈 청크는 청
     크 인코더에서 무시됩니다. 이는 형식이 잘못된 인코딩으로 인해 대상
     서버의 요청 읽기가 조기에 종료되지 않도록 하려는 것입니다.

   버전 3.6에 추가: 청크 인코딩 지원. *encode_chunked* 매개 변수가 추
   가되었습니다.

HTTPConnection.send(data)

   서버로 data를 보냅니다. 이것은 "endheaders()" 메서드가 호출된 후,
   그리고 "getresponse()"가 호출되기 전에만 직접 사용해야 합니다.

   Raises an auditing event "http.client.send" with arguments "self",
   "data".


HTTPResponse 객체
=================

"HTTPResponse" 인스턴스는 서버의 HTTP 응답을 감쌉니다. 요청 헤더와 엔
티티 바디에 대한 액세스를 제공합니다. 응답은 이터러블 객체이며 with 문
에서 사용할 수 있습니다.

버전 3.5에서 변경: "io.BufferedIOBase" 인터페이스가 이제 구현되었으며
이것의 모든 판독기(reader) 연산이 지원됩니다.

HTTPResponse.read([amt])

   응답 바디나 다음 최대 *amt* 바이트를 읽고 반환합니다.

HTTPResponse.readinto(b)

   응답 바디의 다음 최대 len(b) 바이트를 버퍼 *b*로 읽습니다. 읽은 바
   이트 수를 반환합니다.

   버전 3.3에 추가.

HTTPResponse.getheader(name, default=None)

   Return the value of the header *name*, or *default* if there is no
   header matching *name*.  If there is more than one  header with the
   name *name*, return all of the values joined by ', '.  If *default*
   is any iterable other than a single string, its elements are
   similarly returned joined by commas.

HTTPResponse.getheaders()

   (헤더, 값) 튜플의 리스트를 반환합니다.

HTTPResponse.fileno()

   하부 소켓의 "fileno"를 반환합니다.

HTTPResponse.msg

   응답 헤더를 포함하는 "http.client.HTTPMessage" 인스턴스.
   "http.client.HTTPMessage"는 "email.message.Message"의 서브 클래스입
   니다.

HTTPResponse.version

   서버가 사용하는 HTTP 프로토콜 버전. HTTP/1.0의 경우 10, HTTP/1.1의
   경우 11.

HTTPResponse.url

   가져온 자원의 URL, 일반적으로 리디렉션을 따라갔는지 판별하는 데 사
   용됩니다.

HTTPResponse.headers

   "email.message.EmailMessage" 인스턴스 형식의 응답 헤더.

HTTPResponse.status

   서버가 반환한 상태 코드.

HTTPResponse.reason

   서버가 반환한 이유 문구.

HTTPResponse.debuglevel

   디버깅 훅. "debuglevel"이 0보다 크면, 응답을 읽고 구문 분석할 때 메
   시지가 표준 출력으로 인쇄됩니다.

HTTPResponse.closed

   스트림이 닫혔으면 "True"입니다.

HTTPResponse.geturl()

   버전 3.9부터 폐지: 폐지되었고 "url"로 대체되었습니다.

HTTPResponse.info()

   버전 3.9부터 폐지: 폐지되었고 "headers"로 대체되었습니다.

HTTPResponse.getcode()

   버전 3.9부터 폐지: 폐지되었고 "status"로 대체되었습니다.


예
==

"GET" 메서드를 사용하는 예제 세션은 다음과 같습니다:

   >>> import http.client
   >>> conn = http.client.HTTPSConnection("www.python.org")
   >>> conn.request("GET", "/")
   >>> r1 = conn.getresponse()
   >>> print(r1.status, r1.reason)
   200 OK
   >>> data1 = r1.read()  # This will return entire content.
   >>> # The following example demonstrates reading data in chunks.
   >>> conn.request("GET", "/")
   >>> r1 = conn.getresponse()
   >>> while chunk := r1.read(200):
   ...     print(repr(chunk))
   b'<!doctype html>\n<!--[if"...
   ...
   >>> # Example of an invalid request
   >>> conn = http.client.HTTPSConnection("docs.python.org")
   >>> conn.request("GET", "/parrot.spam")
   >>> r2 = conn.getresponse()
   >>> print(r2.status, r2.reason)
   404 Not Found
   >>> data2 = r2.read()
   >>> conn.close()

다음은 "HEAD" 메서드를 사용하는 예제 세션입니다. "HEAD" 메서드는 어떤
데이터도 반환하지 않음에 유의하십시오.

   >>> import http.client
   >>> conn = http.client.HTTPSConnection("www.python.org")
   >>> conn.request("HEAD", "/")
   >>> res = conn.getresponse()
   >>> print(res.status, res.reason)
   200 OK
   >>> data = res.read()
   >>> print(len(data))
   0
   >>> data == b''
   True

Here is an example session that uses the "POST" method:

   >>> import http.client, urllib.parse
   >>> params = urllib.parse.urlencode({'@number': 12524, '@type': 'issue', '@action': 'show'})
   >>> headers = {"Content-type": "application/x-www-form-urlencoded",
   ...            "Accept": "text/plain"}
   >>> conn = http.client.HTTPConnection("bugs.python.org")
   >>> conn.request("POST", "", params, headers)
   >>> response = conn.getresponse()
   >>> print(response.status, response.reason)
   302 Found
   >>> data = response.read()
   >>> data
   b'Redirecting to <a href="https://bugs.python.org/issue12524">https://bugs.python.org/issue12524</a>'
   >>> conn.close()

Client side HTTP "PUT" requests are very similar to "POST" requests.
The difference lies only on the server side where HTTP servers will
allow resources to be created via "PUT" requests. It should be noted
that custom HTTP methods are also handled in "urllib.request.Request"
by setting the appropriate method attribute. Here is an example
session that uses the "PUT" method:

   >>> # This creates an HTTP request
   >>> # with the content of BODY as the enclosed representation
   >>> # for the resource http://localhost:8080/file
   ...
   >>> import http.client
   >>> BODY = "***filecontents***"
   >>> conn = http.client.HTTPConnection("localhost", 8080)
   >>> conn.request("PUT", "/file", BODY)
   >>> response = conn.getresponse()
   >>> print(response.status, response.reason)
   200, OK


HTTPMessage 객체
================

"http.client.HTTPMessage" 인스턴스는 HTTP 응답의 헤더를 보유합니다.
"email.message.Message" 클래스를 사용하여 구현됩니다.
