test
This commit is contained in:
@@ -846,6 +846,7 @@ type RongxingConfig struct {
|
||||
AppID string `mapstructure:"app_id"` // 应用 ID
|
||||
PrivateKey string `mapstructure:"private_key"` // RSA 私钥(PEM 或 PKCS#8 Base64)
|
||||
Timeout time.Duration `mapstructure:"timeout"`
|
||||
Proxy string `mapstructure:"proxy"` // 可选,仅戎行请求走此代理,如 socks5://rongxing-vpn:1080
|
||||
|
||||
Logging RongxingLoggingConfig `mapstructure:"logging"`
|
||||
}
|
||||
|
||||
47
internal/infrastructure/external/rongxing/http_client_test.go
vendored
Normal file
47
internal/infrastructure/external/rongxing/http_client_test.go
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
package rongxing
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNewHTTPClient_Direct(t *testing.T) {
|
||||
client, err := newHTTPClient(5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if client.Timeout != 5*time.Second {
|
||||
t.Fatalf("timeout = %v", client.Timeout)
|
||||
}
|
||||
if client.Transport != nil && client.Transport != http.DefaultTransport {
|
||||
// 直连允许 Transport 为 nil(使用 DefaultTransport)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewHTTPClient_Socks5(t *testing.T) {
|
||||
client, err := newHTTPClient(3*time.Second, "socks5://rongxing-vpn:1080")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if client.Transport == nil {
|
||||
t.Fatal("expected custom transport for socks5")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewHTTPClient_HTTPProxy(t *testing.T) {
|
||||
client, err := newHTTPClient(3*time.Second, "http://127.0.0.1:8888")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if client.Transport == nil {
|
||||
t.Fatal("expected custom transport for http proxy")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewHTTPClient_UnsupportedScheme(t *testing.T) {
|
||||
_, err := newHTTPClient(time.Second, "ftp://x")
|
||||
if err == nil {
|
||||
t.Fatal("expected error for unsupported scheme")
|
||||
}
|
||||
}
|
||||
@@ -46,5 +46,6 @@ func NewRongxingServiceWithConfig(cfg *config.Config) (*RongxingService, error)
|
||||
AppID: cfg.Rongxing.AppID,
|
||||
PrivateKey: cfg.Rongxing.PrivateKey,
|
||||
Timeout: timeout,
|
||||
}, logger), nil
|
||||
Proxy: cfg.Rongxing.Proxy,
|
||||
}, logger)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -15,6 +17,7 @@ import (
|
||||
"hyapi-server/internal/shared/external_logger"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -32,12 +35,14 @@ type serviceConfig struct {
|
||||
AppID string
|
||||
PrivateKey string
|
||||
Timeout time.Duration
|
||||
Proxy string
|
||||
}
|
||||
|
||||
// RongxingService 戎行数据源服务
|
||||
type RongxingService struct {
|
||||
config serviceConfig
|
||||
logger *external_logger.ExternalServiceLogger
|
||||
client *http.Client
|
||||
|
||||
tokenMu sync.RWMutex
|
||||
cachedToken string
|
||||
@@ -65,12 +70,52 @@ func (r apiResponse) code() string {
|
||||
}
|
||||
|
||||
// NewRongxingService 创建戎行服务实例
|
||||
func NewRongxingService(cfg serviceConfig, logger *external_logger.ExternalServiceLogger) *RongxingService {
|
||||
func NewRongxingService(cfg serviceConfig, logger *external_logger.ExternalServiceLogger) (*RongxingService, error) {
|
||||
if cfg.Timeout <= 0 {
|
||||
cfg.Timeout = defaultRequestTimeout
|
||||
}
|
||||
cfg.BaseURL = strings.TrimRight(strings.TrimSpace(cfg.BaseURL), "/")
|
||||
return &RongxingService{config: cfg, logger: logger}
|
||||
client, err := newHTTPClient(cfg.Timeout, cfg.Proxy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &RongxingService{config: cfg, logger: logger, client: client}, nil
|
||||
}
|
||||
|
||||
// newHTTPClient 构建 HTTP 客户端;proxyURL 支持 socks5/socks5h/http/https,空则直连。
|
||||
func newHTTPClient(timeout time.Duration, proxyURL string) (*http.Client, error) {
|
||||
client := &http.Client{Timeout: timeout}
|
||||
proxyURL = strings.TrimSpace(proxyURL)
|
||||
if proxyURL == "" {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
u, err := url.Parse(proxyURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("解析 proxy 失败: %w", err)
|
||||
}
|
||||
|
||||
switch strings.ToLower(u.Scheme) {
|
||||
case "socks5", "socks5h":
|
||||
dialer, err := proxy.FromURL(u, proxy.Direct)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("创建 SOCKS 代理失败: %w", err)
|
||||
}
|
||||
transport := &http.Transport{}
|
||||
if cd, ok := dialer.(proxy.ContextDialer); ok {
|
||||
transport.DialContext = cd.DialContext
|
||||
} else {
|
||||
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return dialer.Dial(network, addr)
|
||||
}
|
||||
}
|
||||
client.Transport = transport
|
||||
case "http", "https":
|
||||
client.Transport = &http.Transport{Proxy: http.ProxyURL(u)}
|
||||
default:
|
||||
return nil, fmt.Errorf("不支持的 proxy scheme: %s(支持 socks5/socks5h/http/https)", u.Scheme)
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// GetConfig 获取运行时配置
|
||||
@@ -309,8 +354,7 @@ func (s *RongxingService) login(ctx context.Context, transactionID string) (stri
|
||||
}
|
||||
|
||||
func (s *RongxingService) doHTTP(req *http.Request) ([]byte, int, error) {
|
||||
client := &http.Client{Timeout: s.config.Timeout}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := s.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user