package main import ( "errors" "io/ioutil" "log" "os" "regexp" "strconv" "strings" "github.com/kballard/go-shellquote" "gopkg.in/yaml.v3" ) type pathConfig struct { // Path to match Path string // Resource to serve Root string Proxy string Command string r *regexp.Regexp cmd []string } type certConfig struct { Cert string Key string } type serverConfig struct { Listen string Certificates []*certConfig Hosts map[string][]*pathConfig hostname string port int } var config = &serverConfig{ hostname: "localhost", port: 1965, } func readconfig(configPath string) error { if configPath == "" { return errors.New("file unspecified") } if _, err := os.Stat(configPath); os.IsNotExist(err) { return errors.New("file not found") } configData, err := ioutil.ReadFile(configPath) if err != nil { return err } err = yaml.Unmarshal(configData, &config) if err != nil { return err } split := strings.Split(config.Listen, ":") if len(split) != 2 { config.hostname = config.Listen config.Listen += ":1965" } else { config.hostname = split[0] config.port, err = strconv.Atoi(split[1]) if err != nil { log.Fatalf("invalid port specified: %s", err) } } for _, paths := range config.Hosts { for _, serve := range paths { if serve.Path == "" { log.Fatal("path must be specified in serve entry") } else if (serve.Root != "" && (serve.Proxy != "" || serve.Command != "")) || (serve.Proxy != "" && (serve.Root != "" || serve.Command != "")) || (serve.Command != "" && (serve.Root != "" || serve.Proxy != "")) { log.Fatal("only one root, reverse proxy or command may specified in a serve entry") } if serve.Path[0] == '^' { serve.r = regexp.MustCompile(serve.Path) } else if serve.Path[len(serve.Path)-1] == '/' { serve.Path = serve.Path[:len(serve.Path)-1] } if serve.Command != "" { serve.cmd, err = shellquote.Split(serve.Command) if err != nil { log.Fatalf("failed to parse command %s: %s", serve.cmd, err) } } } } return nil }