feat: 迁移 geekai-plus v4.3.1 到开源版

- 同步 Plus v4.3.1 功能源并移除商业 License 闭环
- 更新开源镜像命名、Docker 部署版本和 geekai 数据库配置
- 补充前端 ESLint 检查配置并修复存量解析与模板问题
- 保留 JWT、管理员权限、API Key 和 OAuth 等正常鉴权机制
This commit is contained in:
RockYang
2026-09-13 14:37:12 +08:00
parent 3e66c5ac5b
commit d4fd38ab7e
96 changed files with 7164 additions and 3047 deletions
+76
View File
@@ -8,6 +8,7 @@ package utils
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
import (
"bytes"
"context"
"encoding/json"
"errors"
@@ -177,6 +178,81 @@ func FetchURLBytes(ctx context.Context, rawURL string, proxy string, timeout tim
return nil, 0, lastErr
}
// PostURLBytes 发起 POST(如 application/json)并返回响应体(只在 2xx 认为成功)。
func PostURLBytes(ctx context.Context, rawURL string, contentType string, body []byte, proxy string, timeout time.Duration, retries int, maxBytes int64) ([]byte, int, error) {
if ctx == nil {
ctx = context.Background()
}
if timeout <= 0 {
timeout = defaultHTTPTimeout
}
if retries < 0 {
retries = 0
}
if maxBytes <= 0 {
maxBytes = 8 << 20
}
if contentType == "" {
contentType = "application/json"
}
var lastErr error
for attempt := 0; attempt <= retries; attempt++ {
if ctx.Err() != nil {
return nil, 0, ctx.Err()
}
client := newHTTPClient(timeout, proxy)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, rawURL, bytes.NewReader(body))
if err != nil {
return nil, 0, err
}
req.Header.Set("Content-Type", contentType)
resp, err := client.Do(req)
if err != nil {
lastErr = err
if attempt < retries && isRetryableError(err) {
time.Sleep(retryDelay(attempt))
continue
}
return nil, 0, err
}
respBody, readErr := readAllLimit(resp.Body, maxBytes)
_ = resp.Body.Close()
if readErr != nil {
lastErr = readErr
if attempt < retries && isRetryableError(readErr) {
time.Sleep(retryDelay(attempt))
continue
}
return nil, resp.StatusCode, readErr
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
status := resp.StatusCode
lastErr = fmt.Errorf("request failed: status=%d", status)
if attempt < retries && (status == http.StatusTooManyRequests || status >= 500 && status <= 599) {
time.Sleep(retryDelay(attempt))
continue
}
preview := strings.TrimSpace(string(respBody))
if len(preview) > 256 {
preview = preview[:256]
}
if preview != "" {
return respBody, status, fmt.Errorf("request failed: status=%d body=%s", status, preview)
}
return respBody, status, lastErr
}
return respBody, resp.StatusCode, nil
}
return nil, 0, lastErr
}
// SendMsg 回复客户片段端消息
func SendMsg(client *types.WsClient, message types.ReplyMessage) {
message.ClientId = client.Id