fierj
PublicTiny personal git forge
0d345980a75f73bd46166048167334ca8e6b5bb3
diff --git a/config.go b/config.go
new file mode 100644
index 0000000..188d3fb
--- /dev/null
+++ b/config.go
@@ -0,0 +1,49 @@
+package main
+
+import (
+ "encoding/json"
+ "log/slog"
+ "os"
+ "reflect"
+)
+
+const envPrefix = "FIERJ_"
+
+type Config struct {
+ Addr string `json:"addr" env:"ADDR"`
+}
+
+func LoadConfig(path string) Config {
+ // default config
+ cfg := Config{
+ Addr: ":8080",
+ }
+
+ // read file, log read/unmarshal errors, if any
+ b, err := os.ReadFile(path)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ slog.Error("failed to read config file", "error", err)
+ }
+ } else {
+ if err := json.Unmarshal(b, &cfg); err != nil {
+ slog.Error("failed to unmarshal config file", "error", err)
+ }
+ }
+
+ // scan fields and override with env vars (FIERJ_<env>) if present
+ v := reflect.ValueOf(&cfg).Elem()
+ slog.Info("scanning config fields for env overrides", "x", v)
+ for i := 0; i < v.NumField(); i++ {
+ field := v.Type().Field(i)
+ envTag := field.Tag.Get("env")
+ slog.Info("checking field for env override", "field", field, "env", envTag)
+ if envTag == "" {
+ continue
+ }
+ if envVal, ok := os.LookupEnv(envPrefix + envTag); ok {
+ v.Field(i).SetString(envVal)
+ }
+ }
+ return cfg
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..d0ba93a
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,3 @@
+module github.com/zserge/fierj
+
+go 1.26.3
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..a4e47c9
--- /dev/null
+++ b/main.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+ "log/slog"
+ "net/http"
+ "os"
+)
+
+func main() {
+ cfgPath := "config.json"
+ if len(os.Args) > 1 {
+ cfgPath = os.Args[1]
+ }
+ cfg := LoadConfig(cfgPath)
+
+ slog.Info("Starting server", "addr", cfg.Addr)
+ if err := http.ListenAndServe(cfg.Addr, nil); err != nil {
+ slog.Error("Server exited", "error", err)
+ }
+}