Files
ai-gateway-go/internal/provider/openai/adapter.go
T
superidou 9501751792 0.10.1: 安全与业务逻辑加固、新品牌与部署加固
三轮审查修复(60+ 项),相对远端 main(b536672)的关键变更:
- 安全: 数据面 SSRF 拨号防护(防 DNS rebinding)/上游凭据剥离/登录防枚举
  与锁定态统一/可信代理(X-Forwarded-For)限流加固/会话版本失效机制/
  撤销即时传播/弱密钥拒绝启动/脱敏字节级重写(保签名契约)
- 业务逻辑: 裸 body 上传 panic/bootstrap 审计管线卡死/定价通配符优先级/
  全局工具可见性/调度器停机补跑/TOTP 挑战令牌消费顺序/熔断探针语义/
  >4MB 响应 token 计量/管理员重置密码作废会话 等
- 前端: 新 logo(语枢 AI 网关主题)/Provider 凭据异常警示/删除入口/
  后端错误消息透传/localStorage 敏感数据收敛
- 部署: CREDENTIAL_MASTER_KEY 持久化与弱值拒绝/Provider DELETE 接口/
  nginx 安全头/worker 内存限制
- 新增迁移 000029(key_hash 索引)/000030(usage_daily 币种维度)
2026-08-13 10:50:51 +08:00

59 lines
1.5 KiB
Go

package openai
import (
"net/http"
"net/url"
"strings"
"aigateway.local/core/internal/provider"
)
type Adapter struct {
target *url.URL
apiKey string
}
func New(baseURL, apiKey string) (*Adapter, error) {
target, err := url.Parse(baseURL)
if err != nil {
return nil, err
}
return &Adapter{target: target, apiKey: apiKey}, nil
}
func (a *Adapter) Name() string { return "openai-compatible" }
func (a *Adapter) Target() *url.URL {
copy := *a.target
return &copy
}
func (a *Adapter) Capabilities() []provider.Capability {
return []provider.Capability{
provider.CapabilityChat,
provider.CapabilityResponses,
provider.CapabilityEmbeddings,
provider.CapabilityMessages,
provider.CapabilityModels,
}
}
func (a *Adapter) Prepare(request *http.Request) {
// 无条件剥离客户端凭据:客户端携带的网关 API Key 绝不能转发给上游。
// 只有配置了 Provider 自身凭据时才注入 Authorization。
request.Header.Del("Authorization")
request.Header.Del("X-Gateway-API-Key")
request.Header.Del("X-Gateway-Provider")
basePath := strings.TrimRight(a.target.Path, "/")
duplicatedVersionPrefix := basePath + "/v1/"
if strings.HasSuffix(basePath, "/v1") && strings.HasPrefix(request.URL.Path, duplicatedVersionPrefix) {
request.URL.Path = basePath + "/" + strings.TrimPrefix(request.URL.Path, duplicatedVersionPrefix)
request.URL.RawPath = ""
}
if a.apiKey != "" {
request.Header.Set("Authorization", "Bearer "+a.apiKey)
}
}
var _ provider.Adapter = (*Adapter)(nil)