Remove dead code, secure debug endpoints, fix encapsulation

This commit is contained in:
Alexander
2026-04-10 13:07:26 +02:00
parent 4abd4e68dc
commit 17cde479c3
5 changed files with 25 additions and 63 deletions
-1
View File
@@ -18,7 +18,6 @@ cp config.example.yaml config.yaml
Edit `config.yaml`: Edit `config.yaml`:
- `api_keys` — key(s) your clients use to authenticate with the proxy - `api_keys` — key(s) your clients use to authenticate with the proxy
- `claude_credentials` — path to your Claude credentials file - `claude_credentials` — path to your Claude credentials file
- `auth_dir` — optional, directory with additional OAuth credential JSON files
- `claude_binary` — path to `claude` binary (used on startup to capture request fingerprint) - `claude_binary` — path to `claude` binary (used on startup to capture request fingerprint)
## Build and run ## Build and run
+1 -3
View File
@@ -48,9 +48,7 @@ func (p *Pool) MarkFailure(cred *Credential, statusCode int) {
} }
func (p *Pool) MarkSuccess(cred *Credential) { func (p *Pool) MarkSuccess(cred *Credential) {
cred.mu.Lock() cred.ClearCooldown()
defer cred.mu.Unlock()
cred.CooldownUntil = time.Time{}
} }
func (p *Pool) RefreshExpiring(ctx context.Context) { func (p *Pool) RefreshExpiring(ctx context.Context) {
+16 -16
View File
@@ -7,22 +7,15 @@ import (
// Credential represents an Anthropic API credential loaded from a JSON file. // Credential represents an Anthropic API credential loaded from a JSON file.
type Credential struct { type Credential struct {
ID string ID string
Email string Email string
AccessToken string AccessToken string
RefreshToken string RefreshToken string
ExpiresAt time.Time ExpiresAt time.Time
FilePath string FilePath string
CooldownUntil time.Time CooldownUntil time.Time
nextRefreshAfter time.Time nextRefreshAfter time.Time
mu sync.Mutex mu sync.Mutex
}
// IsExpired returns true if the credential's access token has expired.
func (c *Credential) IsExpired() bool {
c.mu.Lock()
defer c.mu.Unlock()
return time.Now().After(c.ExpiresAt)
} }
// IsOnCooldown returns true if the credential is currently on cooldown. // IsOnCooldown returns true if the credential is currently on cooldown.
@@ -39,6 +32,13 @@ func (c *Credential) SetCooldown(duration time.Duration) {
c.CooldownUntil = time.Now().Add(duration) c.CooldownUntil = time.Now().Add(duration)
} }
// ClearCooldown removes any active cooldown on the credential.
func (c *Credential) ClearCooldown() {
c.mu.Lock()
defer c.mu.Unlock()
c.CooldownUntil = time.Time{}
}
// Token returns the current access token. // Token returns the current access token.
func (c *Credential) Token() string { func (c *Credential) Token() string {
c.mu.Lock() c.mu.Lock()
+7 -27
View File
@@ -10,8 +10,6 @@ import (
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/tidwall/gjson"
) )
// SniffedProfile holds everything captured from a real Claude Code request. // SniffedProfile holds everything captured from a real Claude Code request.
@@ -124,18 +122,15 @@ func SniffClaudeCode(claudeBinary string) (*SniffedProfile, error) {
} }
func extractProfile(r *http.Request, body []byte) *SniffedProfile { func extractProfile(r *http.Request, body []byte) *SniffedProfile {
// Capture raw headers preserving original casing and order. // Capture raw headers preserving original casing.
var headers [][2]string var headers [][2]string
for i := 0; i < len(r.Header); i++ { for name, vals := range r.Header {
for name, vals := range r.Header { if skipHeaders[strings.ToLower(name)] {
if skipHeaders[strings.ToLower(name)] { continue
continue }
} for _, v := range vals {
for _, v := range vals { headers = append(headers, [2]string{name, v})
headers = append(headers, [2]string{name, v})
}
} }
break
} }
// Deduplicate and strip subscription-specific betas. // Deduplicate and strip subscription-specific betas.
@@ -170,21 +165,6 @@ func extractProfile(r *http.Request, body []byte) *SniffedProfile {
} }
} }
// Extract the system prompt template from the body (everything except the billing header block).
// The billing header is the first system block starting with "x-anthropic-billing-header:".
systemBlocks := gjson.GetBytes(body, "system")
var templateSystem []string
if systemBlocks.IsArray() {
for _, block := range systemBlocks.Array() {
text := block.Get("text").String()
if strings.HasPrefix(text, "x-anthropic-billing-header:") {
continue
}
templateSystem = append(templateSystem, block.Raw)
}
}
_ = templateSystem // stored in body for now
return &SniffedProfile{ return &SniffedProfile{
Headers: deduped, Headers: deduped,
Body: body, Body: body,
+1 -16
View File
@@ -7,7 +7,6 @@ import (
"net/http" "net/http"
"strings" "strings"
"sync/atomic" "sync/atomic"
"time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@@ -47,7 +46,6 @@ func New(cfg *config.Config, pool *auth.Pool, profile *proxy.SniffedProfile) *Se
engine.POST("/reload", s.handleReload()) engine.POST("/reload", s.handleReload())
engine.POST("/debug/refresh", handleDebugRefresh(pool)) engine.POST("/debug/refresh", handleDebugRefresh(pool))
engine.POST("/debug/shutdown", handleDebugShutdown(s))
engine.GET("/healthz", func(c *gin.Context) { engine.GET("/healthz", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "ok"}) c.JSON(http.StatusOK, gin.H{"status": "ok"})
}) })
@@ -100,19 +98,6 @@ func (s *Server) handleReload() gin.HandlerFunc {
} }
} }
func handleDebugShutdown(s *Server) gin.HandlerFunc {
return func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "shutting down"})
go func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := s.Shutdown(ctx); err != nil {
log.Printf("shutdown error: %v", err)
}
}()
}
}
func handleDebugRefresh(pool *auth.Pool) gin.HandlerFunc { func handleDebugRefresh(pool *auth.Pool) gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
results := pool.RefreshAll(c.Request.Context()) results := pool.RefreshAll(c.Request.Context())
@@ -146,7 +131,7 @@ func corsMiddleware() gin.HandlerFunc {
func (s *Server) authMiddleware() gin.HandlerFunc { func (s *Server) authMiddleware() gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
path := c.Request.URL.Path path := c.Request.URL.Path
if path == "/healthz" || path == "/reload" || strings.HasPrefix(path, "/debug/") { if path == "/healthz" || path == "/reload" {
c.Next() c.Next()
return return
} }