feat(config): env-based configuration with validation

This commit is contained in:
2026-07-01 16:27:31 +07:00
parent 353f1e9dd3
commit 0d42eb2db0
3 changed files with 100 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
package config
import (
"encoding/base64"
"fmt"
"os"
"strconv"
)
type Config struct {
HTTPAddr string
DatabaseURL string
AuthUser string
AuthPass string
EncKey []byte
SessionSecret []byte
WorkerConcurrency int
}
func Load() (Config, error) {
c := Config{
HTTPAddr: getenv("HTTP_ADDR", ":8080"),
DatabaseURL: os.Getenv("DATABASE_URL"),
AuthUser: os.Getenv("AUTH_USER"),
AuthPass: os.Getenv("AUTH_PASS"),
SessionSecret: []byte(os.Getenv("SESSION_SECRET")),
WorkerConcurrency: 4,
}
if v := os.Getenv("WORKER_CONCURRENCY"); v != "" {
n, err := strconv.Atoi(v)
if err != nil || n < 1 {
return Config{}, fmt.Errorf("WORKER_CONCURRENCY invalid: %q", v)
}
c.WorkerConcurrency = n
}
for k, v := range map[string]string{
"DATABASE_URL": c.DatabaseURL, "AUTH_USER": c.AuthUser,
"AUTH_PASS": c.AuthPass, "SESSION_SECRET": string(c.SessionSecret),
} {
if v == "" {
return Config{}, fmt.Errorf("%s is required", k)
}
}
key, err := base64.StdEncoding.DecodeString(os.Getenv("ENC_KEY"))
if err != nil {
return Config{}, fmt.Errorf("ENC_KEY must be base64: %w", err)
}
if len(key) != 32 {
return Config{}, fmt.Errorf("ENC_KEY must decode to 32 bytes, got %d", len(key))
}
c.EncKey = key
return c, nil
}
func getenv(k, def string) string {
if v := os.Getenv(k); v != "" {
return v
}
return def
}