84 lines
3.3 KiB
Go
84 lines
3.3 KiB
Go
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
const defaultEnvPrefix = "GO_OMNI_"
|
|
|
|
// ServerEnvAliases returns the documented short names for Config fields.
|
|
// field is the JSON path of Config in a project (usually "server"), or ""
|
|
// for Config itself. Canonical names win over aliases. Both use the same
|
|
// EnvOptions.Empty/Lookup and typed parser; collections use JSON syntax.
|
|
func ServerEnvAliases(prefix, field string) map[string][]string {
|
|
root := prefix
|
|
if field != "" {
|
|
for _, part := range strings.Split(field, ".") {
|
|
root += envName(part) + "_"
|
|
}
|
|
}
|
|
names := map[string]string{
|
|
"ADDRESS": "HTTP_ADDR", "TRANSPORT": "TRANSPORT", "TLS_CERT_FILE": "TLS_CERT_FILE", "TLS_KEY_FILE": "TLS_KEY_FILE",
|
|
"REQUEST_ID_HEADER": "REQUEST_ID_HEADER", "ENABLE_LOGGER": "ENABLE_LOGGER", "SLOW_REQUEST_THRESHOLD": "SLOW_REQUEST_THRESHOLD",
|
|
"TRUSTED_PROXIES": "TRUSTED_PROXIES", "SHUTDOWN_TIMEOUT": "SHUTDOWN_TIMEOUT",
|
|
"LOG_LEVEL": "LOG_LEVEL", "LOG_FORMAT": "LOG_FORMAT", "LOG_OUTPUT": "LOG_OUTPUT", "LOG_FILE": "LOG_FILE", "LOG_SERVICE": "SERVICE", "LOG_ENVIRONMENT": "ENVIRONMENT", "LOG_ADD_SOURCE": "LOG_ADD_SOURCE",
|
|
"HTTP_READ_HEADER_TIMEOUT": "HTTP_READ_HEADER_TIMEOUT", "HTTP_READ_TIMEOUT": "HTTP_READ_TIMEOUT", "HTTP_WRITE_TIMEOUT": "HTTP_WRITE_TIMEOUT", "HTTP_IDLE_TIMEOUT": "HTTP_IDLE_TIMEOUT", "HTTP_MAX_HEADER_BYTES": "HTTP_MAX_HEADER_BYTES",
|
|
"LIFECYCLE_STOP_TIMEOUT": "LIFECYCLE_STOP_TIMEOUT", "LIFECYCLE_DRAIN_TIMEOUT": "LIFECYCLE_DRAIN_TIMEOUT", "LIFECYCLE_CANCEL_TIMEOUT": "LIFECYCLE_CANCEL_TIMEOUT",
|
|
}
|
|
for _, endpoint := range []string{"LIVENESS", "READINESS", "OPENAPI"} {
|
|
for _, part := range []string{"ENABLED", "PATH", "RESPONSE_MODE"} {
|
|
if endpoint == "OPENAPI" && part == "RESPONSE_MODE" {
|
|
continue
|
|
}
|
|
name := "ENDPOINTS_" + endpoint + "_" + part
|
|
names[name] = name
|
|
}
|
|
}
|
|
aliases := map[string][]string{}
|
|
for key, alias := range names {
|
|
if root+key != prefix+alias {
|
|
aliases[root+key] = []string{prefix + alias}
|
|
}
|
|
}
|
|
return aliases
|
|
}
|
|
|
|
// LoadFromEnv loads defaults using the legacy short-name conventions.
|
|
func LoadFromEnv(prefix string) (Config, error) { return ApplyEnv(Default(), prefix) }
|
|
|
|
// ApplyEnv retains legacy whitespace trimming, ignored empty variables and
|
|
// comma-separated TRUSTED_PROXIES. New projects should use OverlayEnv with
|
|
// ServerEnvAliases for one explicit empty-value policy across the whole config.
|
|
func ApplyEnv(defaults Config, prefix string) (Config, error) {
|
|
prefix = strings.TrimSpace(prefix)
|
|
if prefix == "" {
|
|
prefix = defaultEnvPrefix
|
|
}
|
|
lookup := func(key string) (string, bool) {
|
|
raw, ok := os.LookupEnv(key)
|
|
raw = strings.TrimSpace(raw)
|
|
if ok && raw != "" && key == prefix+"TRUSTED_PROXIES" && !strings.HasPrefix(raw, "[") {
|
|
values := strings.Split(raw, ",")
|
|
for i := range values {
|
|
values[i] = strings.TrimSpace(values[i])
|
|
}
|
|
data, _ := json.Marshal(values)
|
|
raw = string(data)
|
|
}
|
|
return raw, ok
|
|
}
|
|
defaults.Errors = defaults.Errors.Clone()
|
|
defaults.TrustedProxies = append([]string(nil), defaults.TrustedProxies...)
|
|
defaults.Log.RedactKeys = append([]string(nil), defaults.Log.RedactKeys...)
|
|
cfg, err := OverlayEnv(defaults, EnvOptions{Prefix: prefix, Empty: "ignore", Lookup: lookup, Aliases: ServerEnvAliases(prefix, "")})
|
|
if err != nil {
|
|
return Config{}, err
|
|
}
|
|
if err = cfg.Validate(); err != nil {
|
|
return Config{}, err
|
|
}
|
|
return cfg, nil
|
|
}
|