개요
이전에 python의 requests를 사용해 http 요청하는 방법을 적어두었었는데, requests 라이브러리 외에 http 요청을 할 수 있는 방법은 여러 가지다. 이번 글에서는 Tornado의 httpclient 객체를 사용해 http 요청을 하는 방법을 적어둔다.
tornado.httpclient
tornado.httpclient는 차단/비차단 HTTP 클라이언트 인터페이스다.
simple_httpclient, curl_httpclient을 공유하는 공통 인터페이스를 정의하며, 사용자 애플리케이션은 적절한 구현 클래스를 직접 인스턴스화하거나 AsyncHTTPClient를 사용하여 재정의할 수 있는 구현 클래스를 선택할 수 있다. 기본적으로는 simple_httpclient를 사용한다.
curl_httpclient은 simple_httpclient에서 지원하지 않는 HTTP 프록시나 지정 네트워크 인터페이스 사용 기능을 지원하며, HTTP 사양을 제대로 준수하지 않는 사이트나 HTTP 기능을 거의 사용하지 않는 사이트와 보다 높은 호환성을 가진다.
라이브러리 임포트
tornado.httpclient를 사용할 때는 아래와 같이 임포트하여 사용한다.
from tornado import httpclient
기본 사용 예시
일반적으로 httpclient를 사용해 HTTP를 요청할 때는 HTTPClient 객체 생성 -> fetch 함수로 요청 -> HTTPClient.close 호출 순으로 구현한다.
from tornado import httpclient
import json
http_client = httpclient.HTTPClient()
response = http_client.fetch("https://jsonplaceholder.typicode.com/todos/1")
print(json.loads(response.body))
http_client.close()
다만 httpclient는 200번 이외의 응답 코드를 받은 경우 httpclient.HTTPError를 발생시킨다. 따라서 일반적으로 예외 처리도 함께 이루어져야 한다. 에러에 대한 응답은 httpclient.HTTPError의 response 속성으로 접근할 수 있다.
from tornado import httpclient
import json
http_client = httpclient.HTTPClient()
try:
response = http_client.fetch("https://jsonplaceholder.typicode.com/todos/2f")
print(json.loads(response.body))
except httpclient.HTTPError as e:
print("Error: " + str(e.response.error))
except Exception as e:
print("Error: " + str(e))
http_client.close()
참고로 asyncio 제한으로 인해 IOLoop가 동작 중일 때는 동기 방식 HTTPClient를 사용할 수 없게 되었다. 따라서 AsyncHTTPClient를 대신 사용해야 한다.
HTTPRequest 전달 예시
실제로 요청을 할 때는 단순 GET 뿐만 아니라, POST로 요청하거나 Header를 설정해야 하는 경우도 있다. 이런 경우에는 HTTPRequest를 선언한 후 전달한다.
아래 코드는 요청할 URL과 메서드 종류, 헤더 및 요청 본문을 지정한 HTTPRequest 객체이다.
request = httpclient.HTTPRequest(
url='https://jsonplaceholder.typicode.com/posts',
method='POST',
headers={'Content-Type': 'application/json; charset=UTF-8'},
body=json.dumps({
'title': 'foo',
'body': 'passwd',
'userId': 99,
})
)
이 객체를 아래와 같이 그대로 fetch 함수에 전달하면 된다.
from tornado import httpclient
import json
http_client = httpclient.HTTPClient()
request = httpclient.HTTPRequest(
'https://jsonplaceholder.typicode.com/posts',
method='POST',
headers={'Content-Type': 'application/json; charset=UTF-8'},
body=json.dumps({
'title': 'foo',
'body': 'passwd',
'userId': 99,
})
)
try:
response = http_client.fetch(request)
print(json.loads(response.body))
except httpclient.HTTPError as e:
print("Error: " + str(e.response.error))
except Exception as e:
print("Error: " + str(e))
http_client.close()
참고 문서
https://www.tornadoweb.org/en/stable/httpclient.html