requests 封装, http
封装
点击查看代码
import functools
import traceback
from django_redis import get_redis_connection
from requests.adapters import HTTPAdapter
import requests
import logging
redis_obj = get_redis_connection()
def http_base(func):
@functools.wraps(func)
def decorator(*args, **kwargs):
timeout = kwargs.get("timeout")
exception_info = kwargs.pop("exception_info", None) # 异常时需要打印的信息
exception_info = f"【{exception_info}】" if exception_info else ""
retry = kwargs.pop("retry", 0)
_session = requests.Session()
_session.mount("http://", HTTPAdapter(max_retries=retry))
_session.mount("https://", HTTPAdapter(max_retries=retry))
try:
kwargs["session"] = _session
response = func(*args, **kwargs)
if response.status_code != 200:
logger.error(f"{exception_info},外部接口调用状态错误:{args, kwargs}\n,错误码:{response.status_code}")
return False, dict()
else:
return True, response.json()
except requests.exceptions.ReadTimeout:
_timeout = timeout * retry if retry else timeout
logger.error(f"{exception_info},外部接口调用超时:{args, kwargs}\n请求时长:{_timeout}S")
return False, dict()
except Exception as e:
logger.error(f"{exception_info},外部接口调用异常:{args, kwargs}\n{traceback.format_exc()}")
return False, dict()
return decorator
@http_base
def http_post(*args, **kwargs) -> (bool, dict):
"""用于外部post请求,封装相关异常处理
:param kwargs:
session: request对象(http_base装饰器返回)
exception_info:异常提示
retry:超时重试次数
:return data: 字典,具体有业务决定
"""
_session = kwargs.pop("session")
return _session.post(*args, **kwargs)
@http_base
def http_get(*args, **kwargs) -> (bool, dict):
"""用于外部get请求,封装相关异常处理
:param kwargs:
session: request对象(http_base装饰器返回)
exception_info:异常提示
retry:超时重试次数
:return data: 字典,具体有业务决定
"""
_session = kwargs.pop("session")
return _session.get(*args, **kwargs)
使用
点击查看代码
url = ''
json_data = {
}
headers = {
"token": ''
}
ok, data = http_post(url=url, timeout=TIMEOUT, json=json_data, headers=headers,
exception_info=f"分流推送异常")
return data
异常
如果在使用的时候遇到"UNSAFE_LEGACY_RENEGOTIATION_DISABLED"异常,这是因为ssl加密不支持了,需要跟换加密方式,解决方案如需下:
import ssl
import urllib3
from requests.adapters import HTTPAdapter
class CustomHttpAdapter (requests.adapters.HTTPAdapter):
'''Transport adapter" that allows us to use custom ssl_context.'''
def __init__(self, ssl_context=None, **kwargs):
self.ssl_context = ssl_context
super().__init__(**kwargs)
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = urllib3.poolmanager.PoolManager(
num_pools=connections, maxsize=maxsize,
block=block, ssl_context=self.ssl_context)
# 把http_base函数用下边的替换:
def http_base(func):
@functools.wraps(func)
def decorator(*args, **kwargs):
timeout = kwargs.get("timeout")
exception_info = kwargs.pop("exception_info", None) # 异常时需要打印的信息
exception_info = f"【{exception_info}】" if exception_info else ""
retry = kwargs.pop("retry", 0)
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ctx.options |= 0x4
_session = requests.Session()
_session.mount("http://", CustomHttpAdapter(ctx, max_retries=retry))
_session.mount("https://", CustomHttpAdapter(ctx, max_retries=retry))
try:
kwargs["session"] = _session
response = func(*args, **kwargs)
if response.status_code != 200:
logger.error(f"{exception_info},外部接口调用状态错误:{args, kwargs}\n,错误码:{response.status_code}")
return False, dict()
else:
return True, response.json()
except requests.exceptions.ReadTimeout:
_timeout = timeout * retry if retry else timeout
logger.error(f"{exception_info},外部接口调用超时:{args, kwargs}\n请求时长:{_timeout}S")
return False, dict()
except Exception as e:
logger.error(f"{exception_info},外部接口调用异常:{args, kwargs}\n{traceback.format_exc()}")
return False, dict()
return decorator
上边最主要的是改了一下内容: