2026-08-19 20:52:13 -07:00
|
|
|
package config
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"os"
|
|
|
|
|
"time"
|
2026-08-26 16:39:30 -07:00
|
|
|
|
|
|
|
|
"forgejo.riotpiao.com/rock/homelab-frontend/internal/serviceadapter"
|
2026-08-19 20:52:13 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Config holds the gateway configuration.
|
|
|
|
|
type Config struct {
|
|
|
|
|
// ListenAddr is the address to listen on for HTTP traffic.
|
|
|
|
|
ListenAddr string
|
|
|
|
|
// ShutdownTimeout is the maximum time to wait for in-flight requests
|
|
|
|
|
// to complete before forcing shutdown.
|
|
|
|
|
ShutdownTimeout time.Duration
|
|
|
|
|
// Routes maps route names to their upstream configuration.
|
|
|
|
|
Routes map[string]*Route
|
|
|
|
|
// Models maps model names to their upstream configuration.
|
|
|
|
|
// Multiple models can point to the same upstream address.
|
|
|
|
|
Models map[string]*ModelUpstream
|
2026-08-26 16:39:30 -07:00
|
|
|
// Adapters holds service adapter definitions for X-Service routing.
|
|
|
|
|
Adapters []*serviceadapter.ServiceAdapter
|
2026-08-31 23:01:59 -07:00
|
|
|
// Auth holds JWT authentication configuration for /v1/* endpoints.
|
|
|
|
|
Auth AuthConfig
|
2026-08-19 20:52:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ModelUpstream holds upstream configuration for a specific model.
|
|
|
|
|
type ModelUpstream struct {
|
|
|
|
|
// Name is the model name clients send (e.g., "reasoning", "ornith:35b").
|
|
|
|
|
Name string
|
|
|
|
|
// Address is the upstream server address (host:port).
|
|
|
|
|
Address string
|
|
|
|
|
// Path is the upstream path for this model (e.g., "/v1/chat/completions").
|
|
|
|
|
Path string
|
2026-08-31 23:01:59 -07:00
|
|
|
// AuthRequired indicates whether this model requires JWT authentication.
|
|
|
|
|
AuthRequired bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AuthConfig holds JWT authentication configuration.
|
|
|
|
|
type AuthConfig struct {
|
|
|
|
|
// Enabled globally enables/disables auth for /v1/* endpoints.
|
|
|
|
|
Enabled bool
|
|
|
|
|
// Issuer is the expected JWT issuer (iss claim).
|
|
|
|
|
Issuer string
|
|
|
|
|
// Audience is the expected JWT audience (aud claim).
|
|
|
|
|
Audience string
|
|
|
|
|
// JWKSURL is the URL to fetch JSON Web Key Set for signature validation.
|
|
|
|
|
JWKSURL string
|
|
|
|
|
// RequiredCapability is the permission required for LLM inference (e.g., "llm:inference").
|
|
|
|
|
RequiredCapability string
|
2026-08-19 20:52:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Route represents a single route and its upstream configuration.
|
|
|
|
|
type Route struct {
|
|
|
|
|
// Name is the route identifier.
|
|
|
|
|
Name string
|
|
|
|
|
// Upstream holds the upstream server configuration.
|
|
|
|
|
Upstream Upstream
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Upstream holds upstream server configuration for a route.
|
|
|
|
|
type Upstream struct {
|
|
|
|
|
// Address is the upstream server address (host:port).
|
|
|
|
|
Address string
|
|
|
|
|
// PathRewrite is an optional path prefix rewrite. Empty string means no rewrite.
|
|
|
|
|
PathRewrite string
|
|
|
|
|
// ConnectTimeout is the maximum time to establish a connection to the upstream.
|
|
|
|
|
ConnectTimeout time.Duration
|
|
|
|
|
// ReadTimeout is the maximum time to read a response from the upstream.
|
|
|
|
|
ReadTimeout time.Duration
|
|
|
|
|
// WriteTimeout is the maximum time to write a request to the upstream.
|
|
|
|
|
WriteTimeout time.Duration
|
|
|
|
|
// MaxBodySize is the maximum request body size in bytes.
|
|
|
|
|
MaxBodySize int64
|
|
|
|
|
// AuthRequired indicates whether this route requires authentication.
|
|
|
|
|
AuthRequired bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LookupModel finds a model by name (case-sensitive, exact match).
|
|
|
|
|
func (c *Config) LookupModel(name string) *ModelUpstream {
|
|
|
|
|
if c == nil || c.Models == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return c.Models[name]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ModelNames returns a sorted list of all known model names.
|
|
|
|
|
func (c *Config) ModelNames() []string {
|
|
|
|
|
if c == nil || c.Models == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
names := make([]string, 0, len(c.Models))
|
|
|
|
|
for name := range c.Models {
|
|
|
|
|
names = append(names, name)
|
|
|
|
|
}
|
|
|
|
|
return names
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load reads configuration from environment variables with defaults.
|
|
|
|
|
func Load() (*Config, error) {
|
|
|
|
|
listenAddr := "127.0.0.1:8080"
|
|
|
|
|
// Allow override via environment variable
|
|
|
|
|
if addr, ok := os.LookupEnv("LISTEN_ADDR"); ok {
|
|
|
|
|
listenAddr = addr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shutdownTimeout := 30 * time.Second
|
|
|
|
|
// Allow override via environment variable
|
|
|
|
|
if timeout, ok := os.LookupEnv("SHUTDOWN_TIMEOUT"); ok {
|
|
|
|
|
d, err := time.ParseDuration(timeout)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("invalid SHUTDOWN_TIMEOUT: %w", err)
|
|
|
|
|
}
|
|
|
|
|
shutdownTimeout = d
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-31 23:01:59 -07:00
|
|
|
// Load routes, models, adapters, and auth from config file
|
2026-08-19 20:52:13 -07:00
|
|
|
routes := make(map[string]*Route)
|
|
|
|
|
models := make(map[string]*ModelUpstream)
|
2026-08-26 16:39:30 -07:00
|
|
|
var adapters []*serviceadapter.ServiceAdapter
|
2026-08-31 23:01:59 -07:00
|
|
|
var authConfig AuthConfig
|
2026-08-19 20:52:13 -07:00
|
|
|
if configPath, ok := os.LookupEnv("CONFIG_PATH"); ok {
|
2026-08-31 23:01:59 -07:00
|
|
|
loadedRoutes, loadedModels, loadedAdapters, loadedAuth, err := LoadRoutesAndModelsFromFile(configPath)
|
2026-08-19 20:52:13 -07:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
routes = loadedRoutes
|
|
|
|
|
models = loadedModels
|
2026-08-26 16:39:30 -07:00
|
|
|
adapters = loadedAdapters
|
2026-08-31 23:01:59 -07:00
|
|
|
authConfig = loadedAuth
|
2026-08-19 20:52:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &Config{
|
|
|
|
|
ListenAddr: listenAddr,
|
|
|
|
|
ShutdownTimeout: shutdownTimeout,
|
|
|
|
|
Routes: routes,
|
|
|
|
|
Models: models,
|
2026-08-26 16:39:30 -07:00
|
|
|
Adapters: adapters,
|
2026-08-31 23:01:59 -07:00
|
|
|
Auth: authConfig,
|
2026-08-19 20:52:13 -07:00
|
|
|
}, nil
|
|
|
|
|
}
|