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 } }