package main import ( "context" "log" "net/http" "net/http/httputil" "net/url" "os" "os/exec" "os/signal" "syscall" ) func main() { config, oa2, err := LoadConfig() if err != nil { log.Printf("error loading config: %s\n", err.Error()) } upstream, _ := url.Parse(config.Upstream.Addr) rp := httputil.NewSingleHostReverseProxy(upstream) var cmd *exec.Cmd if config.Upstream.Program != "" { ctx, cancel := context.WithCancel(context.Background()) defer cancel() cmd = exec.CommandContext(ctx, config.Upstream.Program, config.Upstream.Args...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr defer func() { if cmd != nil && cmd.Process != nil { log.Println("Terminating child process...") cmd.Process.Signal(syscall.SIGTERM) cmd.Process.Wait() } }() go func() { if err := cmd.Run(); err != nil { log.Printf("Child process exited with error: %v\n", err) } }() } c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { <-c log.Println("Received shutdown signal, cleaning up...") if cmd != nil && cmd.Process != nil { cmd.Process.Signal(syscall.SIGTERM) cmd.Process.Wait() } os.Exit(0) }() oauthStore := NewSessionStore(&config, &oa2) http.Handle("/oauth/callback", oauthStore.CallbackHandler()) http.Handle("/oauth/login", oauthStore.LoginPage()) protectedRoot := false for _, pattern := range config.GuardedPaths { if pattern == "/" { protectedRoot = true } http.Handle(pattern, oauthStore.Protected(rp)) } if !protectedRoot { http.Handle("/", rp) } http.Handle("/favicon.ico", rp) listenAddr, _ := url.Parse(config.ListenURL) listenPort := listenAddr.Port() if listenPort == "" { if listenAddr.Scheme == "https" { listenPort = "443" } else { listenPort = "80" } } log.Printf("Starting server on port %s\n", listenPort) if err := http.ListenAndServe(":"+listenPort, nil); err != nil { log.Printf("Server error: %v\n", err) } }