package main
import (
"fmt"
"net"
"strconv"
"strings"
)
type Config struct {
Profile, Address, Database, Trace string
Hosts map[string]bool
Connections, Inflight int
}
func loadConfig(get func(string) string) (Config, error) {
c := Config{Profile: get("APP_PROFILE"), Address: get("LISTEN_ADDR"), Database: databaseURL(get("DATABASE_URL")), Trace: get("SQL_TRACE"), Hosts: map[string]bool{}}
if c.Profile == "" {
c.Profile = "production"
}
if c.Profile != "production" && c.Profile != "compat" {
return c, fmt.Errorf("APP_PROFILE must be production or compat")
}
if c.Address == "" {
c.Address = "127.0.0.1:18001"
}
if _, _, err := net.SplitHostPort(c.Address); err != nil {
return c, fmt.Errorf("LISTEN_ADDR must be host:port")
}
for _, host := range strings.Split(get("ALLOWED_HOSTS"), ",") {
host = strings.ToLower(strings.TrimSpace(host))
if host == "" {
continue
}
if strings.ContainsAny(host, "/*@ \t\r\n") {
return c, fmt.Errorf("ALLOWED_HOSTS requires exact hostnames without wildcards")
}
c.Hosts[host] = true
}
if c.Profile == "production" && len(c.Hosts) == 0 {
return c, fmt.Errorf("ALLOWED_HOSTS is required in production")
}
if c.Profile == "production" && c.Trace != "" {
return c, fmt.Errorf("SQL_TRACE is only available in compat profile")
}
for _, item := range []struct {
name string
target *int
def, max int
}{
{"DB_MAX_CONNS", &c.Connections, 8, 128}, {"MAX_INFLIGHT", &c.Inflight, 64, 4096},
} {
*item.target = item.def
if raw := get(item.name); raw != "" {
value, err := strconv.Atoi(raw)
if err != nil || value < 1 || value > item.max {
return c, fmt.Errorf("%s must be between 1 and %d", item.name, item.max)
}
*item.target = value
}
}
return c, nil
}
func databaseURL(value string) string {
if value == "" {
return "dbname=assignment_harness_native"
}
return value
}