requests 라이브러리를 통해 외부 API 개발을 하는 도중,
로컬 및 개발 환경에서는 큰 문제가 없었지만 운영 환경에서 SSLError가 발생했다.
verify=False 인자를 추가하거나 파이썬 3.9.x 버전을 사용하는 것은 좋은 방법이 아닌 것 같아 다른 해결 방법을 찾던 중 좋은 자료를 찾았다. (하단 참고)
urllib3가 requests보다 더 low level의 코드라고 한다. 자세한 건 chatgpt에게 물어보는 것도 좋다.
예제를 통해 두 라이브러리를 비교하면서 알아보자.
[GET] request
import hashlib
import requests
params ={
"key_a": "val_a",
"key_b": "val_b",
"key_c": "val_c",
}
sig = ""
for key, value in params.items():
sig += f"{key}={value}&"
sig += f"hashKey={HASH_KEY}"
signature = hashlib.sha256(sig.encode()).hexdigest()
params['signature'] = signature
response = requests.get(
url="요청 URL",
params=params,
)
status = response.status_code
result = response.json()
[GET] urllib3
import hashlib
import ssl
from urllib3 import PoolManager
from urllib3.util import create_urllib3_context
from config import settings # 개인 환경 설정
# params 설정을 동일하다.
params ={
"key_a": "val_a",
"key_b": "val_b",
"key_c": "val_c",
}
sig = ""
for key, value in params.items():
sig += f"{key}={value}&"
sig += f"hashKey={HASH_KEY}"
signature = hashlib.sha256(sig.encode()).hexdigest()
params['signature'] = signature
# SSLError가 발생하지 않는 로컬 및 개발 환경에서는 ctx 인자가 필요없다.
if settings.ENV != "PROD":
pool_manager = PoolManager()
else:
ctx = create_urllib3_context()
ctx.load_default_certs()
ctx.set_ciphers('AES256-GCM-SHA384')
pool_manager = PoolManager(ssl_context=ctx)
with pool_manager as pool:
response = pool.request(
method='GET',
url='요청 URL',
fields=params,
)
status = response.status
result = response.json()
[POST] request
import hashlib
import json
import requests
from config import settings # 개인 환경 설정
# body 설정을 동일하다.
body ={
"key_a": "val_a",
"key_b": "val_b",
"key_c": "val_c",
}
sig = ""
for key, value in params.items():
sig += f"{key}={value}&"
sig += f"hashKey={HASH_KEY}"
signature = hashlib.sha256(sig.encode()).hexdigest()
body['signature'] = signature
response = requests.post(
url='요청 URL',
headers={
"Content-Type": "application/json;charset=utf-8"
},
data=body,
)
status = response.status_code
result = response.json()
[POST] urllib3 - application/json
import hashlib
import json
import ssl
from urllib3 import PoolManager
from urllib3.util import create_urllib3_context
from config import settings # 개인 환경 설정
# body 설정을 동일하다.
body ={
"key_a": "val_a",
"key_b": "val_b",
"key_c": "val_c",
}
sig = ""
for key, value in params.items():
sig += f"{key}={value}&"
sig += f"hashKey={HASH_KEY}"
signature = hashlib.sha256(sig.encode()).hexdigest()
body['signature'] = signature
# SSLError가 발생하지 않는 로컬 및 개발 환경에서는 ctx 인자가 필요없다.
if settings.ENV != "PROD":
pool_manager = PoolManager()
else:
ctx = create_urllib3_context()
ctx.load_default_certs()
ctx.set_ciphers('AES256-GCM-SHA384')
pool_manager = PoolManager(ssl_context=ctx)
with pool_manager as pool:
response = pool.request(
method='POST',
url='요청 URL',
headers={
"Content-Type": "application/json;charset=utf-8"
},
json=body, # json.dumps(body).encode('utf-8'),
timeout=3.0,
)
status = response.status
result = response.json()
[POST] urllib3 - application/x-www-form-urlencoded
import hashlib
import ssl
from urllib3 import PoolManager
from urllib3.util import create_urllib3_context
from urllib.parse import urlencode
from config import settings # 개인 환경 설정
# body 설정을 동일하다.
body ={
"key_a": "val_a",
"key_b": "val_b",
"key_c": "val_c",
}
sig = ""
for key, value in params.items():
sig += f"{key}={value}&"
sig += f"hashKey={HASH_KEY}"
signature = hashlib.sha256(sig.encode()).hexdigest()
body['signature'] = signature
# SSLError가 발생하지 않는 로컬 및 개발 환경에서는 ctx 인자가 필요없다.
if settings.ENV != "PROD":
pool_manager = PoolManager()
else:
ctx = create_urllib3_context()
ctx.load_default_certs()
ctx.set_ciphers('AES256-GCM-SHA384')
pool_manager = PoolManager(ssl_context=ctx)
with pool_manager as pool:
response = pool.request(
method='POST',
url='요청 URL',
headers={
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
},
body=urlencode(body),
timeout=3.0,
)
status = response.status
result = response.json()
- Content-Type에 따라 파라미터가 다르다.
- json: json = json.dumps().encode('utf-8')
- x-www-form-urlencoded: body = urlencode()
관련 자료
urllib3 docs
'Python tips' 카테고리의 다른 글
서버 로컬 지역에 상관없이 한국 시간 기준 datetime (0) | 2024.06.19 |
---|---|
임시 비밀번호, 랜덤 문자열 generator (0) | 2024.05.08 |
@property와 __call__ 비교 (0) | 2024.05.08 |
KISA 128bit SEED CBC 암호화 복호화 (0) | 2024.04.16 |
map(), filter(), pipe()를 활용하여 데이터 다루기 (0) | 2024.04.08 |