diff --git a/constant/channel_setting.go b/constant/channel_setting.go index 71b9f58b..6eccfb84 100644 --- a/constant/channel_setting.go +++ b/constant/channel_setting.go @@ -1,5 +1,6 @@ package constant var ( - ForceFormat = "force_format" // ForceFormat 强制格式化为OpenAI格式 + ForceFormat = "force_format" // ForceFormat 强制格式化为OpenAI格式 + ChanelSettingProxy = "proxy" // Proxy 代理 ) diff --git a/docs/channel/orher_setting.md b/docs/channel/orher_setting.md new file mode 100644 index 00000000..775da557 --- /dev/null +++ b/docs/channel/orher_setting.md @@ -0,0 +1,28 @@ +# 渠道而外设置说明 + +该配置用于设置一些额外的渠道参数,可以通过 JSON 对象进行配置。主要包含以下两个设置项: + +1. force_format + - 用于标识是否对数据进行强制格式化为 OpenAI 格式 + - 类型为布尔值,设置为 true 时启用强制格式化 + +2. proxy + - 用于配置网络代理 + - 类型为字符串,填写代理地址(例如 socks5 协议的代理地址) + +-------------------------------------------------------------- + +## JSON 格式示例 + +以下是一个示例配置,启用强制格式化并设置了代理地址: + +```json +{ + "force_format": true, + "proxy": "socks5://xxxxxxx" +} +``` + +-------------------------------------------------------------- + +通过调整上述 JSON 配置中的值,可以灵活控制渠道的额外行为,比如是否进行格式化以及使用特定的网络代理。 \ No newline at end of file diff --git a/relay/channel/api_request.go b/relay/channel/api_request.go index 8b51c535..cd1b5153 100644 --- a/relay/channel/api_request.go +++ b/relay/channel/api_request.go @@ -39,7 +39,7 @@ func DoApiRequest(a Adaptor, c *gin.Context, info *common.RelayInfo, requestBody if err != nil { return nil, fmt.Errorf("setup request header failed: %w", err) } - resp, err := doRequest(c, req) + resp, err := doRequest(c, req, info) if err != nil { return nil, fmt.Errorf("do request failed: %w", err) } @@ -62,7 +62,7 @@ func DoFormRequest(a Adaptor, c *gin.Context, info *common.RelayInfo, requestBod if err != nil { return nil, fmt.Errorf("setup request header failed: %w", err) } - resp, err := doRequest(c, req) + resp, err := doRequest(c, req, info) if err != nil { return nil, fmt.Errorf("do request failed: %w", err) } @@ -90,8 +90,18 @@ func DoWssRequest(a Adaptor, c *gin.Context, info *common.RelayInfo, requestBody return targetConn, nil } -func doRequest(c *gin.Context, req *http.Request) (*http.Response, error) { - resp, err := service.GetHttpClient().Do(req) +func doRequest(c *gin.Context, req *http.Request, info *common.RelayInfo) (*http.Response, error) { + var client *http.Client + var err error + if proxyURL, ok := info.ChannelSetting["proxy"]; ok { + client, err = service.NewProxyHttpClient(proxyURL.(string)) + if err != nil { + return nil, fmt.Errorf("new proxy http client failed: %w", err) + } + } else { + client = service.GetHttpClient() + } + resp, err := client.Do(req) if err != nil { return nil, err } @@ -120,7 +130,7 @@ func DoTaskApiRequest(a TaskAdaptor, c *gin.Context, info *common.TaskRelayInfo, if err != nil { return nil, fmt.Errorf("setup request header failed: %w", err) } - resp, err := doRequest(c, req) + resp, err := doRequest(c, req, info.ToRelayInfo()) if err != nil { return nil, fmt.Errorf("do request failed: %w", err) } diff --git a/service/http_client.go b/service/http_client.go index df920bd6..992c73a0 100644 --- a/service/http_client.go +++ b/service/http_client.go @@ -1,7 +1,12 @@ package service import ( + "context" + "fmt" + "golang.org/x/net/proxy" + "net" "net/http" + "net/url" "one-api/common" "time" ) @@ -30,3 +35,43 @@ func GetHttpClient() *http.Client { func GetImpatientHttpClient() *http.Client { return impatientHTTPClient } + +// NewProxyHttpClient 创建支持代理的 HTTP 客户端 +func NewProxyHttpClient(proxyURL string) (*http.Client, error) { + if proxyURL == "" { + return http.DefaultClient, nil + } + + // 解析代理URL + parsedURL, err := url.Parse(proxyURL) + if err != nil { + return nil, err + } + + switch parsedURL.Scheme { + case "http", "https": + return &http.Client{ + Transport: &http.Transport{ + Proxy: http.ProxyURL(parsedURL), + }, + }, nil + + case "socks5": + // 创建 SOCKS5 代理拨号器 + dialer, err := proxy.SOCKS5("tcp", parsedURL.Host, nil, proxy.Direct) + if err != nil { + return nil, err + } + + return &http.Client{ + Transport: &http.Transport{ + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + return dialer.Dial(network, addr) + }, + }, + }, nil + + default: + return nil, fmt.Errorf("unsupported proxy scheme: %s", parsedURL.Scheme) + } +} diff --git a/web/src/pages/Channel/EditChannel.js b/web/src/pages/Channel/EditChannel.js index 6f576344..40f8b8eb 100644 --- a/web/src/pages/Channel/EditChannel.js +++ b/web/src/pages/Channel/EditChannel.js @@ -966,7 +966,6 @@ const EditChannel = (props) => { value={inputs.weight} autoComplete="new-password" /> - {inputs.type === 8 && ( <>
@@ -999,9 +998,8 @@ const EditChannel = (props) => { }} > {t('填入模板')} - - - )} + +