mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-03-09 07:17:32 +00:00
74 lines
2.7 KiB
Go
74 lines
2.7 KiB
Go
// Package client defines the interface and base structure for AI API clients.
|
|
// It provides a common interface that all supported AI service clients must implement,
|
|
// including methods for sending messages, handling streams, and managing authentication.
|
|
package client
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"net/http"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/luispater/CLIProxyAPI/internal/auth"
|
|
"github.com/luispater/CLIProxyAPI/internal/config"
|
|
)
|
|
|
|
// ClientBase provides a common base structure for all AI API clients.
|
|
// It implements shared functionality such as request synchronization, HTTP client management,
|
|
// configuration access, token storage, and quota tracking.
|
|
type ClientBase struct {
|
|
// RequestMutex ensures only one request is processed at a time for quota management.
|
|
RequestMutex *sync.Mutex
|
|
|
|
// httpClient is the HTTP client used for making API requests.
|
|
httpClient *http.Client
|
|
|
|
// cfg holds the application configuration.
|
|
cfg *config.Config
|
|
|
|
// tokenStorage manages authentication tokens for the client.
|
|
tokenStorage auth.TokenStorage
|
|
|
|
// modelQuotaExceeded tracks when models have exceeded their quota.
|
|
// The map key is the model name, and the value is the time when the quota was exceeded.
|
|
modelQuotaExceeded map[string]*time.Time
|
|
}
|
|
|
|
// GetRequestMutex returns the mutex used to synchronize requests for this client.
|
|
// This ensures that only one request is processed at a time for quota management.
|
|
//
|
|
// Returns:
|
|
// - *sync.Mutex: The mutex used for request synchronization
|
|
func (c *ClientBase) GetRequestMutex() *sync.Mutex {
|
|
return c.RequestMutex
|
|
}
|
|
|
|
// AddAPIResponseData adds API response data to the Gin context for logging purposes.
|
|
// This method appends the provided data to any existing response data in the context,
|
|
// or creates a new entry if none exists. It only performs this operation if request
|
|
// logging is enabled in the configuration.
|
|
//
|
|
// Parameters:
|
|
// - ctx: The context for the request
|
|
// - line: The response data to be added
|
|
func (c *ClientBase) AddAPIResponseData(ctx context.Context, line []byte) {
|
|
if c.cfg.RequestLog {
|
|
data := bytes.TrimSpace(bytes.Clone(line))
|
|
if ginContext, ok := ctx.Value("gin").(*gin.Context); len(data) > 0 && ok {
|
|
if apiResponseData, isExist := ginContext.Get("API_RESPONSE"); isExist {
|
|
if byteAPIResponseData, isOk := apiResponseData.([]byte); isOk {
|
|
// Append new data and separator to existing response data
|
|
byteAPIResponseData = append(byteAPIResponseData, data...)
|
|
byteAPIResponseData = append(byteAPIResponseData, []byte("\n\n")...)
|
|
ginContext.Set("API_RESPONSE", byteAPIResponseData)
|
|
}
|
|
} else {
|
|
// Create new response data entry
|
|
ginContext.Set("API_RESPONSE", data)
|
|
}
|
|
}
|
|
}
|
|
}
|