🔖 chore: add chat image request proxy address

This commit is contained in:
MartialBE 2024-05-29 04:01:28 +08:00
parent 3d8a51e139
commit b5a4283b28
No known key found for this signature in database
GPG Key ID: 27C0267EC84B0A5C
11 changed files with 76 additions and 53 deletions

View File

@ -69,6 +69,8 @@ var SMTPAccount = ""
var SMTPFrom = "" var SMTPFrom = ""
var SMTPToken = "" var SMTPToken = ""
var ChatImageRequestProxy = ""
var GitHubClientId = "" var GitHubClientId = ""
var GitHubClientSecret = "" var GitHubClientSecret = ""

26
common/image/http.go Normal file
View File

@ -0,0 +1,26 @@
package image
import (
"net/http"
"one-api/common/config"
"one-api/common/utils"
"time"
)
var ImageHttpClients = &http.Client{
Transport: &http.Transport{
DialContext: utils.Socks5ProxyFunc,
Proxy: utils.ProxyFunc,
},
Timeout: 15 * time.Second,
}
func requestImage(url, method string) (*http.Response, error) {
res, err := utils.RequestBuilder(utils.SetProxy(config.ChatImageRequestProxy, nil), method, url, nil, nil)
if err != nil {
return nil, err
}
return ImageHttpClients.Do(res)
}

View File

@ -16,17 +16,8 @@ import (
_ "golang.org/x/image/webp" _ "golang.org/x/image/webp"
) )
// var ImageHttpClients = &http.Client{
// Transport: &http.Transport{
// DialContext: requester.Socks5ProxyFunc,
// Proxy: requester.ProxyFunc,
// },
// //
// // // Timeout: 30 * time.Second,
// }
func IsImageUrl(url string) (bool, error) { func IsImageUrl(url string) (bool, error) {
resp, err := http.Head(url) resp, err := requestImage(url, http.MethodHead)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -41,7 +32,7 @@ func GetImageSizeFromUrl(url string) (width int, height int, err error) {
if !isImage { if !isImage {
return return
} }
resp, err := http.Get(url) resp, err := requestImage(url, http.MethodGet)
if err != nil { if err != nil {
return return
} }
@ -126,6 +117,6 @@ func GetImageSize(image string) (width int, height int, err error) {
case strings.HasPrefix(image, "http"): case strings.HasPrefix(image, "http"):
return GetImageSizeFromUrl(image) return GetImageSizeFromUrl(image)
default: default:
return 0, 0, errors.New("invalid file type, Please view request interface!") return 0, 0, errors.New("invalid file type, please view request interface")
} }
} }

View File

@ -20,7 +20,7 @@ import (
type HttpErrorHandler func(*http.Response) *types.OpenAIError type HttpErrorHandler func(*http.Response) *types.OpenAIError
type HTTPRequester struct { type HTTPRequester struct {
requestBuilder RequestBuilder // requestBuilder utils.RequestBuilder
CreateFormBuilder func(io.Writer) FormBuilder CreateFormBuilder func(io.Writer) FormBuilder
ErrorHandler HttpErrorHandler ErrorHandler HttpErrorHandler
proxyAddr string proxyAddr string
@ -34,7 +34,6 @@ type HTTPRequester struct {
// 如果 errorHandler 为 nil那么会使用一个默认的错误处理函数。 // 如果 errorHandler 为 nil那么会使用一个默认的错误处理函数。
func NewHTTPRequester(proxyAddr string, errorHandler HttpErrorHandler) *HTTPRequester { func NewHTTPRequester(proxyAddr string, errorHandler HttpErrorHandler) *HTTPRequester {
return &HTTPRequester{ return &HTTPRequester{
requestBuilder: NewRequestBuilder(),
CreateFormBuilder: func(body io.Writer) FormBuilder { CreateFormBuilder: func(body io.Writer) FormBuilder {
return NewFormBuilder(body) return NewFormBuilder(body)
}, },
@ -53,7 +52,7 @@ type requestOptions struct {
type requestOption func(*requestOptions) type requestOption func(*requestOptions)
func (r *HTTPRequester) setProxy() context.Context { func (r *HTTPRequester) setProxy() context.Context {
return utils.SetProxy(r.Context, r.proxyAddr) return utils.SetProxy(r.proxyAddr, r.Context)
} }
// 创建请求 // 创建请求
@ -65,7 +64,7 @@ func (r *HTTPRequester) NewRequest(method, url string, setters ...requestOption)
for _, setter := range setters { for _, setter := range setters {
setter(args) setter(args)
} }
req, err := r.requestBuilder.Build(r.setProxy(), method, url, args.body, args.header) req, err := utils.RequestBuilder(r.setProxy(), method, url, args.body, args.header)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,15 +0,0 @@
package requester
import (
"encoding/json"
)
type Marshaller interface {
Marshal(value any) ([]byte, error)
}
type JSONMarshaller struct{}
func (jm *JSONMarshaller) Marshal(value any) ([]byte, error) {
return json.Marshal(value)
}

View File

@ -60,7 +60,11 @@ func Socks5ProxyFunc(ctx context.Context, network, addr string) (net.Conn, error
return proxyDialer.Dial(network, addr) return proxyDialer.Dial(network, addr)
} }
func SetProxy(ctx context.Context, proxyAddr string) context.Context { func SetProxy(proxyAddr string, ctx context.Context) context.Context {
if ctx == nil {
ctx = context.Background()
}
if proxyAddr == "" { if proxyAddr == "" {
return ctx return ctx
} }

View File

@ -1,27 +1,14 @@
package requester package utils
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/json"
"io" "io"
"net/http" "net/http"
) )
type RequestBuilder interface { func RequestBuilder(
Build(ctx context.Context, method, url string, body any, header http.Header) (*http.Request, error)
}
type HTTPRequestBuilder struct {
marshaller Marshaller
}
func NewRequestBuilder() *HTTPRequestBuilder {
return &HTTPRequestBuilder{
marshaller: &JSONMarshaller{},
}
}
func (b *HTTPRequestBuilder) Build(
ctx context.Context, ctx context.Context,
method string, method string,
url string, url string,
@ -34,7 +21,7 @@ func (b *HTTPRequestBuilder) Build(
bodyReader = v bodyReader = v
} else { } else {
var reqBytes []byte var reqBytes []byte
reqBytes, err = b.marshaller.Marshal(body) reqBytes, err = json.Marshal(body)
if err != nil { if err != nil {
return return
} }

2
go.mod
View File

@ -13,6 +13,7 @@ require (
github.com/gin-contrib/static v1.1.0 github.com/gin-contrib/static v1.1.0
github.com/gin-gonic/gin v1.9.1 github.com/gin-gonic/gin v1.9.1
github.com/go-co-op/gocron/v2 v2.2.9 github.com/go-co-op/gocron/v2 v2.2.9
github.com/go-gormigrate/gormigrate/v2 v2.1.2
github.com/go-playground/validator/v10 v10.19.0 github.com/go-playground/validator/v10 v10.19.0
github.com/go-redis/redis/v8 v8.11.5 github.com/go-redis/redis/v8 v8.11.5
github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang-jwt/jwt v3.2.2+incompatible
@ -35,7 +36,6 @@ require (
filippo.io/edwards25519 v1.1.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-gormigrate/gormigrate/v2 v2.1.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect github.com/jonboulle/clockwork v0.4.0 // indirect

View File

@ -16,8 +16,7 @@ type Option struct {
func AllOption() ([]*Option, error) { func AllOption() ([]*Option, error) {
var options []*Option var options []*Option
var err error err := DB.Find(&options).Error
err = DB.Find(&options).Error
return options, err return options, err
} }
@ -83,6 +82,8 @@ func InitOptionMap() {
config.OptionMap["ChatCacheEnabled"] = strconv.FormatBool(config.ChatCacheEnabled) config.OptionMap["ChatCacheEnabled"] = strconv.FormatBool(config.ChatCacheEnabled)
config.OptionMap["ChatCacheExpireMinute"] = strconv.Itoa(config.ChatCacheExpireMinute) config.OptionMap["ChatCacheExpireMinute"] = strconv.Itoa(config.ChatCacheExpireMinute)
config.OptionMap["ChatImageRequestProxy"] = ""
config.OptionMapRWMutex.Unlock() config.OptionMapRWMutex.Unlock()
loadOptionsFromDatabase() loadOptionsFromDatabase()
} }
@ -174,6 +175,7 @@ var optionStringMap = map[string]*string{
"ChatLinks": &config.ChatLinks, "ChatLinks": &config.ChatLinks,
"LarkClientId": &config.LarkClientId, "LarkClientId": &config.LarkClientId,
"LarkClientSecret": &config.LarkClientSecret, "LarkClientSecret": &config.LarkClientSecret,
"ChatImageRequestProxy": &config.ChatImageRequestProxy,
} }
func updateOptionMap(key string, value string) (err error) { func updateOptionMap(key string, value string) (err error) {

View File

@ -35,7 +35,8 @@ const OperationSetting = () => {
RetryCooldownSeconds: 0, RetryCooldownSeconds: 0,
MjNotifyEnabled: '', MjNotifyEnabled: '',
ChatCacheEnabled: '', ChatCacheEnabled: '',
ChatCacheExpireMinute: 5 ChatCacheExpireMinute: 5,
ChatImageRequestProxy: ''
}); });
const [originInputs, setOriginInputs] = useState({}); const [originInputs, setOriginInputs] = useState({});
let [loading, setLoading] = useState(false); let [loading, setLoading] = useState(false);
@ -173,6 +174,9 @@ const OperationSetting = () => {
if (originInputs['ChatCacheExpireMinute'] !== inputs.ChatCacheExpireMinute) { if (originInputs['ChatCacheExpireMinute'] !== inputs.ChatCacheExpireMinute) {
await updateOption('ChatCacheExpireMinute', inputs.ChatCacheExpireMinute); await updateOption('ChatCacheExpireMinute', inputs.ChatCacheExpireMinute);
} }
if (originInputs['ChatImageRequestProxy'] !== inputs.ChatImageRequestProxy) {
await updateOption('ChatImageRequestProxy', inputs.ChatImageRequestProxy);
}
break; break;
} }
@ -334,6 +338,26 @@ const OperationSetting = () => {
/> />
</FormControl> </FormControl>
</Stack> </Stack>
<Stack spacing={2}>
<Alert severity="info">
当用户使用vision模型并提供了图片链接时我们的服务器需要下载这些图片并计算 tokens为了在下载图片时保护服务器的 IP
地址不被泄露可以在下方配置一个代理这个代理配置使用的是 HTTP SOCKS5
代理如果你是个人用户这个配置可以不用理会代理格式为 http://127.0.0.1:1080 或 socks5://127.0.0.1:1080
</Alert>
<FormControl>
<InputLabel htmlFor="ChatImageRequestProxy">图片检测代理</InputLabel>
<OutlinedInput
id="ChatImageRequestProxy"
name="ChatImageRequestProxy"
value={inputs.ChatImageRequestProxy}
onChange={handleInputChange}
label="图片检测代理"
placeholder="聊天图片检测代理设置如果不设置可能会泄漏服务器ip"
disabled={loading}
/>
</FormControl>
</Stack>
<Button <Button
variant="contained" variant="contained"
onClick={() => { onClick={() => {

View File

@ -376,6 +376,9 @@ const SystemSetting = () => {
</SubCard> </SubCard>
<SubCard title="配置 SMTP" subTitle="用以支持系统的邮件发送"> <SubCard title="配置 SMTP" subTitle="用以支持系统的邮件发送">
<Grid container spacing={{ xs: 3, sm: 2, md: 4 }}> <Grid container spacing={{ xs: 3, sm: 2, md: 4 }}>
<Grid xs={12}>
<Alert severity="info">请注意有些邮箱服务商发送邮件时会携带你的服务器IP地址非个人使用时建议使用专业的邮件服务商</Alert>
</Grid>
<Grid xs={12} md={4}> <Grid xs={12} md={4}>
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel htmlFor="SMTPServer">SMTP 服务器地址</InputLabel> <InputLabel htmlFor="SMTPServer">SMTP 服务器地址</InputLabel>