chore: initial commit of Go API gateway
Baseline for the Kong replacement on api.riotpiao.com. Brings the working tree under version control for the first time: gateway source, the task board that drives the agent runs, test fixtures, and K8s manifests. Anchor the gateway ignore rule to the repo root. Unanchored, "gateway" also matched the cmd/gateway/ source directory, so the program entrypoint was excluded from every commit. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Load routes and models from config file
|
||||
routes := make(map[string]*Route)
|
||||
models := make(map[string]*ModelUpstream)
|
||||
if configPath, ok := os.LookupEnv("CONFIG_PATH"); ok {
|
||||
loadedRoutes, loadedModels, err := LoadRoutesAndModelsFromFile(configPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
routes = loadedRoutes
|
||||
models = loadedModels
|
||||
}
|
||||
|
||||
return &Config{
|
||||
ListenAddr: listenAddr,
|
||||
ShutdownTimeout: shutdownTimeout,
|
||||
Routes: routes,
|
||||
Models: models,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user