From bc5e835f78598d21358de8a01238d80a66f58c5d Mon Sep 17 00:00:00 2001 From: Eason Date: Sun, 12 Mar 2023 19:38:59 +0800 Subject: [PATCH] feat: support linux command line proxy standard (#308) * feat: support linux command line proxy standard with env HTTPS_PROXY and ALL_PROXY * chore: update docs for linux command linux proxy standard --- README.en.md | 6 ++++++ README.md | 6 ++++++ docker-compose/docker-compose.yml | 2 ++ service/.env.example | 3 +++ service/package.json | 1 + service/pnpm-lock.yaml | 12 ++++++++++++ service/src/chatgpt/index.ts | 20 ++++++++++++++++++++ service/src/types.ts | 1 + src/components/common/Setting/About.vue | 2 ++ src/locales/en-US.ts | 1 + src/locales/zh-CN.ts | 1 + 11 files changed, 55 insertions(+) diff --git a/README.en.md b/README.en.md index db9044935d..e764c7ca28 100644 --- a/README.en.md +++ b/README.en.md @@ -174,6 +174,8 @@ pnpm dev - `TIMEOUT_MS` timeout, in milliseconds, optional - `SOCKS_PROXY_HOST` optional, effective with SOCKS_PROXY_PORT - `SOCKS_PROXY_PORT` optional, effective with SOCKS_PROXY_HOST +- `HTTPS_PROXY` optional, support http,https, socks5 +- `ALL_PROXY` optional, support http,https, socks5 ![docker](./docs/docker.png) @@ -223,6 +225,8 @@ services: SOCKS_PROXY_HOST: xxxx # socks proxy port, optional, effective with SOCKS_PROXY_HOST SOCKS_PROXY_PORT: xxxx + # HTTPS Proxy,optional, support http, https, socks5 + HTTPS_PROXY: http://xxx:7890 ``` The `OPENAI_API_BASE_URL` is optional and only used when setting the `OPENAI_API_KEY`. The `OPENAI_API_MODEL` is optional and only used when setting the `OPENAI_API_KEY`. @@ -245,6 +249,8 @@ The `OPENAI_API_MODEL` is optional and only used when setting the `OPENAI_API_KE | `API_REVERSE_PROXY` | Optional, only for `Web API` | Reverse proxy address for `Web API`. [Details](https://github.com/transitive-bullshit/chatgpt-api#reverse-proxy) | | `SOCKS_PROXY_HOST` | Optional, effective with `SOCKS_PROXY_PORT` | Socks proxy. | | `SOCKS_PROXY_PORT` | Optional, effective with `SOCKS_PROXY_HOST` | Socks proxy port. | +| `HTTPS_PROXY` | Optional | HTTPS Proxy. | +| `ALL_PROXY` | Optional | ALL Proxy. | > Note: Changing environment variables in Railway will cause re-deployment. diff --git a/README.md b/README.md index 47797786f7..1d5da22cf8 100644 --- a/README.md +++ b/README.md @@ -178,6 +178,8 @@ pnpm dev - `TIMEOUT_MS` 超时,单位毫秒,可选 - `SOCKS_PROXY_HOST` 可选,和 SOCKS_PROXY_PORT 一起时生效 - `SOCKS_PROXY_PORT` 可选,和 SOCKS_PROXY_HOST 一起时生效 +- `HTTPS_PROXY` 可选,支持 http,https, socks5 +- `ALL_PROXY` 可选,支持 http,https, socks5 ![docker](./docs/docker.png) @@ -227,6 +229,8 @@ services: SOCKS_PROXY_HOST: xxxx # Socks代理端口,可选,和 SOCKS_PROXY_HOST 一起时生效 SOCKS_PROXY_PORT: xxxx + # HTTPS 代理,可选,支持 http,https,socks5 + HTTPS_PROXY: http://xxxx:7890 ``` - `OPENAI_API_BASE_URL` 可选,设置 `OPENAI_API_KEY` 时可用 - `OPENAI_API_MODEL` 可选,设置 `OPENAI_API_KEY` 时可用 @@ -248,6 +252,8 @@ services: | `API_REVERSE_PROXY` | 可选,`Web API` 时可用 | `Web API` 反向代理地址 [详情](https://github.com/transitive-bullshit/chatgpt-api#reverse-proxy) | | `SOCKS_PROXY_HOST` | 可选,和 `SOCKS_PROXY_PORT` 一起时生效 | Socks代理 | | `SOCKS_PROXY_PORT` | 可选,和 `SOCKS_PROXY_HOST` 一起时生效 | Socks代理端口 | +| `HTTPS_PROXY` | 可选 | HTTPS 代理,支持 http,https, socks5 | +| `ALL_PROXY` | 可选 | 所有代理 代理,支持 http,https, socks5 | > 注意: `Railway` 修改环境变量会重新 `Deploy` diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml index f6082eddb4..91dee3c0a8 100644 --- a/docker-compose/docker-compose.yml +++ b/docker-compose/docker-compose.yml @@ -24,6 +24,8 @@ services: SOCKS_PROXY_HOST: xxxx # Socks代理端口,可选,和 SOCKS_PROXY_HOST 一起时生效 SOCKS_PROXY_PORT: xxxx + # HTTPS_PROXY 代理,可选 + HTTPS_PROXY: http://xxxx:7890 nginx: image: nginx:alpine ports: diff --git a/service/.env.example b/service/.env.example index 43fe3a616c..7ca4a4db2d 100644 --- a/service/.env.example +++ b/service/.env.example @@ -24,3 +24,6 @@ SOCKS_PROXY_HOST= # Socks Proxy Port SOCKS_PROXY_PORT= + +# HTTPS PROXY +HTTPS_PROXY= diff --git a/service/package.json b/service/package.json index 5a735dd5f8..904a23881b 100644 --- a/service/package.json +++ b/service/package.json @@ -28,6 +28,7 @@ "dotenv": "^16.0.3", "esno": "^0.16.3", "express": "^4.18.2", + "https-proxy-agent": "^5.0.1", "isomorphic-fetch": "^3.0.0", "node-fetch": "^3.3.0", "socks-proxy-agent": "^7.0.0" diff --git a/service/pnpm-lock.yaml b/service/pnpm-lock.yaml index a27fef4e58..6a724a1d56 100644 --- a/service/pnpm-lock.yaml +++ b/service/pnpm-lock.yaml @@ -9,6 +9,7 @@ specifiers: eslint: ^8.35.0 esno: ^0.16.3 express: ^4.18.2 + https-proxy-agent: ^5.0.1 isomorphic-fetch: ^3.0.0 node-fetch: ^3.3.0 rimraf: ^4.3.0 @@ -21,6 +22,7 @@ dependencies: dotenv: 16.0.3 esno: 0.16.3 express: 4.18.2 + https-proxy-agent: 5.0.1 isomorphic-fetch: 3.0.0 node-fetch: 3.3.0 socks-proxy-agent: 7.0.0 @@ -2079,6 +2081,16 @@ packages: toidentifier: 1.0.1 dev: false + /https-proxy-agent/5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /human-signals/2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} diff --git a/service/src/chatgpt/index.ts b/service/src/chatgpt/index.ts index 9ddebafd63..85d98e73f7 100644 --- a/service/src/chatgpt/index.ts +++ b/service/src/chatgpt/index.ts @@ -3,6 +3,7 @@ import 'isomorphic-fetch' import type { ChatGPTAPIOptions, ChatMessage, SendMessageOptions } from 'chatgpt' import { ChatGPTAPI, ChatGPTUnofficialProxyAPI } from 'chatgpt' import { SocksProxyAgent } from 'socks-proxy-agent' +import { HttpsProxyAgent } from 'https-proxy-agent' import fetch from 'node-fetch' import { sendResponse } from '../utils' import type { ApiModel, ChatContext, ChatGPTUnofficialProxyAPIOptions, ModelConfig } from '../types' @@ -55,6 +56,14 @@ let api: ChatGPTAPI | ChatGPTUnofficialProxyAPI } } + const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.ALL_PROXY || process.env.all_proxy + if (httpsProxy) { + const agent = new HttpsProxyAgent(httpsProxy) + options.fetch = (url, options) => { + return fetch(url, { agent, ...options }) + } + } + api = new ChatGPTAPI({ ...options }) apiModel = 'ChatGPTAPI' } @@ -74,6 +83,14 @@ let api: ChatGPTAPI | ChatGPTUnofficialProxyAPI } } + const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.ALL_PROXY || process.env.all_proxy + if (httpsProxy) { + const agent = new HttpsProxyAgent(httpsProxy) + options.fetch = (url, options) => { + return fetch(url, { agent, ...options }) + } + } + if (process.env.API_REVERSE_PROXY) options.apiReverseProxyUrl = process.env.API_REVERSE_PROXY @@ -119,6 +136,8 @@ async function chatReplyProcess( } async function chatConfig() { + const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.ALL_PROXY || process.env.all_proxy + return sendResponse({ type: 'Success', data: { @@ -126,6 +145,7 @@ async function chatConfig() { reverseProxy: process.env.API_REVERSE_PROXY, timeoutMs, socksProxy: (process.env.SOCKS_PROXY_HOST && process.env.SOCKS_PROXY_PORT) ? (`${process.env.SOCKS_PROXY_HOST}:${process.env.SOCKS_PROXY_PORT}`) : '-', + httpsProxy, } as ModelConfig, }) } diff --git a/service/src/types.ts b/service/src/types.ts index dcade0c047..995894cd4c 100644 --- a/service/src/types.ts +++ b/service/src/types.ts @@ -19,6 +19,7 @@ export interface ModelConfig { reverseProxy?: string timeoutMs?: number socksProxy?: string + httpsProxy?: string } export type ApiModel = 'ChatGPTAPI' | 'ChatGPTUnofficialProxyAPI' | undefined diff --git a/src/components/common/Setting/About.vue b/src/components/common/Setting/About.vue index d585e5ea23..e6d503aa52 100644 --- a/src/components/common/Setting/About.vue +++ b/src/components/common/Setting/About.vue @@ -9,6 +9,7 @@ interface ConfigState { reverseProxy?: string apiModel?: string socksProxy?: string + httpsProxy?: string } const loading = ref(false) @@ -57,6 +58,7 @@ onMounted(() => {

{{ $t("setting.reverseProxy") }}:{{ config?.reverseProxy ?? '-' }}

{{ $t("setting.timeout") }}:{{ config?.timeoutMs ?? '-' }}

{{ $t("setting.socks") }}:{{ config?.socksProxy ?? '-' }}

+

{{ $t("setting.httpsProxy") }}:{{ config?.httpsProxy ?? '-' }}

diff --git a/src/locales/en-US.ts b/src/locales/en-US.ts index e8b470b080..e64eaca8ee 100644 --- a/src/locales/en-US.ts +++ b/src/locales/en-US.ts @@ -50,6 +50,7 @@ export default { reverseProxy: 'Reverse Proxy', timeout: 'Timeout', socks: 'Socks', + httpsProxy: 'HTTPS Proxy', }, } diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index a0cb26b4d7..8ee0e648d5 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -50,6 +50,7 @@ export default { reverseProxy: '反向代理', timeout: '超时', socks: 'Socks', + httpsProxy: 'HTTPS Proxy', }, }