5759c1862e
M0-M7 已完成:核心网关(身份/RBAC/TOTP/OIDC/SAML/Provider/配额/路由/内容策略/审计/定价)+ 资源市场(MCP/Skills/数字员工)。 含 22 个 PostgreSQL 迁移、管理端/门户端前端源码、OpenAPI 契约、部署 compose。 Co-Authored-By: Claude <noreply@anthropic.com>
77 lines
1.8 KiB
Go
77 lines
1.8 KiB
Go
package gateway
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
type ModelRouteQuery struct {
|
|
ProviderCode string
|
|
Model string
|
|
Endpoint string
|
|
APIKeyID string
|
|
TenantID string
|
|
Seed string
|
|
}
|
|
|
|
type ModelRouteResult struct {
|
|
ResolvedAdapter
|
|
TargetModel string
|
|
Matched bool
|
|
Known bool
|
|
}
|
|
|
|
type ModelRouteResolver interface {
|
|
ModelRoutingEnabled() bool
|
|
ResolveModelRoute(ModelRouteQuery) (ModelRouteResult, error)
|
|
}
|
|
|
|
type modelRequest struct {
|
|
body map[string]json.RawMessage
|
|
model string
|
|
}
|
|
|
|
func readModelRequest(request *http.Request, maxBody int64) (modelRequest, error) {
|
|
if request.Body == nil || request.Method == http.MethodGet {
|
|
return modelRequest{}, nil
|
|
}
|
|
body, err := io.ReadAll(io.LimitReader(request.Body, maxBody+1))
|
|
if err != nil {
|
|
return modelRequest{}, err
|
|
}
|
|
_ = request.Body.Close()
|
|
if int64(len(body)) > maxBody {
|
|
return modelRequest{}, errRequestBodyTooLarge
|
|
}
|
|
restoreRequestBody(request, body)
|
|
var payload map[string]json.RawMessage
|
|
if json.Unmarshal(body, &payload) != nil {
|
|
return modelRequest{}, nil
|
|
}
|
|
var model string
|
|
_ = json.Unmarshal(payload["model"], &model)
|
|
return modelRequest{body: payload, model: model}, nil
|
|
}
|
|
|
|
func (m modelRequest) rewrite(request *http.Request, target string) error {
|
|
if len(m.body) == 0 || target == "" || target == m.model {
|
|
return nil
|
|
}
|
|
encodedModel, _ := json.Marshal(target)
|
|
m.body["model"] = encodedModel
|
|
body, err := json.Marshal(m.body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
restoreRequestBody(request, body)
|
|
return nil
|
|
}
|
|
|
|
func restoreRequestBody(request *http.Request, body []byte) {
|
|
request.Body = io.NopCloser(bytes.NewReader(body))
|
|
request.ContentLength = int64(len(body))
|
|
request.GetBody = func() (io.ReadCloser, error) { return io.NopCloser(bytes.NewReader(body)), nil }
|
|
}
|