mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-18 12:20:52 +08:00
Implements unified model routing
Migrates the AMP module to a new unified routing system, replacing the fallback handler with a router-based approach. This change introduces a `ModelRoutingWrapper` that handles model extraction, routing decisions, and proxying based on provider availability and model mappings. It provides a more flexible and maintainable routing mechanism by centralizing routing logic. The changes include: - Introducing new `routing` package with core routing logic. - Creating characterization tests to capture existing behavior. - Implementing model extraction and rewriting. - Updating AMP module routes to utilize the new routing wrapper. - Deprecating `FallbackHandler` in favor of the new `ModelRoutingWrapper`.
This commit is contained in:
83
internal/routing/testutil/fake_proxy.go
Normal file
83
internal/routing/testutil/fake_proxy.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
)
|
||||
|
||||
// CloseNotifierRecorder wraps httptest.ResponseRecorder with CloseNotify support.
|
||||
// This is needed because ReverseProxy requires http.CloseNotifier.
|
||||
type CloseNotifierRecorder struct {
|
||||
*httptest.ResponseRecorder
|
||||
closeChan chan bool
|
||||
}
|
||||
|
||||
// NewCloseNotifierRecorder creates a ResponseRecorder that implements CloseNotifier.
|
||||
func NewCloseNotifierRecorder() *CloseNotifierRecorder {
|
||||
return &CloseNotifierRecorder{
|
||||
ResponseRecorder: httptest.NewRecorder(),
|
||||
closeChan: make(chan bool, 1),
|
||||
}
|
||||
}
|
||||
|
||||
// CloseNotify implements http.CloseNotifier.
|
||||
func (c *CloseNotifierRecorder) CloseNotify() <-chan bool {
|
||||
return c.closeChan
|
||||
}
|
||||
|
||||
// FakeProxyRecorder records proxy invocations for testing.
|
||||
type FakeProxyRecorder struct {
|
||||
Called bool
|
||||
CallCount int
|
||||
RequestBody []byte
|
||||
RequestHeaders http.Header
|
||||
ResponseStatus int
|
||||
ResponseBody []byte
|
||||
}
|
||||
|
||||
// NewFakeProxyRecorder creates a new fake proxy recorder.
|
||||
func NewFakeProxyRecorder() *FakeProxyRecorder {
|
||||
return &FakeProxyRecorder{
|
||||
ResponseStatus: http.StatusOK,
|
||||
ResponseBody: []byte(`{"status":"proxied"}`),
|
||||
}
|
||||
}
|
||||
|
||||
// ServeHTTP implements http.Handler to act as a reverse proxy.
|
||||
func (f *FakeProxyRecorder) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
f.Called = true
|
||||
f.CallCount++
|
||||
f.RequestHeaders = r.Header.Clone()
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err == nil {
|
||||
f.RequestBody = body
|
||||
}
|
||||
|
||||
w.WriteHeader(f.ResponseStatus)
|
||||
w.Write(f.ResponseBody)
|
||||
}
|
||||
|
||||
// GetCallCount returns the number of times the proxy was called.
|
||||
func (f *FakeProxyRecorder) GetCallCount() int {
|
||||
return f.CallCount
|
||||
}
|
||||
|
||||
// Reset clears the recorder state.
|
||||
func (f *FakeProxyRecorder) Reset() {
|
||||
f.Called = false
|
||||
f.CallCount = 0
|
||||
f.RequestBody = nil
|
||||
f.RequestHeaders = nil
|
||||
}
|
||||
|
||||
// ToHandler returns the recorder as an http.Handler for use with httptest.
|
||||
func (f *FakeProxyRecorder) ToHandler() http.Handler {
|
||||
return http.HandlerFunc(f.ServeHTTP)
|
||||
}
|
||||
|
||||
// CreateTestServer creates an httptest server with this fake proxy.
|
||||
func (f *FakeProxyRecorder) CreateTestServer() *httptest.Server {
|
||||
return httptest.NewServer(f.ToHandler())
|
||||
}
|
||||
Reference in New Issue
Block a user