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

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

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

이 모듈은 HTTP 및 HTTPS 프로토콜의 클라이언트 측을 구현하는 클래스를
정의합니다. 일반적으로 직접 사용되지 않습니다 --- "urllib.request" 모
듈은 이를 사용하여 HTTP와 HTTPS를 사용하는 URL을 처리합니다.

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

참고:

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

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

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

   "HTTPConnection" 인스턴스는 HTTP 서버와의 하나의 트랜잭션을 나타냅
   니다. 호스트와 선택적 포트 번호를 전달하여 인스턴스화해야 합니다.
   포트 번호가 전달되지 않으면, host 문자열이 "host:port" 형식이면 여
   기에서 포트가 추출됩니다, 그렇지 않으면 기본 HTTP 포트(80)가 사용됩
   니다. 선택적 *timeout* 매개 변수가 제공되면, 블로킹 연산(연결 시도
   와 같은)이 지정된 초 후에 시간제한으로 종료됩니다 (제공되지 않으면,
   전역 기본 시간제한 설정이 사용됩니다). 선택적 *source_address* 매개
   변수는 HTTP 연결의 소스 주소로 사용할 (호스트, 포트)의 튜플일 수 있
   습니다. 선택적 *blocksize* 매개 변수는 파일류 메시지 바디를 보내는
   데 필요한 버퍼 크기를 바이트 단위로 설정합니다.

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

      >>> 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에서 변경: *strict* 매개 변수가 제거되었습니다. HTTP 0.9 스
   타일 "간단한 응답"은 더는 지원되지 않습니다.

   버전 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.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()

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

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()"가 호출되기 전에만 직접 사용해야 합니다.


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)

   헤더 *name*의 값을 반환하거나, *name*과 일치하는 헤더가 없으면
   *default*를 반환합니다. 이름이 *name*인 헤더가 둘 이상 있으면, ','
   로 연결한 모든 값을 반환합니다. 'default'가 단일 문자열 이외의 이터
   러블이면, 해당 요소들도 마찬가지로 쉼표로 연결되어 반환됩니다.

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.getstatus()

   버전 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

다음은 요청을 "POST" 하는 방법을 보여주는 예제 세션입니다:

   >>> 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="http://bugs.python.org/issue12524">http://bugs.python.org/issue12524</a>'
   >>> conn.close()

클라이언트 측 "HTTP PUT" 요청은 "POST" 요청과 매우 유사합니다. 차이점
은 HTTP 서버가 "PUT" 요청을 통해 리소스를 만들도록 허락하는 서버 측에
만 있습니다. 사용자 정의 HTTP 메서드는 적절한 method 어트리뷰트를 설정
함으로써 "urllib.request.Request"에서도 처리된다는 점에 주목해야 합니
다. 다음은 http.client를 사용하여 "PUT" 요청을 보내는 방법을 보여주는
예제 세션입니다:

   >>> # This creates an HTTP message
   >>> # 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" 클래스를 사용하여 구현됩니다.
