twins-upstream/config.go

132 lines
2.6 KiB
Go
Raw Normal View History

2020-10-29 21:35:48 +01:00
package main
import (
"crypto/tls"
2020-10-29 21:35:48 +01:00
"errors"
"io/ioutil"
2020-10-30 01:17:23 +01:00
"log"
2020-10-29 21:35:48 +01:00
"os"
"regexp"
"strconv"
"strings"
2020-10-29 21:35:48 +01:00
"github.com/kballard/go-shellquote"
2020-10-29 21:35:48 +01:00
"gopkg.in/yaml.v3"
)
type pathConfig struct {
// Path to match
Path string
2020-10-30 01:17:23 +01:00
// Resource to serve
Root string
Proxy string
Command string
2020-10-29 21:35:48 +01:00
// Request input
Input string
// Request sensitive input
SensitiveInput string
2020-10-31 02:31:13 +01:00
// List directory entries
ListDirectory bool
r *regexp.Regexp
cmd []string
2020-10-29 21:35:48 +01:00
}
type hostConfig struct {
Cert string
Key string
Paths []*pathConfig
cert *tls.Certificate
}
2020-10-29 21:35:48 +01:00
type serverConfig struct {
Listen string
Hosts map[string]*hostConfig
hostname string
port int
2020-10-29 21:35:48 +01:00
}
var config *serverConfig
2020-10-29 21:35:48 +01:00
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
}
var newConfig *serverConfig
err = yaml.Unmarshal(configData, &newConfig)
2020-10-29 21:35:48 +01:00
if err != nil {
return err
}
config = newConfig
if config.Listen == "" {
log.Fatal("listen address must be specified")
}
2020-10-29 21:35:48 +01:00
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)
2020-10-29 21:35:48 +01:00
}
}
for _, host := range config.Hosts {
if host.Cert == "" || host.Key == "" {
log.Fatal("a certificate must be specified for each domain (gemini requires TLS for all connections)")
}
cert, err := tls.LoadX509KeyPair(host.Cert, host.Key)
if err != nil {
log.Fatalf("failed to load certificate: %s", err)
}
host.cert = &cert
for _, serve := range host.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)
}
}
}
2020-10-29 21:35:48 +01:00
}
return nil
}