package main import ( "errors" "fmt" "os" "path/filepath" "github.com/BurntSushi/toml" ) type Config struct { Listen string `toml:"listen"` Root string `toml:"root"` Hidden bool `toml:"hidden"` Footer string `toml:"footer"` FollowSymlinks bool `toml:"follow_symlinks"` } func loadConfig(path string) (*Config, error) { b, err := os.ReadFile(path) if err != nil { return nil, err } cfg := &Config{} md, err := toml.Decode(string(b), cfg) if err != nil { return nil, fmt.Errorf("%s: %w", path, err) } // follow_symlinks defaults to true: symlinks are served as a window onto // their target, even outside root. if !md.IsDefined("follow_symlinks") { cfg.FollowSymlinks = true } if cfg.Root == "" { return nil, errors.New(`config: "root" is required`) } root, err := filepath.Abs(cfg.Root) if err != nil { return nil, err } if info, err := os.Stat(root); err != nil || !info.IsDir() { return nil, fmt.Errorf("config: root %q is not a directory", root) } cfg.Root = root if cfg.Listen == "" { cfg.Listen = ":8080" } if cfg.Footer == "" { cfg.Footer = "kaidan 1.0" } return cfg, nil }