✨ Feature: Add feature: Support socks5 proxy
Browse files- README.md +1 -0
- README_CN.md +1 -0
- main.py +54 -7
- requirements.txt +1 -0
README.md
CHANGED
@@ -101,6 +101,7 @@ providers:
|
|
101 |
gemini-1.5-pro: 10 # Model gemini-1.5-pro timeout is 10 seconds
|
102 |
gemini-1.5-flash: 10 # Model gemini-1.5-flash timeout is 10 seconds
|
103 |
default: 10 # Model does not have a timeout set, use the default timeout of 10 seconds, when requesting a model not in model_timeout, the timeout is also 10 seconds, if default is not set, uni-api will use the default timeout set by the environment variable TIMEOUT, the default timeout is 100 seconds
|
|
|
104 |
|
105 |
- provider: vertex
|
106 |
project_id: gen-lang-client-xxxxxxxxxxxxxx # Description: Your Google Cloud project ID. Format: String, usually composed of lowercase letters, numbers, and hyphens. How to obtain: You can find your project ID in the project selector of the Google Cloud Console.
|
|
|
101 |
gemini-1.5-pro: 10 # Model gemini-1.5-pro timeout is 10 seconds
|
102 |
gemini-1.5-flash: 10 # Model gemini-1.5-flash timeout is 10 seconds
|
103 |
default: 10 # Model does not have a timeout set, use the default timeout of 10 seconds, when requesting a model not in model_timeout, the timeout is also 10 seconds, if default is not set, uni-api will use the default timeout set by the environment variable TIMEOUT, the default timeout is 100 seconds
|
104 |
+
proxy: socks5://[username]:[password]@[ip]:[port] # Proxy address, optional. Supports socks5 and http proxies, default is not used.
|
105 |
|
106 |
- provider: vertex
|
107 |
project_id: gen-lang-client-xxxxxxxxxxxxxx # Description: Your Google Cloud project ID. Format: String, usually composed of lowercase letters, numbers, and hyphens. How to obtain: You can find your project ID in the project selector of the Google Cloud Console.
|
README_CN.md
CHANGED
@@ -101,6 +101,7 @@ providers:
|
|
101 |
gemini-1.5-pro: 10 # 模型 gemini-1.5-pro 的超时时间为 10 秒
|
102 |
gemini-1.5-flash: 10 # 模型 gemini-1.5-flash 的超时时间为 10 秒
|
103 |
default: 10 # 模型没有设置超时时间,使用默认的超时时间 10 秒,当请求的不在 model_timeout 里面的模型时,超时时间默认是 10 秒,不设置 default,uni-api 会使用全局配置的模型超时时间。
|
|
|
104 |
|
105 |
- provider: vertex
|
106 |
project_id: gen-lang-client-xxxxxxxxxxxxxx # 描述: 您的Google Cloud项目ID。格式: 字符串,通常由小写字母、数字和连字符组成。获取方式: 在Google Cloud Console的项目选择器中可以找到您的项目ID。
|
|
|
101 |
gemini-1.5-pro: 10 # 模型 gemini-1.5-pro 的超时时间为 10 秒
|
102 |
gemini-1.5-flash: 10 # 模型 gemini-1.5-flash 的超时时间为 10 秒
|
103 |
default: 10 # 模型没有设置超时时间,使用默认的超时时间 10 秒,当请求的不在 model_timeout 里面的模型时,超时时间默认是 10 秒,不设置 default,uni-api 会使用全局配置的模型超时时间。
|
104 |
+
proxy: socks5://[用户名]:[密码]@[IP地址]:[端口] # 代理地址,选填。支持 socks5 和 http 代理,默认不使用代理。
|
105 |
|
106 |
- provider: vertex
|
107 |
project_id: gen-lang-client-xxxxxxxxxxxxxx # 描述: 您的Google Cloud项目ID。格式: 字符串,通常由小写字母、数字和连字符组成。获取方式: 在Google Cloud Console的项目选择器中可以找到您的项目ID。
|
main.py
CHANGED
@@ -600,7 +600,7 @@ class ClientManager:
|
|
600 |
self.default_config = default_config
|
601 |
|
602 |
@asynccontextmanager
|
603 |
-
async def get_client(self, timeout_value):
|
604 |
# 直接获取或创建客户端,不使用锁
|
605 |
timeout_value = int(timeout_value)
|
606 |
if timeout_value not in self.clients:
|
@@ -610,11 +610,42 @@ class ClientManager:
|
|
610 |
write=30.0,
|
611 |
pool=self.pool_size
|
612 |
)
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
**self.default_config
|
617 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
618 |
|
619 |
try:
|
620 |
yield self.clients[timeout_value]
|
@@ -795,8 +826,24 @@ async def process_request(request: Union[RequestModel, ImageGenerationRequest, A
|
|
795 |
timeout_value = app.state.timeouts.get("default", DEFAULT_TIMEOUT)
|
796 |
# print("timeout_value", timeout_value)
|
797 |
|
|
|
|
|
|
|
798 |
try:
|
799 |
-
async with app.state.client_manager.get_client(timeout_value) as client:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
800 |
if request.stream:
|
801 |
generator = fetch_response_stream(client, url, headers, payload, engine, original_model)
|
802 |
wrapped_generator, first_response_time = await error_handling_wrapper(generator, channel_id)
|
|
|
600 |
self.default_config = default_config
|
601 |
|
602 |
@asynccontextmanager
|
603 |
+
async def get_client(self, timeout_value, proxy=None):
|
604 |
# 直接获取或创建客户端,不使用锁
|
605 |
timeout_value = int(timeout_value)
|
606 |
if timeout_value not in self.clients:
|
|
|
610 |
write=30.0,
|
611 |
pool=self.pool_size
|
612 |
)
|
613 |
+
limits = httpx.Limits(max_connections=self.pool_size)
|
614 |
+
|
615 |
+
client_config = {
|
616 |
+
**self.default_config,
|
617 |
+
"timeout": timeout,
|
618 |
+
"limits": limits
|
619 |
+
}
|
620 |
+
|
621 |
+
if proxy:
|
622 |
+
# 解析代理URL
|
623 |
+
from urllib.parse import urlparse
|
624 |
+
parsed = urlparse(proxy)
|
625 |
+
|
626 |
+
# 修改这里: 将 socks5h 转换为 socks5
|
627 |
+
scheme = parsed.scheme.rstrip('h')
|
628 |
+
# print("scheme", scheme)
|
629 |
+
|
630 |
+
if scheme == 'socks5':
|
631 |
+
try:
|
632 |
+
from httpx_socks import AsyncProxyTransport
|
633 |
+
# 使用修改后的scheme创建代理URL
|
634 |
+
proxy = proxy.replace('socks5h://', 'socks5://')
|
635 |
+
# 创建SOCKS5代理传输
|
636 |
+
transport = AsyncProxyTransport.from_url(proxy)
|
637 |
+
client_config["transport"] = transport
|
638 |
+
except ImportError:
|
639 |
+
logger.error("httpx-socks package is required for SOCKS proxy support")
|
640 |
+
raise ImportError("Please install httpx-socks package for SOCKS proxy support: pip install httpx-socks")
|
641 |
+
else:
|
642 |
+
# 对于HTTP/HTTPS代理使用原有方式
|
643 |
+
client_config["proxies"] = {
|
644 |
+
"http://": proxy,
|
645 |
+
"https://": proxy
|
646 |
+
}
|
647 |
+
|
648 |
+
self.clients[timeout_value] = httpx.AsyncClient(**client_config)
|
649 |
|
650 |
try:
|
651 |
yield self.clients[timeout_value]
|
|
|
826 |
timeout_value = app.state.timeouts.get("default", DEFAULT_TIMEOUT)
|
827 |
# print("timeout_value", timeout_value)
|
828 |
|
829 |
+
proxy = safe_get(provider, "preferences", "proxy", default=None)
|
830 |
+
# print("proxy", proxy)
|
831 |
+
|
832 |
try:
|
833 |
+
async with app.state.client_manager.get_client(timeout_value, proxy) as client:
|
834 |
+
# 打印client配置信息
|
835 |
+
# logger.info(f"Client config - Timeout: {client.timeout}")
|
836 |
+
# logger.info(f"Client config - Headers: {client.headers}")
|
837 |
+
# if hasattr(client, '_transport'):
|
838 |
+
# if hasattr(client._transport, 'proxy_url'):
|
839 |
+
# logger.info(f"Client config - Proxy: {client._transport.proxy_url}")
|
840 |
+
# elif hasattr(client._transport, 'proxies'):
|
841 |
+
# logger.info(f"Client config - Proxies: {client._transport.proxies}")
|
842 |
+
# else:
|
843 |
+
# logger.info("Client config - No proxy configured")
|
844 |
+
# else:
|
845 |
+
# logger.info("Client config - No transport configured")
|
846 |
+
# logger.info(f"Client config - Follow Redirects: {client.follow_redirects}")
|
847 |
if request.stream:
|
848 |
generator = fetch_response_stream(client, url, headers, payload, engine, original_model)
|
849 |
wrapped_generator, first_response_time = await error_handling_wrapper(generator, channel_id)
|
requirements.txt
CHANGED
@@ -9,5 +9,6 @@ sqlalchemy
|
|
9 |
watchfiles
|
10 |
ruamel.yaml
|
11 |
httpx[http2]
|
|
|
12 |
cryptography
|
13 |
python-multipart
|
|
|
9 |
watchfiles
|
10 |
ruamel.yaml
|
11 |
httpx[http2]
|
12 |
+
httpx-socks
|
13 |
cryptography
|
14 |
python-multipart
|