diff options
Diffstat (limited to 'roseh.moe.go')
| -rw-r--r-- | roseh.moe.go | 114 |
1 files changed, 91 insertions, 23 deletions
diff --git a/roseh.moe.go b/roseh.moe.go index 81285e7..5afa814 100644 --- a/roseh.moe.go +++ b/roseh.moe.go @@ -18,7 +18,6 @@ import ( "log" "net/http" "os" - "path/filepath" "strings" "sync" "time" @@ -28,10 +27,10 @@ import ( ) var ( - port = flag.Int("port", 42069, "port to listen on") - selfURL = flag.String("self-url", "http://localhost:42069", "base URL of the server") - secretsFile = flag.String("secrets", "secrets", "secrets file") - redirectsDir = flag.String("redirect", "redirect", "directory containing Go package redirects") + port = flag.Int("port", 42069, "port to listen on") + selfURL = flag.String("self-url", "http://localhost:42069", "base URL of the server") + secretsFile = flag.String("secrets", "secrets", "secrets file") + configFile = flag.String("config", "config.ini", "configuration file (no spec or examples, sorry)") serverStartTime = time.Now() ) @@ -59,6 +58,82 @@ func loadSecrets() error { return nil } +type serviceConfiguration struct { + packageRedirects map[string]string + commandRedirects map[string]string +} + +var ( + serviceConfigMu sync.Mutex + serviceConfig *serviceConfiguration + serviceConfigLastModified time.Time +) + +func loadConfig() (*serviceConfiguration, error) { + stat, err := os.Stat(*configFile) + if err != nil { + return nil, err + } + serviceConfigMu.Lock() + oldConfig := serviceConfig + configLastModified := serviceConfigLastModified + serviceConfigMu.Unlock() + newModTime := stat.ModTime() + if !newModTime.After(configLastModified) { + return oldConfig, nil + } + f, err := os.Open(*configFile) + if err != nil { + return nil, err + } + defer f.Close() + config := &serviceConfiguration{ + packageRedirects: make(map[string]string), + commandRedirects: make(map[string]string), + } + scanner := bufio.NewScanner(f) + lineNo := 0 + var currentSection map[string]string + for scanner.Scan() { + lineNo++ + line := strings.TrimSpace(scanner.Text()) + if len(line) == 0 || strings.HasPrefix(line, "//") || strings.HasPrefix(line, "#") { + continue + } + if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { + switch sectionName := strings.TrimSpace(line[1 : len(line)-1]); sectionName { + case "package-redirects": + currentSection = config.packageRedirects + case "command-redirects": + currentSection = config.commandRedirects + default: + currentSection = nil + log.Printf("Warning: %s:%d unknown section", *configFile, lineNo) + } + continue + } + key, val, ok := strings.Cut(line, "=") + if !ok { + log.Printf("Warning: %s:%d invalid key-value pair", *configFile, lineNo) + continue + } + if currentSection == nil { + log.Printf("Warning: %s:%d key-value pair outside section", *configFile, lineNo) + continue + } + key, val = strings.TrimSpace(key), strings.TrimSpace(val) + currentSection[key] = val + } + if err := scanner.Err(); err != nil { + return nil, err + } + serviceConfigMu.Lock() + serviceConfig = config + serviceConfigLastModified = newModTime + serviceConfigMu.Unlock() + return config, nil +} + var ( //go:embed templates/404.html.template notFoundString string @@ -455,25 +530,13 @@ func autosave(w http.ResponseWriter, r *http.Request) { } } -func findRedirect(kind, name string) (string, bool) { - f, err := os.Open(filepath.Join(*redirectsDir, kind)) +func cmd(w http.ResponseWriter, r *http.Request) { + serviceConfig, err := loadConfig() if err != nil { - return "", false - } - defer f.Close() - scanner := bufio.NewScanner(f) - pfx := []byte(name + "\t") - for scanner.Scan() { - line := scanner.Bytes() - if bytes.HasPrefix(line, pfx) { - return string(line[len(pfx):]), true - } + http.Error(w, fmt.Sprintf("load config: %s", err), http.StatusInternalServerError) + return } - return "", false -} - -func cmd(w http.ResponseWriter, r *http.Request) { - source, ok := findRedirect("cmd", r.PathValue("cmd")) + source, ok := serviceConfig.commandRedirects[r.PathValue("cmd")] if !ok { notFound(w, r) return @@ -486,7 +549,12 @@ func cmd(w http.ResponseWriter, r *http.Request) { } func pkg(w http.ResponseWriter, r *http.Request) { - source, ok := findRedirect("pkg", r.PathValue("pkg")) + serviceConfig, err := loadConfig() + if err != nil { + http.Error(w, fmt.Sprintf("load config: %s", err), http.StatusInternalServerError) + return + } + source, ok := serviceConfig.packageRedirects[r.PathValue("pkg")] if !ok { notFound(w, r) return |
