Files
apiautotest/utils/requests_utils/base_request.py

215 lines
8.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
# @Time : 2023/10/12 13:41
# @Author : floraachy
# @File : base_request.py
# @Software: PyCharm
# @Desc:
# 标准库导入
import os
import time
from typing import Optional, Union, Dict, Text
# 第三方库导入
from loguru import logger
import requests # pip install requests
from requests_toolbelt import MultipartEncoder # pip install requests_toolbelt
class BaseRequest:
"""
Request操作封装
"""
TIMEOUT = 30
@classmethod
def send_request(cls, req_data):
"""
处理请求数据,转换成可用数据发送请求
:param req_data: 请求数据
:return: 响应对象
"""
try:
request_type = req_data.get("request_type", None)
url = req_data.get("url", "")
method = req_data.get("method").lower()
headers = req_data.get("headers", {})
payload = req_data.get("payload", None)
files = req_data.get("files", None)
cookies = req_data.get("cookies", None)
if request_type and request_type.lower() == "json":
return cls.request_type_for_json(method=method, url=url, headers=headers, json=payload, cookies=cookies)
elif request_type and request_type.lower() == "data":
return cls.request_type_for_data(method=method, url=url, headers=headers, data=payload, cookies=cookies)
elif request_type and request_type.lower() == "file":
return cls.request_type_for_file(method=method, url=url, headers=headers, files=files,
fields=payload, cookies=cookies)
elif request_type and request_type.lower() == "params":
return cls.request_type_for_params(method=method, url=url, headers=headers, params=payload,
cookies=cookies)
# todo 待后续补充
# elif request_type and request_type.lower() == "export":
# return cls.request_type_for_export(method=method, url=url, headers=headers, **req_data)
else:
return cls.request_type_for_none(method=method, url=url, headers=headers, cookies=cookies)
except requests.exceptions.RequestException as e:
logger.error(f"请求出错,{str(e)}")
raise
@classmethod
def request_type_for_json(cls, method: Text, url: Text, headers: Optional[Dict], json: Optional[Dict], **kwargs):
"""
处理 requestType 为json格式
json: 通过这种方式传递的参数会出现在请求体中并且需要设置Content-Type为application/json。
所有传递的参数都需要被编码为JSON格式。在Python中可以使用内置的json模块来编码数据。
传递的参数会被编码为JSON格式并包含在请求体中。
需要注意的是使用这种方式传递的参数必须是可序列化为JSON的数据类型如字典、列表、整数、浮点数、布尔值或None。对于不可序列化的数据类型如文件或其他自定义对象需要先进行序列化。
"""
logger.debug("发送请求:\n"
"request_type=json\n"
f"method={method}\n"
f"url={url}\n"
f"headers={headers}\n"
f"json={json}\n"
f"其他参数:{kwargs}\n")
return requests.request(
method=method,
url=url,
json=json,
headers=headers,
timeout=cls.TIMEOUT,
**kwargs
)
@classmethod
def request_type_for_params(cls, method: Text, url: Text, headers: Optional[Dict], params: Dict, **kwargs):
"""
处理 requestType 为 params
params: 这是通过URL传递参数的方式。所有传递的参数都会被编码到URL中。requests库会自动处理这些参数的编码。
需要注意的是,这种方式只适用于简单的键值对,对于复杂的数据结构,如列表或字典,需要先进行序列化。
"""
logger.debug("发送请求:\n"
"request_type=params\n"
f"method={method}\n"
f"url={url}\n"
f"headers={headers}\n"
f"params={params}\n"
f"其他参数:{kwargs}\n")
return requests.request(
method=method,
url=url,
headers=headers,
params=params,
timeout=cls.TIMEOUT,
**kwargs
)
@classmethod
def request_type_for_data(cls, method: Text, url: Text, headers: Optional[Dict], data: Optional[Dict], **kwargs):
"""
处理 requestType 为 data 类型
data: 通过这种方式传递的参数会出现在请求体中。
这些参数通常需要通过requests库提供的data参数来传递并且在发送请求时需要设置Content-Type为application/x-www-form-urlencoded或multipart/form-data。
对于简单的键值对可以直接将它们作为字典传递给data参数对于复杂的数据结构需要先进行序列化。
"""
logger.debug("发送请求:\n"
"request_type=data\n"
f"method={method}\n"
f"url={url}\n"
f"headers={headers}\n"
f"data={data}\n"
f"其他参数:{kwargs}\n")
return requests.request(
method=method,
url=url,
headers=headers,
data=data,
timeout=cls.TIMEOUT,
**kwargs
)
@classmethod
def request_type_for_file(cls, method: Text, url: Text, headers: Optional[Dict],
fields: Union[Dict, Text, None],
files: Text, **kwargs):
"""
处理 requestType 为 file 类型
本方法用于构建和发送包含文件上传的 HTTP 请求。它通过多部分表单数据格式来上传文件,
这是HTTP协议中用于上传文件的标准方法。
参数:
- method (Text): HTTP 方法,如 'POST'
- url (Text): 请求的URL。
- headers (Dict): 请求的HTTP头。
- fields (Dict): 请求的表单字段。通常包含文件字段的信息。
- files: 要上传的文件路径。
- cookies (Optional): 请求的cookies。
- **kwargs: 其他请求参数,如标签和回调函数等。
返回:
- requests.Response: 发送请求后的响应对象。
"""
logger.debug("发送请求:\n"
"request_type=file\n"
f"method={method}\n"
f"url={url}\n"
f"headers={headers}\n"
f"fields={fields}\n"
f"files={files}\n"
f"其他参数:{kwargs}\n")
# 如果fields没有指定则默认使用 "file" 作为字段名
_fields = fields or "file"
# 构建多部分表单数据的编码器,设置边界参数为当前时间戳
encoder = MultipartEncoder(
fields={
_fields: (
os.path.basename(files), # 使用文件的基名作为文件名
open(files, "rb") # 打开文件以二进制读取模式
)
},
boundary='------------------------' + str(time.time()) # 生成唯一的边界标记
)
# 设置Content-Type头为multipart/form-data这是文件上传所需的
headers['Content-Type'] = encoder.content_type
# 发送请求使用multipart/form-data编码的数据
response = requests.request(
method=method,
url=url,
headers=headers,
data=encoder.to_string(), # 将编码数据转换为字符串形式
timeout=cls.TIMEOUT, # 使用类定义的超时时间
**kwargs # 传递其他请求参数
)
return response
@classmethod
def request_type_for_none(cls, method: Text, url: Text, headers: Optional[Dict], **kwargs):
"""处理 requestType 为 None"""
logger.debug("发送请求:\n"
"request_type=none\n"
f"method={method}\n"
f"url={url}\n"
f"headers={headers}\n"
f"其他参数:{kwargs}\n")
return requests.request(
method=method,
url=url,
headers=headers,
timeout=cls.TIMEOUT,
**kwargs
)
@classmethod
def request_type_for_export(cls, method: Text, url: str, headers: Optional[Dict], **kwargs):
"""判断 requestType 为 export 导出类型"""
logger.debug("requestType 为 export 类型")
# todo 后续有需求再补充
return ""