auto close RequestUtils

This commit is contained in:
jxxghp
2025-06-27 08:30:57 +08:00
parent 9555ac6305
commit d8a53da8ee
2 changed files with 132 additions and 49 deletions

View File

@@ -4,7 +4,6 @@ from pathlib import Path
from typing import Optional, List, Dict
import requests
from requests import Response
from app import schemas
from app.core.cache import cached
@@ -77,7 +76,7 @@ class Alist(StorageBase, metaclass=Singleton):
token = conf.get("token")
if token:
return str(token)
resp: Response = RequestUtils(headers={
resp = RequestUtils(headers={
'Content-Type': 'application/json'
}).post_res(
self.__get_api_url("/api/auth/login"),
@@ -151,7 +150,7 @@ class Alist(StorageBase, metaclass=Singleton):
if item:
return [item]
return []
resp: Response = RequestUtils(
resp = RequestUtils(
headers=self.__get_header_with_token()
).post_res(
self.__get_api_url("/api/fs/list"),
@@ -240,7 +239,7 @@ class Alist(StorageBase, metaclass=Singleton):
:param name: 目录名
"""
path = Path(fileitem.path) / name
resp: Response = RequestUtils(
resp = RequestUtils(
headers=self.__get_header_with_token()
).post_res(
self.__get_api_url("/api/fs/mkdir"),
@@ -304,7 +303,7 @@ class Alist(StorageBase, metaclass=Singleton):
:param per_page: 每页数量
:param refresh: 是否刷新
"""
resp: Response = RequestUtils(
resp = RequestUtils(
headers=self.__get_header_with_token()
).post_res(
self.__get_api_url("/api/fs/get"),
@@ -381,7 +380,7 @@ class Alist(StorageBase, metaclass=Singleton):
"""
删除文件
"""
resp: Response = RequestUtils(
resp = RequestUtils(
headers=self.__get_header_with_token()
).post_res(
self.__get_api_url("/api/fs/remove"),
@@ -425,7 +424,7 @@ class Alist(StorageBase, metaclass=Singleton):
"""
重命名文件
"""
resp: Response = RequestUtils(
resp = RequestUtils(
headers=self.__get_header_with_token()
).post_res(
self.__get_api_url("/api/fs/rename"),
@@ -476,7 +475,7 @@ class Alist(StorageBase, metaclass=Singleton):
:param path: 文件保存路径
:param password: 文件密码
"""
resp: Response = RequestUtils(
resp = RequestUtils(
headers=self.__get_header_with_token()
).post_res(
self.__get_api_url("/api/fs/get"),
@@ -561,7 +560,7 @@ class Alist(StorageBase, metaclass=Singleton):
headers.setdefault("As-Task", str(task).lower())
headers.setdefault("File-Path", encoded_path)
with open(path, "rb") as f:
resp: Response = RequestUtils(headers=headers).put_res(
resp = RequestUtils(headers=headers).put_res(
self.__get_api_url("/api/fs/put"),
data=f,
)
@@ -590,7 +589,7 @@ class Alist(StorageBase, metaclass=Singleton):
:param path: 目标目录
:param new_name: 新文件名
"""
resp: Response = RequestUtils(
resp = RequestUtils(
headers=self.__get_header_with_token()
).post_res(
self.__get_api_url("/api/fs/copy"),
@@ -649,7 +648,7 @@ class Alist(StorageBase, metaclass=Singleton):
# 先重命名
if fileitem.name != new_name:
self.rename(fileitem, new_name)
resp: Response = RequestUtils(
resp = RequestUtils(
headers=self.__get_header_with_token()
).post_res(
self.__get_api_url("/api/fs/move"),

View File

@@ -13,6 +13,70 @@ from app.log import logger
urllib3.disable_warnings(InsecureRequestWarning)
class AutoCloseResponse:
"""
自动关闭连接的Response包装器
在访问常用属性后自动关闭连接
"""
def __init__(self, response: Response):
self._response = response
self._closed = False
def __getattr__(self, name):
"""
对于其他属性直接委托给原始response
"""
return getattr(self._response, name)
def _auto_close(self):
"""
自动关闭连接
"""
if not self._closed and self._response:
try:
self._response.close()
self._closed = True
except Exception as e:
logger.debug(f"自动关闭响应失败: {e}")
def json(self, **kwargs):
"""
获取JSON数据并自动关闭连接
"""
try:
data = self._response.json(**kwargs)
return data
finally:
self._auto_close()
@property
def text(self):
"""
获取文本内容并自动关闭连接
"""
try:
return self._response.text
finally:
self._auto_close()
@property
def content(self):
"""
获取二进制内容并自动关闭连接
"""
try:
return self._response.content
finally:
self._auto_close()
def close(self):
"""
手动关闭连接
"""
self._auto_close()
class RequestUtils:
def __init__(self,
@@ -125,7 +189,8 @@ class RequestUtils:
json: dict = None,
allow_redirects: bool = True,
raise_exception: bool = False,
**kwargs) -> Optional[Response]:
auto_close: bool = True,
**kwargs) -> Optional[AutoCloseResponse]:
"""
发送GET请求并返回响应对象
:param url: 请求的URL
@@ -134,18 +199,22 @@ class RequestUtils:
:param json: 请求的JSON数据
:param allow_redirects: 是否允许重定向
:param raise_exception: 是否在发生异常时抛出异常否则默认拦截异常返回None
:param auto_close: 是否自动关闭响应连接None时使用全局配置
:param kwargs: 其他请求参数如headers, cookies, proxies等
:return: HTTP响应对象若发生RequestException则返回None
:raises: requests.exceptions.RequestException 仅raise_exception为True时会抛出
"""
return self.request(method="get",
url=url,
params=params,
data=data,
json=json,
allow_redirects=allow_redirects,
raise_exception=raise_exception,
**kwargs)
response = self.request(method="get",
url=url,
params=params,
data=data,
json=json,
allow_redirects=allow_redirects,
raise_exception=raise_exception,
**kwargs)
if response is not None and auto_close:
return AutoCloseResponse(response)
return response
@contextmanager
def get_stream(self, url: str, params: dict = None, **kwargs):
@@ -171,7 +240,8 @@ class RequestUtils:
files: Any = None,
json: dict = None,
raise_exception: bool = False,
**kwargs) -> Optional[Response]:
auto_close: bool = True,
**kwargs) -> Optional[AutoCloseResponse]:
"""
发送POST请求并返回响应对象
:param url: 请求的URL
@@ -180,20 +250,24 @@ class RequestUtils:
:param allow_redirects: 是否允许重定向
:param files: 请求的文件
:param json: 请求的JSON数据
:param kwargs: 其他请求参数如headers, cookies, proxies等
:param raise_exception: 是否在发生异常时抛出异常否则默认拦截异常返回None
:param auto_close: 是否自动关闭响应连接None时使用全局配置
:param kwargs: 其他请求参数如headers, cookies, proxies等
:return: HTTP响应对象若发生RequestException则返回None
:raises: requests.exceptions.RequestException 仅raise_exception为True时会抛出
"""
return self.request(method="post",
url=url,
data=data,
params=params,
allow_redirects=allow_redirects,
files=files,
json=json,
raise_exception=raise_exception,
**kwargs)
response = self.request(method="post",
url=url,
data=data,
params=params,
allow_redirects=allow_redirects,
files=files,
json=json,
raise_exception=raise_exception,
**kwargs)
if response is not None and auto_close:
return AutoCloseResponse(response)
return response
def put_res(self,
url: str,
@@ -203,7 +277,8 @@ class RequestUtils:
files: Any = None,
json: dict = None,
raise_exception: bool = False,
**kwargs) -> Optional[Response]:
auto_close: bool = True,
**kwargs) -> Optional[AutoCloseResponse]:
"""
发送PUT请求并返回响应对象
:param url: 请求的URL
@@ -213,19 +288,23 @@ class RequestUtils:
:param files: 请求的文件
:param json: 请求的JSON数据
:param raise_exception: 是否在发生异常时抛出异常否则默认拦截异常返回None
:param auto_close: 是否自动关闭响应连接None时使用全局配置
:param kwargs: 其他请求参数如headers, cookies, proxies等
:return: HTTP响应对象若发生RequestException则返回None
:raises: requests.exceptions.RequestException 仅raise_exception为True时会抛出
"""
return self.request(method="put",
url=url,
data=data,
params=params,
allow_redirects=allow_redirects,
files=files,
json=json,
raise_exception=raise_exception,
**kwargs)
response = self.request(method="put",
url=url,
data=data,
params=params,
allow_redirects=allow_redirects,
files=files,
json=json,
raise_exception=raise_exception,
**kwargs)
if response is not None and auto_close:
return AutoCloseResponse(response)
return response
def delete_res(self,
url: str,
@@ -233,7 +312,8 @@ class RequestUtils:
params: dict = None,
allow_redirects: bool = True,
raise_exception: bool = False,
**kwargs) -> Optional[Response]:
auto_close: bool = True,
**kwargs) -> Optional[AutoCloseResponse]:
"""
发送DELETE请求并返回响应对象
:param url: 请求的URL
@@ -241,17 +321,21 @@ class RequestUtils:
:param params: 请求的参数
:param allow_redirects: 是否允许重定向
:param raise_exception: 是否在发生异常时抛出异常否则默认拦截异常返回None
:param auto_close: 是否自动关闭响应连接None时使用全局配置
:param kwargs: 其他请求参数如headers, cookies, proxies等
:return: HTTP响应对象若发生RequestException则返回None
:raises: requests.exceptions.RequestException 仅raise_exception为True时会抛出
"""
return self.request(method="delete",
url=url,
data=data,
params=params,
allow_redirects=allow_redirects,
raise_exception=raise_exception,
**kwargs)
response = self.request(method="delete",
url=url,
data=data,
params=params,
allow_redirects=allow_redirects,
raise_exception=raise_exception,
**kwargs)
if response is not None and auto_close:
return AutoCloseResponse(response)
return response
@staticmethod
def cookie_parse(cookies_str: str, array: bool = False) -> Union[list, dict]: