package api import ( "context" "path/filepath" "time" "github.com/gin-gonic/gin" "github.com/router-for-me/CLIProxyAPI/v7/internal/config" "github.com/router-for-me/CLIProxyAPI/v7/internal/logging" "github.com/router-for-me/CLIProxyAPI/v7/internal/pluginhost" "github.com/router-for-me/CLIProxyAPI/v7/sdk/api/handlers" "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth") type serverOptionConfig struct { extraMiddleware []gin.HandlerFunc engineConfigurator func(*gin.Engine) routerConfigurator func(*gin.Engine, *handlers.BaseAPIHandler, *config.Config) requestLoggerFactory func(*config.Config, string) logging.RequestLogger localPassword string keepAliveEnabled bool keepAliveTimeout time.Duration keepAliveOnTimeout func() postAuthHook auth.PostAuthHook postAuthPersistHook auth.PostAuthHook pluginHost *pluginhost.Host configReloadHook func(context.Context, *config.Config) exampleAPIKeySafeMode bool} // ServerOption customises HTTP server construction.type ServerOption func(*serverOptionConfig) func defaultRequestLoggerFactory(cfg *config.Config, configPath string) logging.RequestLogger { configDir := filepath.Dir(configPath) logsDir := logging.ResolveLogDirectory(cfg) logger := logging.NewFileRequestLogger(cfg.RequestLog, logsDir, configDir, cfg.ErrorLogsMaxFiles) logger.SetHomeEnabled(cfg != nil && cfg.Home.Enabled) return logger} func effectiveSDKConfig(cfg *config.Config) *config.SDKConfig { if cfg == nil { return nil } sdkCfg := cfg.SDKConfig sdkCfg.CodexOptimizeMultiAgentV2 = cfg.Codex.OptimizeMultiAgentV2 sdkCfg.CodexOrphanDelegationCompatibility = cfg.Codex.OrphanDelegationCompatibility if cfg.CommercialMode { sdkCfg.RequestLog = false } return &sdkCfg} // WithMiddleware appends additional Gin middleware during server construction.func WithMiddleware(mw ...gin.HandlerFunc) ServerOption { return func(cfg *serverOptionConfig) { cfg.extraMiddleware = append(cfg.extraMiddleware, mw...) }} // WithEngineConfigurator allows callers to mutate the Gin engine prior to middleware setup.func WithEngineConfigurator(fn func(*gin.Engine)) ServerOption { return func(cfg *serverOptionConfig) { cfg.engineConfigurator = fn }} // WithRouterConfigurator appends a callback after default routes are registered.func WithRouterConfigurator(fn func(*gin.Engine, *handlers.BaseAPIHandler, *config.Config)) ServerOption { return func(cfg *serverOptionConfig) { cfg.routerConfigurator = fn }} // WithLocalManagementPassword stores a runtime-only management password accepted for localhost requests.func WithLocalManagementPassword(password string) ServerOption { return func(cfg *serverOptionConfig) { cfg.localPassword = password }} // WithKeepAliveEndpoint enables a keep-alive endpoint with the provided timeout and callback.func WithKeepAliveEndpoint(timeout time.Duration, onTimeout func()) ServerOption { return func(cfg *serverOptionConfig) { if timeout <= 0 || onTimeout == nil { return } cfg.keepAliveEnabled = true cfg.keepAliveTimeout = timeout cfg.keepAliveOnTimeout = onTimeout }} // WithRequestLoggerFactory customises request logger creation.func WithRequestLoggerFactory(factory func(*config.Config, string) logging.RequestLogger) ServerOption { return func(cfg *serverOptionConfig) { cfg.requestLoggerFactory = factory }} // WithPostAuthHook registers a hook to be called after auth record creation.func WithPostAuthHook(hook auth.PostAuthHook) ServerOption { return func(cfg *serverOptionConfig) { cfg.postAuthHook = hook }} // WithPostAuthPersistHook registers a hook to be called after auth persistence.func WithPostAuthPersistHook(hook auth.PostAuthHook) ServerOption { return func(cfg *serverOptionConfig) { cfg.postAuthPersistHook = hook }} // WithPluginHost registers dynamic plugin HTTP adapters with the server.func WithPluginHost(host *pluginhost.Host) ServerOption { return func(cfg *serverOptionConfig) { cfg.pluginHost = host }} // WithConfigReloadHook registers a callback used after management saves config changes.func WithConfigReloadHook(hook func(context.Context, *config.Config)) ServerOption { return func(cfg *serverOptionConfig) { cfg.configReloadHook = hook }} // WithExampleAPIKeySafeMode blocks proxy API endpoints while template API keys remain configured.func WithExampleAPIKeySafeMode() ServerOption { return func(cfg *serverOptionConfig) { cfg.exampleAPIKeySafeMode = true }}
package api
import (
"context"
"path/filepath"
"time"
"github.com/gin-gonic/gin"
"github.com/router-for-me/CLIProxyAPI/v7/internal/config"
"github.com/router-for-me/CLIProxyAPI/v7/internal/logging"
"github.com/router-for-me/CLIProxyAPI/v7/internal/pluginhost"
"github.com/router-for-me/CLIProxyAPI/v7/sdk/api/handlers"
"github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
)
type serverOptionConfig struct {
extraMiddleware []gin.HandlerFunc
engineConfigurator func(*gin.Engine)
routerConfigurator func(*gin.Engine, *handlers.BaseAPIHandler, *config.Config)
requestLoggerFactory func(*config.Config, string) logging.RequestLogger
localPassword string
keepAliveEnabled bool
keepAliveTimeout time.Duration
keepAliveOnTimeout func()
postAuthHook auth.PostAuthHook
postAuthPersistHook auth.PostAuthHook
pluginHost *pluginhost.Host
configReloadHook func(context.Context, *config.Config)
exampleAPIKeySafeMode bool
}
// ServerOption customises HTTP server construction.
type ServerOption func(*serverOptionConfig)
func defaultRequestLoggerFactory(cfg *config.Config, configPath string) logging.RequestLogger {
configDir := filepath.Dir(configPath)
logsDir := logging.ResolveLogDirectory(cfg)
logger := logging.NewFileRequestLogger(cfg.RequestLog, logsDir, configDir, cfg.ErrorLogsMaxFiles)
logger.SetHomeEnabled(cfg != nil && cfg.Home.Enabled)
return logger
}
func effectiveSDKConfig(cfg *config.Config) *config.SDKConfig {
if cfg == nil {
return nil
}
sdkCfg := cfg.SDKConfig
sdkCfg.CodexOptimizeMultiAgentV2 = cfg.Codex.OptimizeMultiAgentV2
sdkCfg.CodexOrphanDelegationCompatibility = cfg.Codex.OrphanDelegationCompatibility
if cfg.CommercialMode {
sdkCfg.RequestLog = false
}
return &sdkCfg
}
// WithMiddleware appends additional Gin middleware during server construction.
func WithMiddleware(mw ...gin.HandlerFunc) ServerOption {
return func(cfg *serverOptionConfig) {
cfg.extraMiddleware = append(cfg.extraMiddleware, mw...)
}
}
// WithEngineConfigurator allows callers to mutate the Gin engine prior to middleware setup.
func WithEngineConfigurator(fn func(*gin.Engine)) ServerOption {
return func(cfg *serverOptionConfig) {
cfg.engineConfigurator = fn
}
}
// WithRouterConfigurator appends a callback after default routes are registered.
func WithRouterConfigurator(fn func(*gin.Engine, *handlers.BaseAPIHandler, *config.Config)) ServerOption {
return func(cfg *serverOptionConfig) {
cfg.routerConfigurator = fn
}
}
// WithLocalManagementPassword stores a runtime-only management password accepted for localhost requests.
func WithLocalManagementPassword(password string) ServerOption {
return func(cfg *serverOptionConfig) {
cfg.localPassword = password
}
}
// WithKeepAliveEndpoint enables a keep-alive endpoint with the provided timeout and callback.
func WithKeepAliveEndpoint(timeout time.Duration, onTimeout func()) ServerOption {
return func(cfg *serverOptionConfig) {
if timeout <= 0 || onTimeout == nil {
return
}
cfg.keepAliveEnabled = true
cfg.keepAliveTimeout = timeout
cfg.keepAliveOnTimeout = onTimeout
}
}
// WithRequestLoggerFactory customises request logger creation.
func WithRequestLoggerFactory(factory func(*config.Config, string) logging.RequestLogger) ServerOption {
return func(cfg *serverOptionConfig) {
cfg.requestLoggerFactory = factory
}
}
// WithPostAuthHook registers a hook to be called after auth record creation.
func WithPostAuthHook(hook auth.PostAuthHook) ServerOption {
return func(cfg *serverOptionConfig) {
cfg.postAuthHook = hook
}
}
// WithPostAuthPersistHook registers a hook to be called after auth persistence.
func WithPostAuthPersistHook(hook auth.PostAuthHook) ServerOption {
return func(cfg *serverOptionConfig) {
cfg.postAuthPersistHook = hook
}
}
// WithPluginHost registers dynamic plugin HTTP adapters with the server.
func WithPluginHost(host *pluginhost.Host) ServerOption {
return func(cfg *serverOptionConfig) {
cfg.pluginHost = host
}
}
// WithConfigReloadHook registers a callback used after management saves config changes.
func WithConfigReloadHook(hook func(context.Context, *config.Config)) ServerOption {
return func(cfg *serverOptionConfig) {
cfg.configReloadHook = hook
}
}
// WithExampleAPIKeySafeMode blocks proxy API endpoints while template API keys remain configured.
func WithExampleAPIKeySafeMode() ServerOption {
return func(cfg *serverOptionConfig) {
cfg.exampleAPIKeySafeMode = true
}
}